feat(kubernetes): retry disrupted Job pods - #327
Conversation
|
@Ark-kun When you have a chance, could you review the API/Job-policy shape? This is deliberately draft and opt-in pending a real-GKE disruption canary. The exact production |
Signed-off-by: Steve Bako <steve.bako@shopify.com> Assisted-By: devx/3e534c34-53a1-4bfa-9aee-cc649ee10009 Signed-off-by: Steve Bako <steve.bako@shopify.com>
c438c67 to
e800927
Compare
|
Follow-up pushed: added the user-facing annotation/restart-safety contract to README and an assertion over the exact serialized Kubernetes Job spec ( |
|
Marking ready for maintainer review. The feature is opt-in and defaults to the existing zero-retry behavior, so upstream merge alone changes no workload. Proposed validation sequence: merge upstream -> bump Oasis staging submodule -> run a real GKE |
|
New real-GKE evidence from staging run https://oasis.shopify.io/runs/01a000936be1d56d65cc: the Embed pod ran successfully for 10h15m, then its node became |
Problem
Tangle renders every Kubernetes container execution as an Indexed Job with
backoffLimitPerIndex: 0andmaxFailedIndexes: 0. A pod deleted by scheduler preemption, the eviction API, or node loss therefore fails its index immediately and the Job never creates a replacement.This is distinct from a component returning a non-zero exit code: infrastructure disruptions often have no useful application exit code and carry the Kubernetes
DisruptionTarget=Truecondition.Observed production examples:
DisruptionTarget=True, reasonPreemptionByScheduler; a higher-priority CoreDNS pod displaced a running Tangle taskDisruptionTarget=True, reasonEvictionByEvictionAPISee Shopify/oasis-backend#491.
Change
Add an opt-in task annotation:
For opted-in Kubernetes Jobs:
backoffLimitPerIndexto the requested bounded retry count (0–10)Counta pod withDisruptionTarget=True, allowing the Job controller to replace it until that budget is exhaustedFailIndeximmediately when themaincontainer exits non-zero, so deterministic user-code failures are not rerunpodReplacementPolicy: Failed, as required withpodFailurePolicyThe default remains exactly zero retries with no pod failure policy, preserving existing behavior for every task that does not opt in.
Safety
[0, 10]and fail closed.Validation
PYTHONPATH=. uv run --frozen pytest -q— 475 passedRemaining validation
Draft pending a real-GKE canary that deletes/evicts an opted-in test pod and confirms one replacement is created under the same Job before this is enabled on production workloads.