Kubernetes Job Retry Management
Kubernetes Job Retry Management ensures job resilience by automatically retrying failed tasks within a defined strategy, enhancing reliability in containerized workloads.
Kubernetes Job Retry Management is the mechanism by which a batch/v1 Job automatically re-attempts failed work by replacing failed Pods with new ones, governed by configurable limits and timing so that retries help a workload recover from transient problems without allowing a persistently broken workload to consume unbounded cluster resources. Retry management sits between failure detection and terminal failure: every retry is a bet that the next attempt will succeed, and the Job controller places a bounded number of those bets before giving up.
Retries in Kubernetes Jobs operate at the Pod level — a failed Pod is not repaired in place (unless restartPolicy: OnFailure restarts a container within the same Pod); instead, the controller creates a brand-new Pod to attempt the same unit of work again.
How Retries Are Triggered
Pod Failure as the Trigger
Whenever a Pod owned by a Job terminates in a failed state — because a container exited non-zero under restartPolicy: Never, or because the Pod was evicted or deleted before completing — the Job controller observes the failure and, provided the retry budget is not exhausted, creates a replacement Pod for the same unit of work (the same index, for Indexed Jobs, or simply one more attempt toward the aggregate completions count for NonIndexed Jobs).
restartPolicy: OnFailure vs Never
OnFailureretries happen inside the same Pod: the kubelet restarts the failing container, and these in-place restarts are tracked by the container's own restart count, separate from the Job'sbackoffLimitaccounting, though a Pod that never manages to succeed will eventually still be considered failed at the Pod level if the container keeps crashing indefinitely relative to the Pod's own backoff.Neverretries happen at the Pod level: each failure produces an entirely new Pod, which is the model most directly and visibly governed bybackoffLimit.
Bounding Retries
backoffLimit
The primary lever: .spec.backoffLimit (default 6) is the maximum number of Pod failures the Job will tolerate in total before it transitions to Failed. Every counted failure decrements the remaining budget; once it reaches zero, no further replacement Pods are created.
Exponential Backoff Timing
Between retries, the controller inserts a delay that grows exponentially with each successive failure — starting around 10 seconds and doubling with each retry up to a capped maximum (6 minutes). This prevents a workload stuck in a fast failure loop from generating an unbounded rate of Pod creation calls against the API server, and gives transient conditions (a dependency restarting, a brief network partition) time to resolve between attempts.
Per-Index Retry Budgets
For completionMode: Indexed Jobs, .spec.backoffLimitPerIndex allocates a separate retry budget to each completion index rather than pooling all retries into one shared counter. This is important for large fan-out Jobs: without per-index budgets, one persistently broken shard could exhaust the entire Job's retry allowance and stop other, healthy shards from getting retried at all. .spec.maxFailedIndexes complements this by capping how many indices are allowed to exhaust their individual budget before the whole Job is failed, rather than requiring every single index to succeed.
Refining What Counts as Retryable
.spec.podFailurePolicy changes retry behavior beyond simple counting:
- A rule with action
Ignorecauses a matching failure to trigger a retry without consuming any of thebackoffLimitbudget — appropriate for infrastructure-driven failures like node preemption, where the failure says nothing about whether the workload itself is broken. - A rule with action
FailJobskips retries altogether for a matching failure, useful for exit codes that indicate the work is fundamentally unrecoverable (malformed input, a configuration error) where further attempts would only waste time and resources.
podFailurePolicy:
rules:
- action: Ignore
onPodConditions:
- type: DisruptionTarget
- action: FailJob
onExitCodes:
containerName: worker
operator: In
values: [78]
Observing Retry Activity
kubectl get pods -l job-name=codartium-batch-import
kubectl get job codartium-batch-import -o jsonpath='{.status.failed}'
kubectl describe job codartium-batch-import
kubectl describe job surfaces recent events, including Pod creation and failure events, which is typically the fastest way to see the retry history of a Job without manually cross-referencing individual Pod objects.
Example
apiVersion: batch/v1
kind: Job
metadata:
name: codartium-retry-example
spec:
completions: 10
parallelism: 3
completionMode: Indexed
backoffLimitPerIndex: 3
maxFailedIndexes: 2
template:
spec:
restartPolicy: Never
containers:
- name: worker
image: codartium/worker:latest