Kubernetes Cron Expression for CronJobs
A Kubernetes cron expression goes in the spec.schedule field of a CronJob and uses the standard five fields. Build the schedule below, then check the time zone and missed-run settings that decide what really happens.
The short answer
A Kubernetes cron expression goes in the spec.schedule field of a CronJob and uses the standard five fields. Set spec.timeZone if you do not want the controller's local time.
apiVersion: batch/v1
kind: CronJob
metadata:
name: nightly-report
spec:
schedule: "30 2 * * *"
timeZone: "Etc/UTC"
concurrencyPolicy: Forbid
startingDeadlineSeconds: 300
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: report
image: registry.example.com/report:1.4This runs at 02:30 UTC daily. If a run is more than 300 seconds late it is skipped, and a run is skipped while the previous one is still going.
Build a Kubernetes CronJob schedule
Set the fields and the output follows Kubernetes rules, with the next runs in your time zone. Copy the result or open it in the full Generator.
Kubernetes cron expression syntax
The schedule follows standard five-field cron: minute, hour, day of month, month and day of week, with weekdays as 0-6 or names. Step values such as */2 and 0-23/2 are supported. A ? is accepted and means the same as *. There is no seconds field and no L, W or #; see the cron special characters reference for what those do elsewhere.
Kubernetes also accepts macros:
| Macro | Same as |
|---|---|
@yearly or @annually | 0 0 1 1 * |
@monthly | 0 0 1 * * |
@weekly | 0 0 * * 0 |
@daily or @midnight | 0 0 * * * |
@hourly | 0 * * * * |
Kubernetes cron expression examples
Load one into the builder above to change it, then paste the result into spec.schedule.
| Expression | What it does | Use |
|---|---|---|
*/5 * * * * | Runs every 5 minutes. | Load |
0 * * * * | Runs every hour, on the hour. | Load |
30 2 * * * | Runs at 2:30 AM every day. | Load |
0 9 * * 1-5 | Runs at 9:00 AM every weekday (Mon-Fri). | Load |
0 3 * * 1 | Runs at 3:00 AM every Monday. Weekly on Monday. | Load |
0 0 1 * * | Runs at 12:00 AM on day 1 of every month. | Load |
Time zone: the controller default and spec.timeZone
With no time zone set, the schedule is read in the local time zone of the kube-controller-manager, which on many clusters is UTC but is not guaranteed to be. Set .spec.timeZone to an IANA name such as America/New_York or Etc/UTC to remove the doubt. This field has been stable since Kubernetes v1.27.
Do not put CRON_TZ= or TZ= inside the schedule string. Kubernetes documents that this is not supported, and the API rejects the resource with a validation error. For conversions and daylight saving time see the cron timezone converter.
Missed runs, deadlines and overlapping jobs
startingDeadlineSecondsis how late a Job may start. After the deadline that run is skipped and counted as failed. A value under 10 seconds may stop the CronJob from being scheduled, because the controller checks every 10 seconds.- The 100 missed schedules rule. If the controller counts more than 100 missed schedules since the last one, it does not start the Job and logs
too many missed start times. SettingstartingDeadlineSecondslimits the window it counts. concurrencyPolicyisAllowby default.Forbidskips a run while the previous Job is running, andReplacestops the old Job and starts a new one.- Approximate scheduling. Kubernetes can in rare cases create two Jobs or none for one scheduled time, so write Jobs that are safe to repeat.
Common mistakes with Kubernetes cron expressions
- Using AWS or Quartz syntax with a leading seconds field or a year. Check it with the cron expression validator.
- Assuming the schedule is in your local time. It is not unless
timeZoneis set. - Running a long Job on a short interval with the default
Allow, so runs pile up. UseForbidor a longer interval; see cron every 5 minutes. - Editing a CronJob and expecting running Jobs to change. Existing Jobs continue unchanged.
Sources and further reading
Use a tool
Try the schedule from this page in a tool.