highIntermediateSymptom-first#cronjob#scheduling#timezone#jobs

CronJob not running — suspended, schedule mismatch, or timezone issue

No new Jobs created for a CronJob past its scheduled time

Likely source:availabilitydeployment

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 yaml
  • Job 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}'
READ

Check suspend status

Fix

kubectl patch cronjob <cronjob> -n <namespace> --type merge -p '{"spec":{"suspend":false}}'
CHANGE

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.

1
kubectl get cronjob <cronjob> -n <namespace> -o yaml | grep -E 'schedule|suspend|timeZone'
READ

Read the schedule and suspend status

2
kubectl get jobs -n <namespace> --sort-by=.metadata.creationTimestamp | tail -10
READ

Check Job history

3
kubectl patch cronjob <cronjob> -n <namespace> --type merge -p '{"spec":{"suspend":false}}'
CHANGE

Unsuspend if suspended

4
kubectl create job <cronjob>-manual-$(date +%s) --from=cronjob/<cronjob> -n <namespace>
CHANGE

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.

Commands marked READ CHANGE DESTRUCTIVE — never run DESTRUCTIVE commands against production data you cannot restore. Copy → verify → execute.