Topic 1.4
Jobs & CronJobs
In one line
A Job runs a pod to completion exactly once (or a set number of times) and stops — a CronJob does the same thing on a recurring schedule — for the genuinely common 'run this task, don't keep it running forever' shape of work.
Think of it like this
A Deployment is like staffing a store that should always be open — if the person working leaves, someone else takes over immediately, forever. A JOB is like a one-time delivery task — once it's done, it's done; nobody needs to 'keep delivering' the same package forever.
Key ideas
- 01
A JOB creates one or more pods and tracks them until a specified number complete SUCCESSFULLY — unlike a Deployment, a Job's pods are meant to FINISH (exit with code 0) rather than run forever, and a Job does not restart a pod that already completed successfully, only ones that failed.
- 02
This is exactly the shape of a genuinely common real task: a database migration, a one-off data-processing script, generating a report — anything that should run to completion once and then simply be done, rather than staying up as a long-running service the way a Deployment's pods are meant to.
- 03
completionsandparallelismcontrol how a Job runs multiple pods:completions: 5means the Job isn't done until 5 pods have succeeded in total;parallelism: 2means up to 2 of those can run AT THE SAME TIME — genuinely useful for a batch of independent work items that can be processed concurrently rather than strictly one at a time. - 04
A CRONJOB is a Job that runs on a recurring SCHEDULE, using the exact same cron syntax Linux's own course covered (
0 2 * * *for 'every night at 2am') — Kubernetes creates a fresh Job (and its pods) automatically at each scheduled time, meaning you get Kubernetes' own self-healing and resource management for what would otherwise be a plain Linux cron job running somewhere less observable. - 05
kubectl get jobsandkubectl get cronjobsshow their status directly, including how many completions have succeeded so far — a Job or CronJob's pods, once completed, are kept around briefly by default (for inspecting logs) rather than deleted immediately, though old completed Jobs are eventually cleaned up automatically based on retention settings.
Code & diagrams
A one-off database migration job.
apiVersion: batch/v1
kind: Job
metadata:
name: db-migration
spec:
completions: 1
backoffLimit: 3 # retry up to 3 times if the pod fails
template:
spec:
restartPolicy: Never
containers:
- name: migrate
image: my-registry/my-app:1.5.0
command: ["./run-migrations.sh"]The same cron syntax as Linux's own course, now managed by Kubernetes.
apiVersion: batch/v1
kind: CronJob
metadata:
name: nightly-cleanup
spec:
schedule: "0 2 * * *" # every night at 2am — identical syntax to Linux crontab
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: cleanup
image: my-registry/my-app:1.5.0
command: ["./cleanup-old-records.sh"]Run a one-off Job and inspect a CronJob's history.
# Run the migration once
kubectl apply -f job.yaml
kubectl get jobs
kubectl logs job/db-migration
# Once it succeeds, it won't run again — confirm with:
kubectl get pods -l job-name=db-migration
# STATUS shows Completed, not Running
# Set up the recurring cleanup job
kubectl apply -f cronjob.yaml
kubectl get cronjobs
# see LAST SCHEDULE and next scheduled run
# See every Job the CronJob has created over time
kubectl get jobs -l job-name
# Manually trigger a CronJob's job immediately, for testing, without waiting for its schedule
kubectl create job manual-test --from=cronjob/nightly-cleanupExplain it without notes
Why doesn't a Job's pod get automatically restarted after it completes successfully, unlike a Deployment's pods?
Why would you use a Kubernetes CronJob instead of just running a plain cron job (Linux's own course) on one of the cluster's nodes directly?
Practice
Create the example Job, confirm it completes successfully, and view its logs — then confirm its pod shows Completed status and is never restarted.
Create the example CronJob and use kubectl create job --from=cronjob/... to manually trigger one run immediately, without waiting for its actual schedule.
Trade-offs
- ↔
Jobs and CronJobs are the right tool specifically for finite, completable work — using a Deployment for a task that should genuinely run once and stop (forcing it to somehow exit gracefully and be manually cleaned up) fights against the Deployment model's core assumption that any exited pod needs replacing, which is exactly the confusion this topic's distinction exists to prevent.
Done when you can
I understand why a Job's pods aren't restarted after completing successfully.
I can create both a one-off Job and a recurring CronJob.
I know a Kubernetes CronJob provides real advantages over a plain node-level cron job.