Skip to main content
Course/Security & Scale/Jobs & CronJobs
2/845 min
Security & Scale

Jobs & CronJobs

Run batch tasks to completion with Jobs and schedule recurring work with CronJobs.

beginner45 minRead β†’ Lab β†’ Quiz β†’ Practice
🧠 Brain Warm-Up
🧠 Brain Warm-Up: If a CronJob is scheduled to run every hour, but the previous Job execution hangs indefinitely, what happens to the next execution? How does Kubernetes track the status of finished Jobs to avoid overloading nodes? Think about concurrency constraints before reading.

Why Not Deployments for Batch Work?

Deployments are designed to run forever β€” they maintain a desired state of continuously running Pods. If a container in a Deployment exits with code 0, the kubelet interprets this as a termination and the Deployment controller immediately restarts it to maintain replica count. This is wrong for a database migration or batch computation: you want the Pod to run once, complete its task, and stop.

Jobs and CronJobs are designed specifically for finite, run-to-completion workloads.

Job Architecture & Restart Policies

A Job ensures a specified number of Pods complete successfully (exit code 0).

Unlike Deployments, Jobs support two restart policies in their Pod templates:

  1. Never: If the container fails (exits non-zero), the pod is not restarted. Instead, the Job controller spawns a completely new Pod on the cluster. This keeps the failed Pod and its logs intact for troubleshooting, but consumes IP/sandbox resources.
  2. OnFailure: If the container fails, the local kubelet restarts the container inside the *same* Pod sandbox. This avoids scheduling overhead but does not create a clean new Pod.

The Job controller manages the retry logic up to backoffLimit times (default: 6). If the limit is reached, the Job is marked as failed.

Visualizing Job Controller Loop

[ CronJob Controller ] (Ticks on cron schedule)

β”‚

β–Ό (Creates Job object)

[ Job Object ] (Specifies completions, parallelism, backoffLimit)

β”‚

β–Ό (Job Controller observes Job in etcd)

[ Job Controller ] ◄────────────────────────────────────────┐

β”‚ β”‚

β”œβ”€β–Ί (Spawns N Pods up to parallelism limit) β”‚

β”‚ β”‚

β–Ό β”‚ (Updates status)

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚

β”‚ Pod 1 β”‚ β”‚ Pod 2 β”‚ β”‚ Pod N β”‚ β”‚

β”‚ (Running) β”‚ β”‚(Completed)β”‚ β”‚ (Failed) β”‚β”€β”€β”˜

β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜

β”‚ β”‚ β”‚

β–Ό β–Ό β–Ό

Runs to exit Clean exit 0 RestartPolicy: Never/OnFailure

status (Success) Evicts/recreates up to backoffLimit

Key Job Fields

FieldDescription
completionsTotal number of successful Pod completions required to mark the Job complete.
parallelismMaximum number of Pods that are allowed to run concurrently at any given moment.
backoffLimitMaximum number of retries before marking the Job as failed (default: 6).
activeDeadlineSecondsReal-time execution limit for the Job. If exceeded, the Job is terminated.
ttlSecondsAfterFinishedTime-to-live. Once finished, the Job and its Pods are garbage collected.
spec:
  completions: 3
  parallelism: 2
  backoffLimit: 3
  ttlSecondsAfterFinished: 120

CronJobs and Concurrency Policies

A CronJob manages Jobs on a schedule using standard Unix cron syntax:

β”Œβ”€β”€β”€ minute (0-59)
β”‚ β”Œβ”€β”€β”€ hour (0-23)
β”‚ β”‚ β”Œβ”€β”€β”€ day of month (1-31)
β”‚ β”‚ β”‚ β”Œβ”€β”€β”€ month (1-12)
β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€ day of week (0-7, 0 and 7 = Sunday)
β”‚ β”‚ β”‚ β”‚ β”‚
* * * * *

"*/1 * * * *" = every minute. "0 2 * * *" = daily at 02:00.

concurrencyPolicy

ValueBehaviour
AllowNew Job starts even if previous is still running (default)
ForbidSkip new Job if previous is still running
ReplaceCancel running Job and start a new one

Use Cases

  • Database migrations on deploy
  • Nightly report generation
  • Periodic data processing or backups
  • Sending scheduled notifications