feat(executor): fall back to non-interruptible capacity on the last attempt - #7911
Open
chris-thomas-dev wants to merge 2 commits into
Open
Conversation
… is unset The executor read interruptibility only from TaskAction.Spec.Interruptible, which is populated from the run-level RunSpec. Interruptible set at the TaskEnvironment, @env.task, or task.override() level serializes into the embedded TaskTemplate metadata but never reached pod scheduling, so the plugins.k8s interruptible node affinity and tolerations were not applied. The task template's metadata now decides interruptibility whenever the run-level flag is unset; an explicit run-level value still wins. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Chris Thomas <chris.john.thomas@gmail.com>
…ttempt Interruptible tasks ran on interruptible capacity for every attempt, so a task whose nodes kept being reclaimed could burn its whole retry budget without ever landing on capacity that survives. The new executor `interruptibleFailureThreshold` sets the attempt count at which a task falls back to non-interruptible capacity. It defaults to -1, which moves only the final attempt; a value above the maximum disables the fallback, and zero is rejected at startup. Either the task's own retries or the system-failure budget can trip it, and at least one attempt always runs on interruptible capacity. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Chris Thomas <chris.john.thomas@gmail.com>
3 tasks
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.
Why are the changes needed?
The Interruptible tasks docs describe a spot-to-on-demand fallback: the final attempt of an interruptible task runs on an on-demand instance, so a task whose nodes keep being reclaimed cannot burn its whole retry budget without ever landing on capacity that survives. The v2 executor schedules interruptible tasks on interruptible capacity for every attempt, so that fallback never happens. Requested in the review of #7885.
Note
Stacked on #7885 — the first commit is that PR (the fallback needs it: without it, env/task-level
interruptiblenever reachesTaskExecutionMetadata). Only the last commit is new here. I'll rebase once #7885 merges.What changes were proposed in this pull request?
A new executor config key,
interruptibleFailureThreshold, ports flytepropeller'sinterruptible-failure-thresholdsemantics to the v2 executor:-1moves only the final attempt to non-interruptible capacity. A value above the maximum disables the fallback; zero is rejected at startup.maxSystemFailures), since a reclaimed node may be charged to either. This covers both of v1'sIgnoreRetryCausebranches without needing that flag.GetInterruptibleFailureThreshold()reports the configured value instead of a hardcoded 0, so connector-backed tasks receive the real threshold inTaskExecutionMetadata.DefaultMaxSystemFailuresmoved fromexecutor/pkg/controllertoexecutor/pkg/config(next to the field it defaults) so the plugin package can use it without an import cycle.Notes for reviewers:
-1default, existing interruptible tasks change behaviour on upgrade: their final attempt moves to on-demand. This matches the documented behaviour and v1's default.non-interruptible-node-selector-requirement) or the fallback pod is unschedulable.config_flags.gowas updated by hand in the generator's style;pflagsisn't installed locally, so re-runninggo generate ./executor/pkg/config/to confirm identical output would be a good check.How was this patch tested?
Table tests over the threshold arithmetic (
aboveInterruptibleFailureThreshold,interruptibleThresholdReached,maxSystemAttempts) and end-to-endNewTaskExecutionMetadatatests driving attempts/system-failures against a swapped-in config: last user attempt falls back, last system attempt falls back, single-attempt tasks keep their interruptible attempt, a threshold above both budgets disables the fallback, non-interruptible tasks are unaffected, and the threshold is reported to plugins.go test ./executor/pkg/plugin/ ./executor/pkg/config/ ./executor/andgo vet ./executor/...pass (the envtest suites were not run locally — no kubebuilder test binaries on this machine).Labels
Check all the applicable boxes
🤖 Generated with Claude Code