diff --git a/nomad/core_sched.go b/nomad/core_sched.go index 8abd1c5407d8..c390d7dc11d9 100644 --- a/nomad/core_sched.go +++ b/nomad/core_sched.go @@ -297,16 +297,18 @@ func (c *CoreScheduler) gcEval(eval *structs.Evaluation, thresholdIndex uint64, } // If the eval is from a running "batch" job we don't want to garbage - // collect its allocations. If there is a long running batch job and its - // terminal allocations get GC'd the scheduler would re-run the - // allocations. + // collect its most current allocations. If there is a long running batch job and its + // terminal allocations get GC'd the scheduler would re-run the allocations. However, + // we do want to GC old Evals and Allocs if there are newer ones due to an update. if eval.Type == structs.JobTypeBatch { // Check if the job is running - // Can collect if: - // Job doesn't exist - // Job is Stopped and dead - // allowBatch and the job is dead + // Can collect if either holds: + // - Job doesn't exist + // - Job is Stopped and dead + // - allowBatch and the job is dead + // + // If we cannot collect outright, check if a partial GC may occur collect := false if job == nil { collect = true @@ -318,12 +320,9 @@ func (c *CoreScheduler) gcEval(eval *structs.Evaluation, thresholdIndex uint64, collect = true } - // We don't want to gc anything related to a job which is not dead - // If the batch job doesn't exist we can GC it regardless of allowBatch if !collect { - // Find allocs associated with older (based on createindex) and GC them if terminal - oldAllocs := olderVersionTerminalAllocs(allocs, job) - return false, oldAllocs, nil + oldAllocs, gcEval := olderVersionTerminalAllocs(allocs, job, thresholdIndex) + return gcEval, oldAllocs, nil } } @@ -344,16 +343,20 @@ func (c *CoreScheduler) gcEval(eval *structs.Evaluation, thresholdIndex uint64, return gcEval, gcAllocIDs, nil } -// olderVersionTerminalAllocs returns terminal allocations whose job create index -// is older than the job's create index -func olderVersionTerminalAllocs(allocs []*structs.Allocation, job *structs.Job) []string { +// olderVersionTerminalAllocs returns a tuplie ([]string, bool). The first element is the list of +// terminal allocations which may be garbage collected for batch jobs. The second element indicates +// whether or not the allocation itself may be garbage collected. +func olderVersionTerminalAllocs(allocs []*structs.Allocation, job *structs.Job, thresholdIndex uint64) ([]string, bool) { var ret []string + var mayGCEval = true for _, alloc := range allocs { - if alloc.Job != nil && alloc.Job.CreateIndex < job.CreateIndex && alloc.TerminalStatus() { + if alloc.CreateIndex < job.JobModifyIndex && alloc.ModifyIndex < thresholdIndex && alloc.TerminalStatus() { ret = append(ret, alloc.ID) + } else { + mayGCEval = false } } - return ret + return ret, mayGCEval } // evalReap contacts the leader and issues a reap on the passed evals and @@ -1121,4 +1124,4 @@ func (c *CoreScheduler) getOldestAllocationIndex() (uint64, error) { } } return 0, nil -} +} \ No newline at end of file diff --git a/version/version.go b/version/version.go index 3374f0362067..e7edec1f2917 100644 --- a/version/version.go +++ b/version/version.go @@ -11,7 +11,7 @@ var ( GitDescribe string // The main version number that is being run at the moment. - Version = "1.4.2" + Version = "1.4.2.updated-gc" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release