Skip to main content

Kubernetes Ep 11: Jobs, CronJobs & Batch Processing

Rachmat Hidayat
Author
Rachmat Hidayat
Learn & sharing insights on TypeScript, Go, Kubernetes, DevOps, DevSecOps, SRE, Platform Engineering, AI/ML Engineering, and MLOps.
kubernetes - This article is part of a series.
Part 11: This Article
Unlike Deployments and StatefulSets—which are designed to keep long-running processes alive indefinitely—Jobs and CronJobs are designed for run-to-completion batch tasks. When the workload process terminates with exit code 0, Kubernetes marks the Pod as Completed.

TL;DR (Quick Summary)
#

  • Job: Creates one or more Pods and ensures that a specified number of them successfully terminate (completions). Supports parallel execution (parallelism).
  • CronJob: Manages time-based Jobs using standard 5-field cron syntax (*/5 * * * *).
  • Restart Policy: Pods in a Job must set restartPolicy: Never or restartPolicy: OnFailure (setting Always is invalid).
  • Cleanup Policy: Set ttlSecondsAfterFinished to automatically garbage-collect completed Job pods.

1. Job vs CronJob Workflow
#


graph TD
    CJ["CronJob: db-backup-cronjob
Schedule: 0 2 * * * (Daily at 2 AM)"] -->|Triggers at 02:00| J["Job: db-backup-2891230"] J -->|Spawns| Pod["Pod: db-backup-2891230-x8k9l"] Pod -->|Executes pg_dump| Execution["PostgreSQL Backup Execution"] Execution -->|Exit Code 0| Status["Pod Status: Completed
Job Status: Successful"]

2. Kubernetes Job Manifest (Batch Processing)
#

Create job-db-migration.yaml:

apiVersion: batch/v1
kind: Job
metadata:
  name: database-migration-job
  namespace: default
spec:
  completions: 1       # Total successful completions required
  parallelism: 1       # Max parallel pods running concurrently
  backoffLimit: 3      # Number of retries before marking Job failed
  ttlSecondsAfterFinished: 300 # Auto-delete completed Pods after 5 mins
  template:
    spec:
      containers:
      - name: migration-runner
        image: python:3.11-alpine
        command:
        - sh
        - -c
        - |
          echo "Starting database schema migration..."
          sleep 5
          echo "Schema migration complete. Exit code 0."
        resources:
          requests:
            cpu: "100m"
            memory: "128Mi"
      restartPolicy: OnFailure

Apply and inspect Job execution:

kubectl apply -f job-db-migration.yaml
kubectl get job database-migration-job --watch

Expected Terminal Output:

NAME                     COMPLETIONS   DURATION   AGE
database-migration-job   0/1           2s         2s
database-migration-job   1/1           7s         7s

Check Pod completion status:

kubectl get pods -l job-name=database-migration-job
NAME                           READY   STATUS      RESTARTS   AGE
database-migration-job-4k9lp   0/1     Completed   0          12s

3. Kubernetes CronJob Manifest (Scheduled Backups)
#

Create cronjob-backup.yaml:

apiVersion: batch/v1
kind: CronJob
metadata:
  name: nightly-backup-cronjob
  namespace: default
spec:
  schedule: "0 2 * * *" # Runs daily at 2:00 AM UTC
  concurrencyPolicy: Forbid # Prevents overlapping jobs if previous run hangs
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 1
  jobTemplate:
    spec:
      backoffLimit: 2
      template:
        spec:
          containers:
          - name: backup-tool
            image: alpine
            command:
            - sh
            - -c
            - "echo 'Running nightly automated backup snapshot...' && sleep 10"
          restartPolicy: OnFailure

Apply manifest:

kubectl apply -f cronjob-backup.yaml

Manually Triggering a CronJob for Testing
#

Instead of waiting until 2:00 AM to test your schedule, manually trigger an ad-hoc Job run from the CronJob definition:

kubectl create job --from=cronjob/nightly-backup-cronjob test-manual-backup-run

4. Concurrency Policies Explained
#

When a scheduled CronJob trigger fires while a previous Job execution is still running:

  1. Allow (Default): Allows concurrent Jobs to run simultaneously.
  2. Forbid: Skips the new Job execution if the previous Job has not finished yet.
  3. Replace: Cancels the currently running Job execution and replaces it with the new Job execution.

5. Summary & Next Steps
#

Jobs and CronJobs handle batch execution and scheduled tasks cleanly.

In Episode 12: Namespaces, Resource Quotas & LimitRanges, we will dive into multi-tenancy cluster administration, learning how to isolate teams and enforce CPU/Memory limits to prevent noisy-neighbor outages!

kubernetes - This article is part of a series.
Part 11: This Article