Jobs & CronJobs
A Job runs Pods until N succeed. CronJob runs a Job on a schedule. Together they cover database migrations, backups, batch processing, periodic cleanup — anything that isn’t long-lived service traffic.
Job + CronJob + parallelism patterns
EXAMPLE
# 1) One-shot Job — run a DB migration
apiVersion: batch/v1
kind: Job
metadata: { name: migrate-2026-06 }
spec:
backoffLimit: 4 # retry the Pod up to 4 times on failure
activeDeadlineSeconds: 900 # 15-minute hard cap
ttlSecondsAfterFinished: 86400 # clean up 1 day after completion
template:
spec:
restartPolicy: Never
containers:
- name: migrate
image: myapp:1.4.2
command: ["./manage.py", "migrate"]
envFrom:
- secretRef: { name: db-credentials }
# 2) Parallel Job — process a queue of work in parallel
apiVersion: batch/v1
kind: Job
metadata: { name: thumbnail-batch }
spec:
completions: 1000 # 1000 successful pods = done
parallelism: 20 # 20 pods at a time
backoffLimit: 50
template:
spec:
restartPolicy: OnFailure
containers:
- name: worker
image: thumbnailer:1.0
args: ["--queue", "redis://queue:6379/0"]
# 3) Indexed Job — each pod knows its index 0..N-1 (great for sharding)
apiVersion: batch/v1
kind: Job
metadata: { name: shard-export }
spec:
completionMode: Indexed
completions: 8
parallelism: 8
template:
spec:
restartPolicy: Never
containers:
- name: export
image: exporter:2.0
env:
- name: SHARD
valueFrom:
fieldRef: { fieldPath: metadata.annotations['batch.kubernetes.io/job-completion-index'] }
# 4) CronJob — nightly backup
apiVersion: batch/v1
kind: CronJob
metadata: { name: backup-nightly }
spec:
schedule: "0 2 * * *" # 02:00 UTC daily
timeZone: Australia/Sydney # since K8s 1.27
concurrencyPolicy: Forbid # don't pile up if a run is slow
startingDeadlineSeconds: 600
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 1
jobTemplate:
spec:
backoffLimit: 2
template:
spec:
restartPolicy: OnFailure
containers:
- name: dump
image: backup:1.0
envFrom:
- secretRef: { name: backup-creds }
# 5) Useful kubectl
kubectl get jobs
kubectl logs job/migrate-2026-06
kubectl describe job/migrate-2026-06
kubectl delete job/migrate-2026-06 # cancel a running job
Why it matters
Use backoffLimit + activeDeadlineSeconds on every Job — an infinite retry loop on a broken image will burn through your namespace quota and trigger pager. ttlSecondsAfterFinished stops zombie Job objects from accumulating.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Discussion
Loading…