CKAD — CronJobs
What Is a CronJob?
A CronJob creates Jobs on a schedule. It uses the standard cron format to define when Jobs should run — every minute, every hour, daily, weekly, or any custom interval.
Think of it as a Kubernetes-native replacement for the Linux crontab.
Cron Schedule Format
┌───────────── minute (0-59)
│ ┌───────────── hour (0-23)
│ │ ┌───────────── day of month (1-31)
│ │ │ ┌───────────── month (1-12)
│ │ │ │ ┌───────────── day of week (0-6, Sun=0)
│ │ │ │ │
* * * * *
| Schedule | Meaning |
|---|---|
*/5 * * * * |
Every 5 minutes |
0 * * * * |
Every hour (at minute 0) |
0 0 * * * |
Every day at midnight |
0 9 * * 1 |
Every Monday at 9:00 AM |
0 0 1 * * |
First day of every month |
30 2 * * 1-5 |
Weekdays at 2:30 AM |
0 */6 * * * |
Every 6 hours |
0 9,17 * * * |
At 9:00 AM and 5:00 PM daily |
Exam tip: Memorize the field order: minute, hour, day-of-month, month, day-of-week. The exam will test your ability to write correct cron expressions.
Creating a CronJob
Imperative (Fast for Exams)
kubectl create cronjob db-backup --image=busybox:1.36 \
--schedule="0 2 * * *" \
-- /bin/sh -c "echo 'Backup at $(date)'"
Declarative (YAML)
apiVersion: batch/v1
kind: CronJob
metadata:
name: db-backup
spec:
schedule: "0 2 * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: backup
image: busybox:1.36
command: ["/bin/sh", "-c"]
args: ["echo 'Database backup started at $(date)' && sleep 10 && echo 'Backup completed'"]
restartPolicy: OnFailure
kubectl apply -f db-backup.yaml
# Check the CronJob
kubectl get cronjobs
# Expected:
# NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
# db-backup 0 2 * * * False 0 <none> 10s
# Manually trigger a CronJob run (useful for testing)
kubectl create job db-backup-test --from=cronjob/db-backup
CronJob YAML Structure
apiVersion: batch/v1
kind: CronJob
metadata:
name: <cronjob-name>
spec: ← CronJob spec
schedule: "*/30 * * * *" ← Cron expression
concurrencyPolicy: Forbid ← How to handle overlaps
startingDeadlineSeconds: 60 ← Max late start
successfulJobsHistoryLimit: 3 ← Keep N successful Jobs
failedJobsHistoryLimit: 1 ← Keep N failed Jobs
suspend: false ← Pause scheduling
jobTemplate: ← Job template
spec: ← Job spec
backoffLimit: 2
activeDeadlineSeconds: 300
template: ← Pod template
spec:
containers:
- name: <container>
image: <image>
command: [...]
restartPolicy: OnFailure
CronJob Configuration Options
| Field | Description | Default |
|---|---|---|
schedule |
Cron expression (required) | — |
concurrencyPolicy |
How to handle overlapping Jobs | Allow |
startingDeadlineSeconds |
Max seconds late a Job can start | None |
successfulJobsHistoryLimit |
How many successful Jobs to keep | 3 |
failedJobsHistoryLimit |
How many failed Jobs to keep | 1 |
suspend |
Pause the CronJob | false |
Concurrency Policy
What happens when a new scheduled run starts while the previous one is still running?
| Policy | Behavior |
|---|---|
Allow |
Multiple Jobs can run at the same time (default) |
Forbid |
Skip the new Job if the previous one is still running |
Replace |
Kill the running Job and start a new one |
# Prevent overlapping backups
spec:
concurrencyPolicy: Forbid
When to Use Each
| Policy | Use When |
|---|---|
Allow |
Jobs are independent and can safely overlap |
Forbid |
Jobs would conflict (e.g., two database migrations at once) |
Replace |
Only the latest run matters (e.g., cache refresh) |
Generating CronJob YAML Quickly
# Generate YAML without creating the CronJob
kubectl create cronjob my-cron --image=busybox:1.36 \
--schedule="0 * * * *" \
--dry-run=client -o yaml \
-- /bin/sh -c "echo hello" > cronjob.yaml
# Edit to add concurrencyPolicy, historyLimits, etc.
vi cronjob.yaml
Next: Learn operational commands with Managing Jobs & CronJobs →