Lesson 7 / 25

Jobs and CronJobs

Run to completion, on demand or on a schedule.

Batch work with retries

A Job runs pods until a task completes successfully (a migration, a report, a batch import), with retries (backoffLimit), parallelism and an optional deadline. A CronJob creates Jobs on a cron schedule. Set concurrencyPolicy (Forbid prevents overlapping runs), history limits, and a ttlSecondsAfterFinished to clean up finished Jobs. Make jobs idempotent, because retries and occasional duplicate runs do happen.

Generating a CronJob, run

I ran this with kubectl 1.37.0 using --dry-run=client (or kubectl kustomize), which generates manifests locally without a cluster; nothing was applied to a live cluster. The schedule "30 2 * * *" runs at 02:30 every day (in the controller's time zone unless spec.timeZone is set); the pod template uses restartPolicy OnFailure, as Jobs require OnFailure or Never.

kubectl create cronjob nightly-report --image=busybox:1.36 --schedule="30 2 * * *" --dry-run=client -o yaml -- sh -c "echo building report"

Output:

apiVersion: batch/v1
kind: CronJob
metadata:
  name: nightly-report
spec:
  jobTemplate:
    metadata:
      name: nightly-report
    spec:
      template:
        metadata: {}
        spec:
          containers:
          - command:
            - sh
            - -c
            - echo building report
            image: busybox:1.36
            name: nightly-report
            resources: {}
          restartPolicy: OnFailure
  schedule: 30 2 * * *
status: {}

Forbid overlapping runs

Set concurrencyPolicy: Forbid for jobs that must not run twice at once, such as billing runs.

Quick check: Why should Jobs be idempotent?

  • Retries and occasional duplicate runs can execute the same work more than once
  • Jobs never retry
  • Kubernetes forbids side effects
  • It makes images smaller
Answer

Retries and occasional duplicate runs can execute the same work more than once — Design for at-least-once execution.