Skip to content

fix(operator): release the batch slot of a node whose stage timed out - #936

Draft
tdnvidia wants to merge 1 commit into
NVIDIA:mainfrom
tdnvidia:tdaugherty/operator-release-terminal-batch-slot
Draft

tdnvidia wants to merge 1 commit into
NVIDIA:mainfrom
tdnvidia:tdaugherty/operator-release-terminal-batch-slot

Conversation

@tdnvidia

@tdnvidia tdnvidia commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

Description

Release a node's batch slot after its package stage times out, so waiting nodes can continue. Previously, a timed-out stage could hold its slot until manual intervention; if every node in a batch failed, the rollout stalled.

  • Release requires a matching Job with a terminal Failed condition, or FailureTarget lasting more than five minutes, and an erroring entry for that stage. Jobs still running or retrying for the same NodeWright keep the node's slot.
  • Released nodes retain their package failure state and count toward deployment-policy failure accounting, even when taints block them. Rollout progress remains subject to failureThreshold and safetyLimit.
  • Failed nodes remain excluded until a reset, package edit, or failed-Job TTL clears the timeout. Once eligible, they retry after waiting nodes, including when the strategy has no new batch left to form.

Closes #869. Also addresses the starvation described in #890; that issue remains open for confirmation.

How this was verified

  • make fmt vet lint unit-tests from operator/: all 15 suites passed; lint reported no issues. Regression coverage includes slot release, active retries, failure accounting, recovery, and repeated reconciles.
  • Integration checks with real Kubernetes Job and node lifecycle controllers and KWOK-simulated nodes passed for terminal failures, unreachable nodes, concurrent packages, failure-threshold stops, and re-entry. A 300-node scenario with 30 failures confirmed the remaining rollout continued.
  • CI on 2e819933 passed all four Chainsaw e2e pools on Kubernetes 1.34.11, 1.35.8, 1.36.4, and 1.37.0, plus deployment-policy, CLI, Helm, operator-agent, and migration tests on 1.37.0. Chainsaw suites were not run locally.

AI assistance: Claude Code drafted the implementation, tests, and docs. I reviewed them and can defend every line. Codex edited this description.

Checklist

  • I am familiar with the Contributing Guidelines.
  • This PR closes an issue that is assigned to me, or it is a trivial change that needs none.
  • My commits are signed off per the DCO and cryptographically signed: git commit -s -S.
  • If this changes code, I ran the relevant suite locally and recorded the result above.
  • New or existing tests cover these changes.
  • The documentation is up to date with these changes.
  • If an AI tool wrote a meaningful part of this change, I have said so above, and I can explain and defend every line of it.

@github-actions github-actions Bot added doc Documentation change (PR path label; doc issues use the Documentation type) component/operator Skyhook operator (controller-manager) labels Oct 31, 2026
@github-actions

Copy link
Copy Markdown
Contributor

@tdnvidia
tdnvidia force-pushed the tdaugherty/operator-release-terminal-batch-slot branch from d9732bb to bb08a91 Compare October 31, 2026 05:47
A node entered NodePriority when picked and left only on Complete, so a
node whose stage timed out held its interruption-budget slot until someone
deleted or reset it. With a budget of N and k such nodes the rollout ran at
N minus k, and a batch whose every node died never formed another. NVIDIA#870
widened this: HoldsBatchSlot treats an erroring entry as active so a
retrying reboot keeps its slot, and with no check for a Job that has given
up, the lifecycle taints stopped releasing a dead node by accident too.

The finished-Job sweep now records the nodes whose stage has timed out and
the picker parks them before selection: it drops their NodePriority entry
and refuses to re-admit them while the Job stands. A stage has timed out
when the Job has given up and the entry sits at (stage, erroring) for the
current spec, the pair the rerun predicate already keeps in place, shared
through stageTimedOut. A Job gives up by going terminally Failed, or by
sitting at FailureTarget past the grace window on an unreachable node,
where its pod can never terminate and Failed never arrives. A node is
released only once no other package Job on it is running or retrying, so
the release never admits the next node beside work still in flight.

The release keys on the Job, not on the erroring state, so a retrying
attempt keeps its slot as NVIDIA#870 intended. Erroring stays, and a blocked node
with a package entry at erroring now counts as a failed node for the batch,
so a released dead node that the lifecycle taints block still reaches
failureThreshold and safetyLimit. interruptPending makes a returning node
re-run its interrupt. Parking refuses re-admission while the marker stands,
so the slot is released once and NodeOrderOffset moves once, not every
pass.

A released node counts as processed for the strategy, so once every node
is complete or failed the compartment forms no new batch and the node would
wait for a reset forever. The picker now retries such nodes on their own at
the strategy's initial batch size once their Job is gone, which keeps the
documented re-run after JOB_TTL_FAILED. A long TTL keeps the node parked
until someone resets or reruns it.

Closes NVIDIA#869
Refs NVIDIA#890

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Taylor Daugherty <tdaugherty@nvidia.com>
@tdnvidia
tdnvidia force-pushed the tdaugherty/operator-release-terminal-batch-slot branch from bb08a91 to 2e81993 Compare October 31, 2026 14:26

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component/operator Skyhook operator (controller-manager) doc Documentation change (PR path label; doc issues use the Documentation type)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

operator: a node that never returns from an interrupt keeps its batch slot until its Node object is deleted

1 participant