fix(scheduler): relax self-referential pod affinity for gang bootstrap - #4
Open
pfernandes21 wants to merge 2 commits into
Open
fix(scheduler): relax self-referential pod affinity for gang bootstrap#4pfernandes21 wants to merge 2 commits into
pfernandes21 wants to merge 2 commits into
Conversation
Volcano evaluates inter-pod affinity per task against already-placed pods, ignoring not-yet-scheduled members of the same gang. A gang whose required pod affinity can only be satisfied by its own members (e.g. EFA training workers co-located within a capacity-reservation topology) deadlocks: its first member matches no placed pod on any node, InterPodAffinity returns UnschedulableAndUnresolvable, and the whole podgroup is stuck. Let the bootstrap member through only when (a) the failure is the affinity (not anti-affinity) rule, (b) it belongs to a gang of >1 members, (c) no member is placed yet, and (d) every required term is satisfiable by a sibling. Subsequent members are still subject to the standard filter and land in the bootstrap member's topology domain, keeping the gang co-located. Refs volcano-sh#3845
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
The agentscheduler embeds PredicatesPlugin and drives it without a volcano Session, so threading the Session through Predicate broke its build. Inject the gang-bootstrap check via a per-session closure field instead; it is nil (and the relaxation skipped) for schedulers without a volcano Session.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What type of PR is this?
/kind bug
What this PR does / why we need it:
Volcano evaluates inter-pod affinity per task against pods that are already placed, ignoring not-yet-scheduled members of the same gang (podgroup). A gang whose required pod affinity can only be satisfied by its own members therefore deadlocks at the bootstrap step:
InterPodAffinity.FilterreturnsUnschedulableAndUnresolvable(ErrReasonAffinityRulesNotMatch).util.ShouldAborttreats that as a hard failure, so the whole podgroup is wedged and never schedules.This is exactly the shape of our multi-node EFA training jobs, where every worker carries a required pod affinity that co-locates workers within a shared
karpenter.k8s.aws/capacity-reservation-idtopology. kube-scheduler has a built-in escape hatch for "the first pod in a self-affine series" (satisfyPodAffinity), but it only fires when no pod anywhere in the cluster matches the selector. When ambient pods match the selector (e.g. otherrole=workerpods, which is the live behavior today becausematchLabelKeysis dropped by the older FlytePropeller), that escape hatch no longer fires and the gang deadlocks.This PR adds a narrow, gang-aware relaxation in the predicates plugin. When the
InterPodAffinityfilter fails on the affinity rule (not anti-affinity), we let the bootstrap member through iff:Because Volcano allocates a gang's members sequentially and updates the node snapshot after each allocation, every subsequent member is still subject to the standard filter and lands in the bootstrap member's topology domain — so the gang stays co-located. Anti-affinity failures are never relaxed (they return plain
Unschedulable, notUnschedulableAndUnresolvable, and the reason check excludes them).Which issue(s) this PR fixes:
Refs volcano-sh#3845
Special notes for your reviewer:
filterStatus.Reason == interpodaffinity.ErrReasonAffinityRulesNotMatch, so only the pod-affinity rule is ever relaxed; pod anti-affinity and existing-pod anti-affinity are untouched.matchLabelKeys(k8s 1.29+) is honored when computing whether a sibling satisfies a term, mirroring how kube-scheduler expands aPodAffinityTermin PreFilter. This keeps the relaxation correct oncematchLabelKeysis properly propagated.TestGangPodAffinityBootstrapcovers two scenarios:isolated-gang-bootstraps: an isolated self-affine gang (also covered by kube-scheduler's own escape hatch) still schedules both members into the shared topology domain.gang-bootstraps-past-ambient-match: an ambient running pod matches the gang's selector in a different topology domain, defeating kube-scheduler's escape hatch. This reproduces the real deadlock; with the patch the gang bootstraps and co-locates in the reserved domain. Verified that neutralizing the relaxation makes only this case fail, confirming the fix is necessary.go test ./pkg/scheduler/plugins/predicates/,go vet, andgofmtare all clean; the scheduler binary builds.Does this PR introduce a user-facing change?
Link to Devin session: https://app.devin.ai/sessions/109a77f123df47ef8618364848dba0be
Requested by: @pfernandes21