backport of commit b46b41a2e99ad85d18189b44836f6436a2149a8b (#18855)

Co-authored-by: Daniel Bennett <dbennett@hashicorp.com>
This commit is contained in:
hc-github-team-nomad-core 2023-10-24 11:51:04 -05:00 committed by GitHub
parent c3546e80a1
commit 497d91f4bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 36 additions and 2 deletions

3
.changelog/18838.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:bug
scheduler (Enterprise): auto-unblock evals with associated quotas when node resources are freed up
```

View File

@ -567,10 +567,13 @@ func (b *BlockedEvals) unblock(computedClass, quota string, index uint64) {
// never saw a node with the given computed class and thus needs to be
// unblocked for correctness.
for id, wrapped := range b.captured {
if quota != "" && wrapped.eval.QuotaLimitReached != quota {
if quota != "" &&
wrapped.eval.QuotaLimitReached != "" &&
wrapped.eval.QuotaLimitReached != quota {
// We are unblocking based on quota and this eval doesn't match
continue
} else if elig, ok := wrapped.eval.ClassEligibility[computedClass]; ok && !elig {
}
if elig, ok := wrapped.eval.ClassEligibility[computedClass]; ok && !elig {
// Can skip because the eval has explicitly marked the node class
// as ineligible.
continue

View File

@ -13,6 +13,7 @@ import (
"github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/hashicorp/nomad/testutil"
"github.com/shoenig/test/must"
"github.com/stretchr/testify/require"
)
@ -322,6 +323,33 @@ func TestBlockedEvals_UnblockEligible_Quota(t *testing.T) {
requireBlockedEvalsEnqueued(t, blocked, broker, 1)
}
// The quota here is incidental. The eval is blocked due to something else,
// e.g. cpu exhausted, but there happens to also be a quota on the namespace.
func TestBlockedEvals_UnblockEligible_IncidentalQuota(t *testing.T) {
ci.Parallel(t)
blocked, broker := testBlockedEvals(t)
e := mock.BlockedEval()
e.Status = structs.EvalStatusBlocked
e.QuotaLimitReached = "" // explicitly not blocked due to quota limit
blocked.Block(e)
// Verify block caused the eval to be tracked.
blockedStats := blocked.Stats()
must.Eq(t, 1, blockedStats.TotalBlocked)
must.MapLen(t, 1, blockedStats.BlockedResources.ByJob)
// but not due to quota.
must.Eq(t, 0, blockedStats.TotalQuotaLimit)
// When unblocking, the quota name from the alloc is passed in,
// regardless of the cause of the initial blockage.
// Since the initial block in this test was due to something else,
// it should be unblocked without regard to quota.
blocked.UnblockQuota("foo", 1000)
requireBlockedEvalsEnqueued(t, blocked, broker, 1)
}
func TestBlockedEvals_UnblockIneligible_Quota(t *testing.T) {
ci.Parallel(t)
require := require.New(t)