Skip to content
cron.surf

Run a Kubernetes CronJob on the first Monday of every month

Kubernetes has no exact expression for “First Monday of the month”. Here is why, a workaround, and the platforms that can do it. A Kubernetes CronJob reads five-field cron in spec.schedule and starts a Job for each run.

Why Kubernetes can’t do this exactly

Defined on Quartz as 0 0 9 ? * 2#1 · “At 09:00, on the first Monday of the month”

  • day of week: Kubernetes has no “nth weekday of the month” (2#1).

    WorkaroundRun on the day-of-month part and exit in the job unless it is the right weekday.
    0 9 1-7 * *  # job: [ "$(date +%w)" = "1" ] || exit 0
    Not equivalent on its own: it needs a check inside the job.

Kubernetes gotchas

Day of week is 0-6The schedule parser stops at 6. Write 0 for Sunday; 7 is an error.
Too many missed startsIf a CronJob misses more than 100 starts, the controller stops starting it. Set startingDeadlineSeconds so old misses stop counting.
Overlapping runsconcurrencyPolicy defaults to Allow, so a slow Job can overlap the next one. Use Forbid or Replace.
*/n in a day field counts as setOnly * or ? leave a day field open. 0 0 */2 * 1 runs on odd days or on Mondays, while Vixie cron reads it as odd days that are Mondays.

FAQ

What is the Kubernetes cron expression for “First Monday of the month”?

There is none that matches exactly. Kubernetes has no “nth weekday of the month” (2#1).

Which time zone does a Kubernetes schedule use?

Without spec.timeZone, in the local zone of kube-controller-manager, which is usually UTC. Set spec.timeZone (stable since Kubernetes 1.27) to an IANA name. CRON_TZ or TZ inside schedule is rejected.

Does a CronJob support @daily?

Yes. @yearly, @monthly, @weekly, @daily and @hourly work in spec.schedule.

Why did my CronJob run twice, or not at all?

A CronJob creates about one Job per scheduled time, not exactly one. Make the Job safe to repeat, and check startingDeadlineSeconds and concurrencyPolicy.