Jenkinsのスケジュール実行をシステムのタイムゾーンとは、異なるタイムゾーンで実行する。

2016.09.09

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

好物はインフラとフロントエンドのかじわらゆたかです。
Jenkinsでスケジュールでジョブを実行するってケースはよくあると思うのですが、
システムともJenkinsに渡しているUserのタイムゾーンとも異なるタイムゾーンのスケジュールを組みたい。
そんなケースの対応方法になります。

システムと異なるタイムゾーンでJenkinsを起動する

まずは、前段として単純に指定したいタイムゾーンがシステム以外に1つしかない場合、
例えば、システムのタイムゾーンはUTCだけど、Jenkins内の時刻はJSTとして設定したい。
この場合、JenkinsをJSTで起動させることで対応が可能です。

これについては至る所で紹介もされている方法になります。
Change time zone

上記を参考に、Jenkinsの起動オプションとして変更したいタイムゾーンを渡すなり、設定ファイルに書き込めば問題ありません。

Dockerで起動する際も、以下のように引数で渡して上げれば問題ありません。

docker run --name jenkins -d -v /docker_volumes/jenkins:/var/jenkins_home -p 8080:8080 -e JAVA_OPTS='-Duser.timezone=Asia/Tokyo -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8' jenkins

上記で起動したJenkinsでスケジュールを設定してみると、正しく起動予告時間も表示されている事がわかります。
dateCheck_Config__Jenkins_01

設定したジョブもJSTの15:08 UTCの06:08で動いていることがわかります。

定期的に実行
masterでビルドします。 ワークスペース: /var/jenkins_home/workspace/dateCheck
[dateCheck] $ /bin/sh -xe /tmp/hudson6632341593127844001.sh
+ date
Fri Sep  9 06:08:01 UTC 2016
Finished: SUCCESS

日本のようにタイムゾーンが一つしかない環境においては、Jenkinsにtimezoneを設定して起動することで、
ジョブのスケジュール実行で混乱するといったケースは回避できるかと思います。

システムタイムゾーンとも、ユーザーのタイムゾーンとも異なるタイムゾーンのスケジュールでジョブを起動する

以前社内で、こんな話をしたことがあります。

日本のエンジニアはTimezoneはあるし、マルチバイトはあるし、
いざ実装しようとすると考えなくてはいけないことがたくさんある。
でもそんな日本のエンジニアにとって唯一ラッキーだったのは、複数のタイムゾーン対応が無縁だったってことだよね。

まさにその通りだとは思うのですが、
もし複数のタイムゾーンにまたがる設定を行わなければならない場合はどうすればよいでしょうか?
AというジョブはJSTの9:00に起動して、BというジョブはUTCの11:00、
CというジョブはCET(中央ヨーロッパ時間)の3時でよろしくなんて言われた日には途方にくれることでしょう。

ですが、実はJenkinsはTimezoneを指定してスケジュール実行をするといった機能が実は実装されています。
[JENKINS-9283] Add timezone to cron expression - Jenkins JIRA

チケットの起票が2011/Apr/08 1:05 AMで、Resolveが2016/Apr/25 1:05 PM となっており、
実際に公開されたのが、2015/May/25 となっているので長年待望まれていた機能だったと思われます。
なお、Jenkinsのバージョンとしては、1.615以降が対象となります。

What's new in 1.615 (2015/05/25)
CronTab API: Timezone support for scheduling (issue 9283)

Changelog

スケジュールのパラメータの中に、Timezoneを記載するのですがそのルールが癖があります。

  • TimeZone.getTimeZone(specTimezone) で取得できるフォーマットで。
  • TZ=の後はダブルクォート不要

そのため、上記の例を記載する場合は以下のようになります。

JSTの09:00に起動

TZ=JST
00 09 * * *

UTCの11:00に起動

TZ=UTC
00 11 * * *

CETの03:00に起動

TZ=CET
00 03 * * *

上記の用に書くことで、Timezoneを指定してスケジュールを実行することが可能です。
ただ、この機能用いて時間を設定する際に、起動予告時間はスケジュール内で設定しているTimezoneを反映してくれません。
具体的には以下のようになります。 dateCheck_Config__Jenkins_02

上記の環境はJSTをユーザーのタイムゾーンとして渡してJenkinsを起動している環境なのですが、
ジョブをCETの3:00に起動するように設定したのですが、
CETの3:00は反映されておらず、JSTの3:00に起動する旨の文言が表示されています。

ですが、実際にはCETの3:00に当該ジョブは起動することになります。

実際に異なるタイムゾーンで設定したスケジュールが動くか確認してみる

dateCheck_Config__Jenkins_03 このブログを書いているのがJST 16:36なので、CET 9:40に起動するように設定してみたところ、
以下のように起動したことが確認できました。 dateCheck_Config__Jenkins_04

dateCheck_Config__Jenkins_05

まとめ

実行予定時間が正しく表示されない等の挙動が怪しい箇所は有りますが、
Jenkinsを用いて複数のTimezoneでサービスを展開するといった際に、
時間の指定間違えを回避するのに役立つ機能かと思われます。