Developer guide
Kubernetes CronJob schedule: The Field-by-Field Guide
A Kubernetes CronJob runs a container on a schedule defined by spec.schedule. The expression is plain 5-field cron — but timezones, concurrency and missed-run policy are where real clusters go wrong. Here is everything, with YAML you can paste.
Written by Benjamin Rotshtein
Updated
How does the schedule field work in a Kubernetes CronJob?
The spec.schedule field takes a standard 5-field cron expression that the Kubernetes controller evaluates. It follows classic cron semantics but with a few differences: no seconds field, UTC-based local time by default, and no support for some expression tricks. This guide walks every field, the differences, timezone handling and concurrency.
- Schedule field format?
- Standard 5-field cron: minute hour day-of-month month day-of-week. No seconds field.
- Every 5 minutes?
schedule: "*/5 * * * *"- Run only on weekdays at 9am?
schedule: "0 9 * * 1-5"
1. A minimal CronJob
apiVersion: batch/v1
kind: CronJob
metadata:
name: nightly-backup
spec:
schedule: "0 2 * * *" # 02:00 every day, controller-local time
concurrencyPolicy: Forbid # never overlap runs
startingDeadlineSeconds: 300 # give the controller 5 min of grace
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: backup
image: busybox:1.36
command: ["sh", "-c", "echo backup at \$(date)"]2. The schedule field: 5 fields, same rules as cron
The string in spec.schedule follows the standard 5-field cron layout:
┌────────────── minute (0-59) │ ┌──────────── hour (0-23) │ │ ┌────────── day of month (1-31) │ │ │ ┌──────── month (1-12, or JAN-DEC) │ │ │ │ ┌────── day of week (0-6, or SUN-SAT; Sunday=0) │ │ │ │ │ * * * * *
Every operator works: lists 1,15, ranges MON-FRI, steps */15. If a field is * it matches every value. The controller resolves the next time from the schedule and creates a Job when it arrives.
Note there is no seconds field — a Kubernetes schedule cannot run more often than once a minute. For sub-minute cadences you run a long-lived pod (Deployment) that sleeps in a loop, not a CronJob.
3. Real schedule examples
| Schedule | spec.schedule |
|---|---|
| Every minute | * * * * * |
| Every 5 minutes | */5 * * * * |
| Every 6 hours | 0 */6 * * * |
| Daily at 02:00 | 0 2 * * * |
| Weekdays at 09:00 | 0 9 * * 1-5 |
| First day of month at midnight | 0 0 1 * * |
| Every Sunday 23:30 | 30 23 * * 0 |
4. Timezone handling (stable since Kubernetes 1.27)
Without configuration, the schedule is evaluated in the Kubernetes controller-manager’s local time. If your nodes are UTC and your team is in another zone, “2am” is 2am UTC. Since Kubernetes 1.27 the spec.timeZone field pins the schedule to an IANA zone:
spec: schedule: "0 9 * * 1-5" timeZone: "Europe/Berlin" # weekdays at 09:00 Berlin, DST-aware
On clusters older than 1.27 (or if you avoid the field for compatibility), set the container’s TZ environment variable — that fixes the job’s clock, not the schedule’s, so keep the expression in UTC and convert inside the container.
5. Concurrency, missed runs and deadlines
Three fields decide what happens when a run is slow, missed or the cluster was down:
- concurrencyPolicy —
Allow(default) starts a new Job even if the previous is still running,Forbidskips the run,Replacekills the running one and starts fresh. - startingDeadlineSeconds — how long after a missed schedule the controller will still start the Job. Without it, a long cluster outage can trigger a burst of backlogged jobs.
- successfulJobsHistoryLimit / failedJobsHistoryLimit — how many completed or failed Jobs to keep (defaults 3 and 1). Failed pods leave Jobs behind; set these to keep your cluster tidy.
6. Sanity-check your schedule before you ship it
A single wrong field makes the Job fail to create or fire at the wrong time. Paste your expression into the cron generator to get the plain-English meaning and the next 5 fire times, or use the cron to English tool for a quick translation before it reaches your cluster.
Frequently asked questions
What format does a Kubernetes CronJob schedule use?
The spec.schedule field uses standard 5-field cron syntax: minute hour day-of-month month day-of-week. Examples: "*/5 * * * *" every 5 minutes, "0 9 * * 1-5" weekdays at 9am, "0 0 1 * *" first of the month at midnight. It is the same format used by Linux cron, without the 6-field seconds variant.
How does a CronJob schedule differ from regular cron?
The expression format is the same, but execution differs: each CronJob creates a new Job (a pod) per scheduled run, with concurrencyPolicy controlling whether runs can overlap (Allow, Forbid or Replace). A regular cron daemon launches a process on the host; a CronJob schedules a container.
How do I run a Kubernetes CronJob every hour?
Set spec.schedule to "0 * * * *" — minute 0 of every hour. For every 6 hours use "0 */6 * * *", and for every 5 minutes use "*/5 * * * *". Kubernetes computes the next run from the CronJob controller's timezone and creates the Job at the next matching time.
Does a Kubernetes CronJob support timezones?
Since Kubernetes 1.27 the spec.timeZone field is stable: set it to an IANA zone like "Europe/Berlin" and the controller schedules runs in that zone. On older clusters you can compensate by setting the TZ environment variable inside the container, but the schedule itself is evaluated in the controller's local time.
Why is my CronJob not running?
Check the schedule field is valid (a malformed expression makes the Job fail to create), confirm the pod is scheduled (kubectl get cronjobs and kubectl describe cronjob), verify imagePullPolicy and registry access, and look for failed Jobs with kubectl get jobs — a failed pod leaves the Job in the failed state you can inspect with kubectl logs.
Can a CronJob use a 6-field or seconds-based schedule?
No. Kubernetes evaluates spec.schedule with the 5-field standard cron format only — there is no seconds field. For sub-minute cadence, use an alternate workload such as a Deployment running a sleep loop, KEDA, or an application-level scheduler like APScheduler or node-cron.
Related guides
The cron cheat sheet covers every field and operator in the same format CronJob uses, and cron not running explains the environment pitfalls that also bite scheduled containers.