CronJob not running — suspended, schedule mismatch, or timezone issue
No new Jobs created for a CronJob past its scheduled time
Focused incident mode — strips away everything but this runbook.
Symptoms
- No new Jobs created for a CronJob past its scheduled time
- kubectl get cronjob shows Suspend=true
- Last Schedule time is stale or shows schedule-timezone mismatch
Kubernetes CronJobs use UTC by default. If you need local timezone, set .spec.timeZone (requires Kubernetes 1.27+). Schedule syntax is standard 5-field cron.
Evidence to grab
Collect these artifacts before you change anything — they prove (or rule out) each cause.
CronJob status
kubectl get cronjob <cronjob> -n <namespace> -o yamlJob history
kubectl get jobs -n <namespace> --sort-by=.metadata.creationTimestamp | tail -10
Diagnostic flow
Run the steps in order, marking each claim confirmed or refuted. The evidence you gather feeds the ranked causes below.
Guided decision tree is ready.
Steps with commands, expected output, and pass/fail branches.
Ranked root causes
Evidence checklist
- kubectl get cronjob shows Suspend=true
- No new Jobs since it was suspended
Confirm before fixing
kubectl get cronjob <cronjob> -n <namespace> -o jsonpath='{.spec.suspend}'Check suspend status
Fix
kubectl patch cronjob <cronjob> -n <namespace> --type merge -p '{"spec":{"suspend":false}}'Unsuspend the CronJob
Expected: cronjob.batch/<cronjob> patched
Resolution runbook
Apply from top to bottom after the cause is confirmed. Review every command before running it — risk tags are shown on each.
kubectl get cronjob <cronjob> -n <namespace> -o yaml | grep -E 'schedule|suspend|timeZone'Read the schedule and suspend status
kubectl get jobs -n <namespace> --sort-by=.metadata.creationTimestamp | tail -10Check Job history
kubectl patch cronjob <cronjob> -n <namespace> --type merge -p '{"spec":{"suspend":false}}'Unsuspend if suspended
kubectl create job <cronjob>-manual-$(date +%s) --from=cronjob/<cronjob> -n <namespace>Manually trigger a job to test
Prevention
- Set timeZone explicitly on CronJobs that need local schedule.
- Monitor lastScheduleTime and alert if stale for > 2x the schedule interval.
- Use suspend=true for maintenance windows instead of deleting the CronJob.
- Set failedJobsHistoryLimit and successfulJobsHistoryLimit to avoid resource leaks.
Related runbooks
Same stack, same failure family — worth a skim.
kubectl get job shows Failed status with backoffLimitExceeded
kubectl rollout status hangs on 'Waiting for rollout to finish'
Commands marked READ CHANGE DESTRUCTIVE — never run DESTRUCTIVE commands against production data you cannot restore. Copy → verify → execute.