Kubernetes CronJob Guide
Kubernetes' CronJob resource creates a new Job (and therefore a new Pod) on a schedule, using the exact same standard 5-field cron syntax as Linux — but wrapped in a YAML manifest with its own concurrency, history, and deadline controls that a plain crontab doesn't have to think about.
Syntax Notes
The `schedule` field accepts standard 5-field cron syntax (no seconds field, no @nicknames in older versions — check your cluster's Kubernetes version). Everything else (concurrencyPolicy, successfulJobsHistoryLimit, startingDeadlineSeconds) is Kubernetes-specific YAML, not part of cron itself.
Examples
apiVersion: batch/v1
kind: CronJob
metadata:
name: nightly-backup
spec:
schedule: "0 2 * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: backup
image: my-backup-image:latest
restartPolicy: OnFailurespec:
schedule: "*/5 * * * *"
concurrencyPolicy: Forbid
startingDeadlineSeconds: 60Gotchas
- CronJobs schedule in the Kubernetes controller manager's timezone — historically UTC by default in most managed clusters, though newer Kubernetes versions (1.24+) support a `timeZone` field directly on the CronJob spec.
- By default, `concurrencyPolicy: Allow` lets overlapping Job runs stack up if a previous run is still going — for anything non-idempotent, set it to `Forbid` (skip a run if the previous is still active) or `Replace` (kill the old one and start fresh).
- A CronJob that's suspended, or whose controller was down at the scheduled time, can miss a run entirely if it falls outside `startingDeadlineSeconds` — Kubernetes doesn't guarantee catch-up execution the way anacron does on Linux.
Best Practices
- Always set `concurrencyPolicy` explicitly rather than relying on the `Allow` default, especially for jobs that write to shared state.
- Set `successfulJobsHistoryLimit` and `failedJobsHistoryLimit` to reasonable small numbers (e.g. 3 and 1) — Kubernetes keeps completed Job objects around by default, and they accumulate indefinitely otherwise.
- Use `kubectl create job --from=cronjob/<name> manual-run` to trigger an ad-hoc run for testing without waiting for the schedule or editing the CronJob itself.
Frequently Asked Questions
- Does Kubernetes CronJob support 6-field (with seconds) cron syntax?
- No — the schedule field uses standard 5-field cron with no seconds field, same as Linux. The minimum granularity is one minute.
- What timezone does a CronJob run in?
- By default, the kube-controller-manager's timezone (commonly UTC on managed clusters). Kubernetes 1.24+ supports an explicit `timeZone` field on the CronJob spec (using IANA timezone names) to avoid this ambiguity.
- How do I debug a CronJob that never runs?
- Check `kubectl get cronjob` for the schedule and suspend status, `kubectl get jobs` to see if Jobs were even created, and `kubectl describe cronjob <name>` for events — a common cause is the controller being unable to create Jobs due to resource quotas or RBAC permissions.
Related Tools
Platform Guides
Cron syntax for Linux, Kubernetes, AWS, and more
GitHub Actions Cron Guide
Schedule GitHub Actions workflows with cron syntax: the schedule trigger, UTC-only timing, and why scheduled workflows can be delayed.
AWS EventBridge Scheduler Cron Guide
How cron and rate expressions work in AWS EventBridge Scheduler: 6-field Quartz-style syntax, UTC timing, and common Lambda trigger patterns.