Not every workload runs forever. Jobs run a task to completion and stop; CronJobs run them on a schedule — the right tools for migrations, batch processing, and backups.
Why: Deployments are for processes that should run forever — restart a finished one and Kubernetes thinks it crashed. A Job is the opposite: it runs a pod until the task succeeds, then stops. Use it for database migrations, one-off imports, or any "do this once and finish" work. completions and parallelism let you run many at once.
apiVersion: batch/v1
kind: Job
metadata:
name: migrate
spec:
backoffLimit: 4 # retry up to 4 times on failure
template:
spec:
restartPolicy: Never
containers:
- name: migrate
image: myapp:1.0
command: ['./manage.sh', 'migrate']A Job's pod runs, then enters Completed instead of restarting. The Job tracks how many completions succeeded. Read the pod's logs to see what it did, and clean up finished Jobs (or set ttlSecondsAfterFinished to auto-delete them).
kubectl apply -f job.yamlCOMPLETIONS shows 1/1 when done
kubectl get job migrateSee what the task actually did
kubectl logs job/migrateWhy: a CronJob creates a Job on a recurring schedule, written in standard cron syntax. It is how you run nightly backups, hourly reports, or periodic cleanups. Each firing produces a fresh Job (and pod), so you get the same run-to-completion behavior on a timer.
apiVersion: batch/v1
kind: CronJob
metadata:
name: nightly-backup
spec:
schedule: "0 2 * * *" # every day at 02:00 (min hr dom mon dow)
jobTemplate:
spec:
template:
spec:
restartPolicy: Never
containers:
- name: backup
image: myapp:1.0
command: ['./backup.sh']Why: left alone, CronJobs pile up old Job objects and can overlap if one run is slow. concurrencyPolicy: Forbid skips a new run while the previous is still going; the historyLimits cap how many finished Jobs are kept so the namespace stays tidy.
spec:
schedule: "*/15 * * * *"
concurrencyPolicy: Forbid # don't start if one is still running
successfulJobsHistoryLimit: 3 # keep the last 3 successes
failedJobsHistoryLimit: 1 # keep the last 1 failure