閏秒を迎えるにあたってLinuxでは何を対策すべきか?

DevOps
スポンサーリンク

2016/12/27 更新

Googleなどの大手IT企業がうるう秒対策済のNTPサーバが公開したため、これを利用する内容などを以下にまとめました。

2016/07/08 更新

2017/1/1に閏秒の実施が決定されました。対応はこの記事のとおりで問題なさそうです。

2015/06/24 情報追加(2015/06/29 更新)

下記の対応に関わるntpdの比較的新しいバージョンにSLEWモードで動作していても、うるう秒が挿入されるバグが発見されました。[redhat]
これによりntp-4.2.8p3-RC1以降のバージョンでないとSLEWモードで動作していてもうるう秒が挿入されます。RedHatはntp-4.2.6p5-3.el6_6という対応済みのバージョンを提供しています。Ubuntuでは今日現在12.04LTS, 14.04LTSの2バージョンはパッケージが提供されていないようなので独自に作る必要性があります。(個人的には独自パッケージに入れ替えると今後のバージョンアップに追従などがやりにくくなるので、ntpdを停止を推奨します。)

  • うるう秒を挿入させない
  • 時間遡行をさせない
  • 08:59:60 を刻ませない

以上を達成するためには

  • 上記のバグ対応ずみのntpdをSLEWモードで起動させて7/1 9:00を向かえる

もしくは

  • 7/1 9:00の前にntpdを停止、9:01以降にntpdをSLEWモードで起動
    • 6/30 9:00にふってくるLeap Indicatorをすでに受信している場合は起動前にntptime -s 0 -f 0を実行しLeap Indicatorのフラグをリセットしておく

以上の2通りの切り抜け方となります。

元記事はここからです。


日本時間の2015年7月1日にうるう秒が追加されることが発表されました。

ネットニュースでも取り上げられてますが、結局、何すればいいのかわかりませんでした。前回のうるう秒が発生した2012年に起きた問題を踏まえて、いろいろ調べてまとめてみました。
これで完璧とは言えないかもしれませんが、閏秒を迎えるにあたってやることがだいたいわかるかと思います。
間違った認識などがあれば、ご指摘いただけると助かります。

うるう秒とは?

世界時のUT1と協定世界時のUTCの差を差を±0.9秒以内に保つためにうるう秒による調整が実施されます。今まで調整されたうるう秒の調整はいずれも1秒の追加です。
この調整は国際地球回転・基準系事業(IERS。国際観測を実施)が決定するようです。

調整の実施日は?

調整の実施日は協定世界時 (UTC) の月末とされ、年12回の可能性があります。
ですが、第一優先が6月末日または12月末日、第二優先が3月末日または9月末日です。
これまでの実際の運用では第一優先の6月末日または12月末日だけで間に合っているようです。
日本時間(JST)はUTCから+9時間であるため

  • 7月1日午前9時
  • 1月1日午前9時

に調整が実施されることになります。
参考:標準時・周波数標準のQ&A 周波数と時刻に関するQ & A

1秒を追加するとは?

今までのうるう秒の調整がすべて1秒の追加だったので、1秒追加する場合について説明します。
通常であれば7月1日の「08:59:59」の次の時刻は「09:00:00」となります。
うるう秒が調整される場合は
「08:59:59」の次の時刻は「08:59:60」となり、次の時刻は「9:00:00」となります。
実際に末尾が60秒が追加されている2012年のうるう秒を撮影した動画がありましので目を凝らして確認してみてください。

うるう秒によって起きた問題

前回うるう秒が調整された2012年7月1日にはLinuxサーバのプロセスがCPU100%に張り付くという現象などが発生しました。これによりサービスが停止したものが数多くありました。

身近なソフトウェアで言うとMySQLやJavaがCPU100%に張り付くというような現象が起きたようです。

原因は?

根本的な原因はLinuxカーネルの不具合によるものです。下記のサイトがとても詳しく解説しています。細かいところまで知りたい方はそちらを参照してください。

2012年の時には古いバージョンのLinuxカーネルには発生せず、比較的新しいバージョンにこの問題が発生していました。よって、最新のカーネルにすれば同様の問題は発生しません。とは単純に言い切れない問題でした。
その後、Linux Test Projectなどで、うるう秒の対応などをRedHat社は発表しているので、2015年の今回のうるう秒の対策としては、最新のLinuxカーネルにバージョンを上げておけば同様の問題は発生しないことが期待できます。
ですが、変更の激しいLinuxカーネルなので、約3年立ってLinuxカーネルが前回のように変更が加えられていることによって発生する可能性も少なからずあります。よって、Linuxを運用している方は、自分の環境がうるう秒によって問題が起きる可能性を事前に調査しなければなりません。

問題となるLinuxのうるう秒の挙動

今回のうるう秒で問題が起きるのは、前回同様のことだけとは限りませんが、前回と同様の問題は起こさないように対処すべきです。
tzdataやntpdを利用しているケースなどで挙動が異なるので、それぞれの場合の挙動をまずは理解していきます。

ntpdを利用してないケース

まず、ntpdも利用せず、tzdataの更新などの対応をしないと、サーバの時間が1秒進んでしまうことなります。
「08:59:60」という時間がカウントされません。結果として1秒、時間がずれることになります。

うるう秒のデータを含んだtzdataを適応しているケース

次に2015年のうるう秒を含んだtzdataパッケージをアップデートし、適応されている場合です。
この状態でntpdを利用してない場合は「08:59:60」という時間がカウントされます。
これは「08:59:60」をカウントしても問題ない環境なら大丈夫。
個人的にはこれをカウントして大丈夫なのか?という判断が扱っているソフトウェア全てでできてません。

ntpdを利用しているケース

大抵の運用されているサーバはntpdが利用されているかと思います。
うるう秒が発生する年は事前に決められていないので、NTPプロトコルによって、うるう秒の調整が送られてきます。(Leap Indicatorを受け取っている)
これによって、Linuxカーネルに1秒追加されることが伝わります。
大抵のntpdはデフォルトのSTEPモードで起動されているため、Leap Indicatorを受け取り、うるう秒を刻むため、

23:59:59.000000(→ 23:59:59.999999)→ 23:59:59.000000 → 00:00:00.000000

というふうに同じ時刻を1秒ほど多く刻み、システムクロックに通知され、この挙動をトリガーにして2012年には7月1日に特定のLinuxカーネルのバージョンに不具合が起きました。
比較的新しいバージョンのLinux Kernelであれば対応がされているので特に問題は起きないはず。
ですが、あえてやることがあるとすれば、このように時間を刻まないことが、問題を同様の引き起こさないために必要な対応です。

STEPモードとSLEWモード

ここでntpdの挙動であるSTEPモードとSLEWモードについて簡単に解説します。
通常、ntpdは時間のずれが128msより小さかった場合はSLEWモードで時間の調整をします。それ以上の場合はSTEPモードで時間を調整します。

STEPモード

STEPモードでは不連続に一度に時刻を調整するため、時刻がずれている場合はすぐに正しい時刻に調整されていきますが、時間の逆行が発生する可能性があります。これによりソフトウェアに不具合が起きることがあります。

SLEWモード

SLEWモードは、時間を逆行させることはせず、最大でも0.5msずつ徐々に時間をずらしていきます。時刻がずれている場合には正しい時刻に調整するにの膨大な時間がかかります。例えば10秒ずれていると、これを調整するのに20000秒必要になります。

ntpdの設定

ntpdには-xオプションがあり、これをつけて起動すると128msだったしきい値が600sとなります。これにより、実質SLEWモードで常に動作しているような挙動になります。
またSLEWモードで起動しているとうるう秒を挿入しなくなります。(後述するLeap Indicatorがセットされない)
よって、7月1日9時の時点では最大1秒ずれていますが、徐々に正しい時間に調整されていく動作になります。
-xオプションについてはman ntpdで確認できます。
この閾値は-xオプションを付けなくともntpd.conftinkerで変更することも可能です。

tinker step 0

こうするとntpdはSTEPモードへの移行しなくなります。他にも色々と設定があるので詳しくはマニュアルを参照してください。
手元のUbuntu 14.LTSの場合ntpdは

/usr/sbin/ntpd -p /var/run/ntpd.pid -g -u 104:111

というように起動していました。
/etc/default/ntp

NTPD_OPTS='-g -x'

と変更してntpdを再起動すると

/usr/sbin/ntpd -p /var/run/ntpd.pid -g -x -u 104:111

-xオプション付きで起動しました。

Leap Indicatorを確認する方法

NTPによってうるう秒の情報が伝わってきているかの確認をする方法です。

$ ntpq -c rv
associd=0 status=0615 leap_none, sync_ntp, 1 event, clock_sync,
version="ntpd [email protected] Wed Oct  9 19:08:06 UTC 2013 (1)",
processor="x86_64", system="Linux/3.13.0-34-generic", leap=00, stratum=2,
precision=-17, rootdelay=21.629, rootdisp=950.751, refid=133.243.238.163,
reftime=d8593032.17d49c42  Fri, Jan  9 2015  1:34:58.093,
clock=d8593065.44e6a51e  Fri, Jan  9 2015  1:35:49.269, peer=33242, tc=6,
mintc=3, offset=0.996, frequency=0.193, sys_jitter=0.000,
clk_jitter=0.352, clk_wander=0.000

という情報が確認できます。leap=00というのがLeap Indicatorです。

  • 00 の場合は調整は発生しません
  • 01 正の調整が発生
  • 10 負調整が発生

どうすればいいのか?

うるう秒を迎えるにあたってどうすればいいのかをまとめます。

  • tzdatazパッケージを最新にして適応しておく
  • Linuxカーネルをアップデートしておく(古すぎるカーネルに一部クラッシュものがあるため)
  • ntpdのパッケージを最新にする(古いバージョンだとSLEWモードでもLIビットを立てるものがあるため)
  • 時刻とハードウェアクロックを正しい時間に合わせておく
  • ntpdを-xオプション付きで起動、もしくはtinkerでstepを調整

以上で前回のうるう秒で起きた同様のケースは防げるかと思います。
ですが、稼働しているアプリケーションやシステムがうるう秒の時間をどのようにカウントするかで影響があるか調査、判断しなければなりません。
そして、2015年7月1日午前9時はサーバの管理者の方は待機して迎えたほうが良さそうです。
仮にプロセスのCPUが100%に張り付くような2012年と同様の症状が発生した場合は、ntpdを停止して

# date `date +'%m%d%H%M%C%y.%S'`

か、再起動で2012年と同様の問題のケースは解決するようです。

参考

以下のサイトを参考にしました。

Linux Kernelの処理について書かれている資料

「4.4 カーネルソース解析の実例」において、kernel内部での時刻制御ついて書かれているらしいのでチェックする。

タイトルとURLをコピーしました