Kubernetes Job Completion Management
Kubernetes Job Completion Management ensures tasks finish successfully through lifecycle control, status tracking, and automated cleanup within the orchestration platform.
Kubernetes Job Completion Management is the set of mechanisms Kubernetes uses to determine, record, and act upon the point at which a batch/v1 Job has finished its work. Completion is not a single event but a tracked, incremental state: the Job controller accumulates successful Pod outcomes, compares them against the completion criteria declared in the spec, and transitions the Job to a terminal condition once those criteria are satisfied. Completion Management covers how that tracking works, how different Job patterns define "done" differently, and how operators observe and react to completion.
Because Jobs represent finite work rather than continuously running services, correctly recognizing completion — and distinguishing it from failure — is the central responsibility of the Job controller, and the primary signal operators and automation systems rely on to know when downstream steps (result collection, cleanup, triggering the next stage of a pipeline) can proceed.
What "Complete" Means
Fixed-Completion-Count Jobs
For Jobs with .spec.completions set, the Job is complete once the number of successfully finished Pods equals that value. Pods that fail are not counted toward completions; the controller replaces them (subject to backoffLimit) until enough succeed.
Indexed Jobs
For completionMode: Indexed Jobs, completion additionally requires that every index from 0 to completions - 1 has at least one successful Pod. The controller tracks completed indices individually, so a retry of index 3 does not require re-running indices that already succeeded.
Work Queue Jobs
Without completions set, the Job is considered complete once any one Pod exits successfully and there are no other Pods still running — the assumption being that Pods coordinate through an external queue and the first one to observe an empty queue exiting successfully signals that all work has been consumed.
Status Fields and Conditions
Status Counters
.status.active, .status.succeeded, and .status.failed give a live numeric summary of Pod outcomes. These are updated continuously as Pods terminate, and are the fields most commonly polled by external automation checking on Job progress.
Conditions
.status.conditions records a list of condition objects with type (Complete, Failed, Suspended, FailureTarget), status, reason, and lastTransitionTime. The Complete condition being True is the canonical signal that a Job finished successfully; a Failed condition with status: True indicates the Job stopped without meeting its completion criteria, along with a reason such as BackoffLimitExceeded or DeadlineExceeded.
completionTime
.status.completionTime records the timestamp at which the Job satisfied its completion criteria, distinct from .status.startTime, which records when the Job began. The difference between the two gives the Job's total wall-clock duration.
Reacting to Completion
Polling and Waiting
kubectl wait --for=condition=complete job/codartium-batch-import --timeout=600s
kubectl wait blocks until the specified condition is observed, making it a common building block in CI/CD pipelines and shell scripts that need to run a Job and then proceed only once it has finished.
Post-Completion Cleanup
.spec.ttlSecondsAfterFinished ties directly into completion management: the TTL controller only begins its countdown once a Job reaches a terminal condition (Complete or Failed), after which it deletes the Job and its Pods automatically. Without a TTL set, completed Jobs and their Pods remain in the cluster indefinitely until manually deleted, which is useful for post-mortem log inspection but requires deliberate garbage collection at scale.
Downstream Triggering
CronJob-managed Jobs, CI/CD systems, and custom controllers frequently watch for the Complete condition to trigger the next step of a pipeline — for example, starting a notification, updating a status dashboard, or kicking off a dependent Job. Watching the condition rather than polling raw Pod state is preferred because the condition already accounts for retries, indexing, and failure policy evaluation.
Distinguishing Completion from Failure
A Job that exhausts its backoffLimit, exceeds its activeDeadlineSeconds, or is short-circuited by a podFailurePolicy rule with action FailJob transitions to Failed rather than Complete, even if some Pods succeeded. Operators building automation around Job completion should always check for both conditions explicitly rather than assuming the absence of Failed implies Complete, since a Job that is still running will have neither condition set.
kubectl get job codartium-batch-import -o jsonpath='{.status.conditions[?(@.type=="Complete")].status}'
kubectl get job codartium-batch-import -o jsonpath='{.status.conditions[?(@.type=="Failed")].status}'
Example
apiVersion: batch/v1
kind: Job
metadata:
name: codartium-completion-example
spec:
completions: 6
parallelism: 2
completionMode: Indexed
backoffLimit: 4
ttlSecondsAfterFinished: 900
template:
spec:
restartPolicy: Never
containers:
- name: worker
image: codartium/worker:latest
kubectl apply -f completion-example.yaml
kubectl wait --for=condition=complete job/codartium-completion-example --timeout=300s
kubectl get job codartium-completion-example -o jsonpath='{.status.completionTime}'