Workloads III: Job & CronJob
Job runs Pods to completion (a fixed number of successful completions) and stops -- the opposite of always-on services. CronJob is a Job template plus a schedule: it creates a new Job object at each s
Job runs Pods to completion (a fixed number of successful completions) and stops -- the opposite of always-on services. CronJob is a Job template plus a schedule: it creates a new Job object at each scheduled tick. Together they handle all batch, one-off, and scheduled recurring work.
-
A Job creates Pods and tracks completions toward spec.completions (default 1), retrying failed Pods up to spec.backoffLimit times.
-
spec.parallelism controls how many Pods run concurrently.
-
completionMode: Indexed gives each Pod a stable index useful for partitioned parallel work.
-
A CronJob controller creates a new Job object at each scheduled tick.
-
concurrencyPolicy: Allow/Forbid/Replace controls what happens if the previous run is still active.
-
Define a Job with a Pod template whose restartPolicy is Never or OnFailure (Job Pods cannot use Always).
-
Set spec.completions and spec.parallelism based on whether the work is a single task, N identical tasks, or a partitioned batch.
-
Apply the Job; the Job controller creates Pods up to spec.parallelism until spec.completions successful completions are reached, retrying failures up to spec.backoffLimit.
-
For recurring work, wrap the same Pod template in a CronJob with a schedule field (standard cron syntax) instead of applying the Job directly.
-
The CronJob controller creates a new Job object at each scheduled tick; set concurrencyPolicy (Allow/Forbid/Replace) to control overlap with a still-running previous Job.
-
Set successfulJobsHistoryLimit / failedJobsHistoryLimit to bound how many old Job objects a CronJob keeps around for inspection.
-
Nightly database backup jobs (pg_dump to object storage) run on a schedule via CronJob, with concurrencyPolicy: Forbid so a slow backup never overlaps the next night's run.
-
A one-off data-migration script run as a Job during a release, so it runs to completion exactly once and Kubernetes tracks/retries it if it fails.
-
A CronJob that runs a nightly report-generation or cache-warming task ahead of business hours.
-
A parallel Job with completionMode: Indexed processing a batch of files/records, where each Pod's index picks a distinct partition of the work.
-
A cleanup CronJob pruning old logs or expired temp data on a recurring schedule.
-
Always set backoffLimit deliberately based on how expensive or side-effecting a retry is, rather than relying on the default.
-
Use concurrencyPolicy: Forbid or Replace for any CronJob whose job isn't safe to run twice concurrently (backups, migrations).
-
Set activeDeadlineSeconds on Jobs that could hang, so a stuck Job doesn't consume capacity indefinitely.
-
Use completionMode: Indexed for partitioned parallel work so each Pod knows its own chunk without external coordination.
-
Keep successfulJobsHistoryLimit/failedJobsHistoryLimit low so completed CronJob history doesn't accumulate unnecessary API objects.
-
Make Job containers idempotent where possible, since a retry re-runs the entire Pod, not just the failed step.
-
Setting restartPolicy: Always on a Job Pod template -- Jobs require Never or OnFailure and will be rejected otherwise.
-
Relying on the default concurrencyPolicy (Allow) for a CronJob whose job isn't safe to run twice at once, silently double-running backups or migrations.
-
Not setting activeDeadlineSeconds, letting a hung Job Pod occupy cluster resources indefinitely.
-
Ignoring startingDeadlineSeconds and missed-schedule behavior, so a CronJob silently skips runs during a control-plane outage without anyone noticing.
-
Assuming a Job's backoffLimit retries mean partial progress is preserved -- each retry re-runs the whole Pod from scratch, not just the failed portion.
-
Letting successfulJobsHistoryLimit default unbounded-ish growth accumulate hundreds of completed Job objects for a frequent CronJob.
-
Tune spec.parallelism to match available cluster capacity -- too high floods the cluster with simultaneous Job Pods competing with regular workloads for scheduling.
-
For partitioned batch work, completionMode: Indexed avoids each Pod needing external coordination to know which chunk of work is its own.
-
Set activeDeadlineSeconds on long-running or potentially-hanging Jobs so a stuck Job doesn't consume scheduler and node capacity indefinitely.
-
Keep successfulJobsHistoryLimit/failedJobsHistoryLimit low -- CronJobs that accumulate hundreds of completed Job objects add unnecessary load to the API server and etcd.
-
Set backoffLimit deliberately for expensive or side-effecting jobs (e.g. sending emails, charging payments) -- a lower limit avoids repeated real-world side effects on failure.
-
Use concurrencyPolicy: Forbid or Replace for any CronJob whose job is not safe to run twice concurrently; default Allow can silently double-run.
-
Alert on CronJob runs that are missed (startingDeadlineSeconds exceeded) or land in Failed state -- a silently-broken nightly backup is a common way teams discover they have no recovery point.
-
Make Job Pods idempotent or safely re-runnable where possible, since retries re-execute the whole Pod, not just the failed step.
-
Create a Job with spec.completions: 5 and spec.parallelism: 2 and watch
kubectl get pods -wto see Pods created in waves of 2 until 5 succeed. -
Create a Job whose container deliberately exits non-zero, and observe backoffLimit retries in
kubectl describe jobbefore it's marked Failed. -
Create a CronJob with schedule "*/2 * * * *" and concurrencyPolicy: Forbid, then check
kubectl get jobsover a few runs to confirm no overlapping Job objects. -
Set activeDeadlineSeconds on a Job running a deliberately long sleep and confirm Kubernetes terminates it once the deadline passes.
-
Job runs Pods to completion (fixed successful count) with configurable parallelism and retry via backoffLimit.
-
CronJob is a schedule plus a Job template -- creates independent Job objects at each tick.
-
concurrencyPolicy (Allow/Forbid/Replace) determines what happens when a previous run is still active.
-
activeDeadlineSeconds and ttlSecondsAfterFinished bound runtime and object lifetime.
Want a visual for this concept?
Generate a diagram tailored to “Workloads III: Job & CronJob” — the AI picks whichever visual (flowchart, comparison, sequence, etc.) best fits.
Sign in to generate a visual →