Kubernetes Operations

Jobs and CronJobs

Not every workload should run forever. Jobs run work to completion, and CronJobs run Jobs on a schedule.

What this lesson covers

Deployments are for long-running services. Jobs and CronJobs are for work that runs to completion, either once or on a schedule.

  • What a Job is
  • What a CronJob is
  • How Jobs differ from Deployments
  • How to inspect completion status
  • How to view logs from completed Pods
  • How to run scheduled work safely
Field note: Use Deployments for services that should keep running. Use Jobs for tasks that should finish.

Deployment vs Job

Deployment:
  Keep this application running.

Job:
  Run this task until it completes successfully.

CronJob:
  Run this task on a schedule.

Before you start

kubectl config current-context
kubectl get nodes
kubectl create namespace jobs-lab

Step 1: Create a simple Job

Create a file named:

simple-job-lab.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: simple-job-lab
  namespace: jobs-lab
spec:
  template:
    spec:
      restartPolicy: Never
      containers:
      - name: worker
        image: busybox:latest
        command: ["sh", "-c", "echo Starting job; sleep 5; echo Job complete"]
kubectl apply -f simple-job-lab.yaml
kubectl get jobs -n jobs-lab
kubectl get pods -n jobs-lab

Step 2: Watch the Job complete

kubectl get jobs -n jobs-lab -w

Press Ctrl+C after the Job shows completion.

Step 3: View logs from the Job Pod

kubectl get pods -n jobs-lab
kubectl logs <job-pod-name> -n jobs-lab

Step 4: Create a Job with completions

Create a file named:

completions-job-lab.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: completions-job-lab
  namespace: jobs-lab
spec:
  completions: 3
  parallelism: 1
  template:
    spec:
      restartPolicy: Never
      containers:
      - name: worker
        image: busybox:latest
        command: ["sh", "-c", "echo Running one unit of work; sleep 3; echo Done"]
kubectl apply -f completions-job-lab.yaml
kubectl get jobs -n jobs-lab -w

This Job needs three successful completions.

Step 5: Create a parallel Job

Create a file named:

parallel-job-lab.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: parallel-job-lab
  namespace: jobs-lab
spec:
  completions: 4
  parallelism: 2
  template:
    spec:
      restartPolicy: Never
      containers:
      - name: worker
        image: busybox:latest
        command: ["sh", "-c", "echo Parallel work on $(hostname); sleep 5; echo Done"]
kubectl apply -f parallel-job-lab.yaml
kubectl get pods -n jobs-lab
kubectl get jobs -n jobs-lab

Step 6: Create a failing Job

Create a file named:

failing-job-lab.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: failing-job-lab
  namespace: jobs-lab
spec:
  backoffLimit: 2
  template:
    spec:
      restartPolicy: Never
      containers:
      - name: worker
        image: busybox:latest
        command: ["sh", "-c", "echo This job will fail; exit 1"]
kubectl apply -f failing-job-lab.yaml
kubectl get jobs -n jobs-lab
kubectl get pods -n jobs-lab
kubectl describe job failing-job-lab -n jobs-lab

The backoffLimit controls how many retries Kubernetes attempts before considering the Job failed.

Step 7: Create a CronJob

Create a file named:

cronjob-lab.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
  name: cronjob-lab
  namespace: jobs-lab
spec:
  schedule: "*/1 * * * *"
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 1
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: Never
          containers:
          - name: scheduled-worker
            image: busybox:latest
            command: ["sh", "-c", "date; echo Scheduled job ran"]
kubectl apply -f cronjob-lab.yaml
kubectl get cronjobs -n jobs-lab

Step 8: Wait for scheduled Jobs

kubectl get jobs -n jobs-lab -w

Wait until the CronJob creates a Job, then press Ctrl+C.

Step 9: View CronJob-created logs

kubectl get pods -n jobs-lab
kubectl logs <cronjob-pod-name> -n jobs-lab

Common Job and CronJob commands

kubectl get jobs -n <namespace>
kubectl describe job <job-name> -n <namespace>
kubectl get cronjobs -n <namespace>
kubectl describe cronjob <cronjob-name> -n <namespace>
kubectl get pods -n <namespace>
kubectl logs <pod-name> -n <namespace>
kubectl get events -n <namespace> --sort-by=.metadata.creationTimestamp

Common mistakes

  • Using a Deployment for one-time work.
  • Forgetting that CronJob schedules use cron syntax.
  • Leaving too much Job history behind.
  • Setting retries too high for tasks that fail fast.
  • Not making scheduled jobs idempotent.

Step 10: Clean up

kubectl delete namespace jobs-lab
Bottom line: Jobs run work to completion. CronJobs create Jobs on a schedule. They are the Kubernetes pattern for batch work, maintenance tasks, and recurring jobs.

Check your understanding

  1. When should you use a Job instead of a Deployment?
  2. What does a CronJob create?
  3. What does backoffLimit control?
  4. What does completions mean?
  5. What does parallelism control?
  6. What command lists CronJobs?
  7. Why should CronJob tasks often be idempotent?
  8. Where do you view logs from completed Job work?
  9. What Namespace command cleaned up the lab?
  10. Name three troubleshooting commands for Jobs.
Answer key
  1. When the work should run to completion instead of staying online.
  2. Jobs.
  3. How many retries are attempted before the Job is considered failed.
  4. How many successful Pod completions are needed.
  5. How many Pods can run at the same time.
  6. kubectl get cronjobs -n <namespace>.
  7. Because retries or overlapping schedules can run the same work more than once.
  8. In the Job-created Pod logs.
  9. kubectl delete namespace jobs-lab.
  10. Examples: get jobs, describe job, get pods, logs, get events.
← Previous: Persistent Storage Series index Next: Scheduling Controls →