Andrew Savinykh
Andrew Savinykh

Reputation: 26300

How to make CronJob respect daylight saving time?

Let's say I and the partner company I'm dealing with live in a country that employs Daylight Saving Time.

I have a CronJob in a kubernetes cluster that uploads files to the partner company daily at, say, 4:00, 10:00, 16:00, and 22:00. E.g. 0 4,10,16,22 * * *.

Kubernetes SIG decided that CronJob object will not support local timezone and will always run in the default one, which is UTC.

I can change the schedule, so that it reflects local time specified above in UTC and give the CronJob that schedule. However every time daylight saving kicks in (twice a year) I would need somehow modify all the CronJobs to use the new time, and I need to modify my deployment pipeline to create new releases of the CronJobs with the new time.

I cannot keep the CronJob running on the same schedule past daylight saving change, as the job will upload files not during the times expected by the partner.

What is the easiest way to manage this?

Option 1

It was suggested that writing a new kubernetes controller could do, but it does not seem that anyone raised up to that challenge and published working solution.

Option 2

Another option I have considered is changing the timezone of the entire cluster. But if you google it it does not seem to be very popular solution, and some people strongly believe that kubernetes being a cloud application should be run in UTC.

From what I understand cron uses a local time zone which, in case of kubernetes will be the timezone of the controller manager, which is not necessary a timezone of the node it is running on. On the other hand, changing time zone of the controller manager container, sounds risky, as it is not clear how it will interact with other components of the kubernetes, such as etcd and kubelets.

Option 3

Doing it manually twice a year. Since people in the organisation come and go it would be difficult to retain the knowledge when and how. I do not want our partner to complain twice a year. Also it might be tricky to set up notifications for this as the dates change every year.

Option 4

Write some homegrown automation to run twice a year and hope that when time comes it works as expected. That is actually triggers, triggers at the right time and does everything it's supposed to do. (the latter is easier to test but the former is harder).

All these options feel quite unsatisfactory. I googled a lot and I have not found a lot, I feel it should be quite common issue, and yet nothing comes up in the search. Am I overlooking something? Is there an easy and natural way to solve it?

Upvotes: 16

Views: 12134

Answers (4)

Andrew Savinykh
Andrew Savinykh

Reputation: 26300

Time Zones was added to CronJob in Kubernetes 1.22. To cite github thread

Just to clarify, it's available in 1.22.

It was implemented in a very strange way that's not exposed in the schema, though. I'm not aware of any explanation for why that was done, and it ignores core concepts behind Kubernetes. I think this still needs work.

It can be done via CRON_TZ variable, as described here.

#      ┌────────────────── timezone (optional)
#      |      ┌───────────── minute (0 - 59)
#      |      │ ┌───────────── hour (0 - 23)
#      |      │ │ ┌───────────── day of the month (1 - 31)
#      |      │ │ │ ┌───────────── month (1 - 12)
#      |      │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday;
#      |      │ │ │ │ │                                   7 is also Sunday on some systems)
#      |      │ │ │ │ │
#      |      │ │ │ │ │
# CRON_TZ=UTC * * * * *

Update

This feature is to be marked as unsupported

Update

Since Kubernetes 1.27 time zones in CronJobs are now supported.

kind: CronJob
apiVersion: batch/v1
metadata:
  name: myCronjob
spec:
  schedule: "10 1 * * *"
  timeZone: Pacific/Auckland
  concurrencyPolicy: Forbid
  jobTemplate:
    spec:
      template:
        metadata:
          name: myCronjob
          labels:
            app: myCronjob
        spec:
...

Upvotes: 2

linoor
linoor

Reputation: 241

Starting from kubernetes 1.24/1.25 there is a feature gate CronJobTimeZone that allows you to set .spec.timeZone to the name of a valid time zone. For example, setting .spec.timeZone: "Etc/UTC" instructs Kubernetes to interpret the schedule relative to Coordinated Universal Time. The feature gate is disabled by default in version 1.24 and enabled by default in version 1.25

Upvotes: 1

kvantour
kvantour

Reputation: 26481

Maybe I come a bit late to the party, but I believe that the easiest is to have two cronjobs running in combination with a tz-check. When the time-zone matches the expected value, only then run command

A very nice post of detecting Daylight Saving Time, can be found here. Copying its examples, we can show that for the time-zone TZ=Europe/Stockholm, the time-zone changes to summer time depending on the date :

$ TZ=Europe/Stockholm date +%Z # CET or CEST depending of when its run
$ TZ=Europe/Stockholm date --date=20170101 +%Z # CET
$ TZ=Europe/Stockholm date --date=20170601 +%Z # CEST
$ TZ=CET date --date=20170101 +%Z # CET
$ TZ=CET date --date=20170601 +%Z # CEST, note that its auto adjusted to CEST

So, when staying in this example and assume the OP wants to run his cron on different times depending on if we are in DST or not, we could write the following crontab:

# Example of job definition:
# .--------------------- minute (0 - 59)
# |    .---------------- hour (0 - 23)
# |    |     .---------- day of month (1 - 31)
# |    |     |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |    |     |  |  .---- day of week (0 - 6) (Sunday=0 or 7)
# |    |     |  |  |
# command only runs in Europe/Stockholm Winter time
  0  4-23/6  *  *  *   tz-test "Europe/Stockholm" "CET"  && command
# command only runs in Europe/Stockholm Summer time
  0  3-23/6  *  *  *   tz-test "Europe/Stockholm" "CEST" && command

Here, the times in the crontab definition are given in UTC (as the cron runs in UTC) and the tz-test command is something like:

#!/usr/bin/env bash
tz=$(TZ="$1" date "+%Z")
[ "$tz" == "$2" ]

Note: You still have to be careful here. It might be possible that, due to the time-selection, your crontab runs twice or even more on the day the hour changes. In the above example, this is not the case.

Note: while this question was for Kubernetes, I'm convinced a similar implementation can be achieved within that framework.

Upvotes: 0

Ben Smith
Ben Smith

Reputation: 72

I know this is an old question but argo workflows has a Cron Workflows CRD that supports timezones and daylight saving. https://argoproj.github.io/argo-workflows/cron-workflows/#daylight-saving.

Upvotes: 0

Related Questions