Man On a Mission

システム運用屋が、日々のあれこれや情報処理技術者試験の攻略を記録していくITブログ…というのも昔の話。今や歴史メインでたまに軍事。別に詳しくないので過大な期待は禁物。

Linux備忘録 ntpdの動作について

今日は唐突ながらntpdによる時刻同期の動作について。

ntpdは、Linuxで標準的に使われているNTPサーバ/クライアントです。
NTPは、ネットワーク上の機器の時刻を同期させる仕組みで、通常、信頼性の高い時刻源から時刻情報を取得して、各機器を正確な時刻に合わせるために利用します。
サーバの時刻がずれていると、ログに記録される時刻が当てにならなくなったり、メールの送受信時刻がおかしくなったりと色々問題が生じます。
そんなわけで、大抵のLinuxサーバでは、ntpdを用いて時刻同期を行っています。
近年、新たなNTP実装としてChronyが登場し、RHEL7/CentOS7ではそちらが標準採用となっておりますが、まだまだntpdで動作しているサーバが多いのではないでしょうか。

 第15章 chrony スイートを使用した NTP 設定(Redhat)

なお、今回記事ではNTP自体について詳しく触れないので、興味があるかたは下記をどうぞ。

eng-entrance.com

当記事についての注意点

今回の記事は、ntpdの動作について、私なりに調べたものであり、正確性については保証できません。
私の技術レベルは大したことが無いので、実際にシステム構築・運用を行う際には、当記事を鵜呑みにせず、より正確な情報源にてご確認ください。
当記事の信頼性は、たとえるなら甫庵信長記*1を下回り、どっかの英語学者が書き飛ばした日本史よりは少しマシなくらい。なお、このたとえはフィクションであり、怪しくはない。安心です。

ntpdによる時刻同期

さて、ntpdは、信頼性の高い時刻源から時刻情報を取得し、自動的にLinuxサーバの時計を正確な時刻に補正してくれます。
しかし、仮にLinuxサーバの時刻がずれていたとして、ここでいきなり正確な時刻に合わせたりすると、問題が生じることがあります。
どんな問題かは一概に言えないのですが、例を挙げると、時刻が巻き戻ってサービスが停止してしまったり*2、データベースの異常動作の原因になったりします。

そのため、ntpdでは二種類の時刻補正方法が用意されています。
いきなり時刻を合わせるstepモードと、徐々に時刻を合わせていくslewモードです。
ntpdでは、状況に応じて、どのモードで時刻補正するか自動的に決定されます。

stepモードでの補正

人間が時計を合わせるのと同じやり方です。
例えば、同期元の時刻源が20:00:00、Linuxサーバが20:05:00というように5分のズレがあった場合、いきなりLinuxサーバの時刻を20:00:00に合わせます。
この例では、Linuxサーバはいきなり5分間、時刻が巻き戻ることになります。
当然ながら、前述したサービス停止や異常動作を引き起こす可能性があり、サーバ稼働中のstepモードでの補正は出来るだけ避けたいところです。

slewモードでの補正

先ほど上げた例を再利用して、同期元の時刻源が20:00:00、Linuxサーバが20:05:00というように5分のズレがあるとします。
slewモードでは、いきなりLinuxサーバの時刻を20:00:00に合わせたりはしません。
徐々に徐々に、長時間かけて時刻を補正します。
具体的にどうやるかというと、Linuxサーバの時刻が進んでいる場合は、サーバ内の「1秒」を実際の1秒より長くして、時間の進み具合を遅くします。
逆に、遅れている場合はサーバ内の「1秒」を実際の1秒より短くし、時間の進みを早めます。
この方式であれば、時刻がいきなり飛んだり巻き戻ったりすることはありません。
(面倒くさい言い方をすると、時間の連続性が保たれます。)
稼働中のサーバでの時刻同期は、こちらの方式で行いたいところです。

slewモードの欠点

じゃあ、二通り用意しないで、全部slewモードでいいじゃん、と思われるかもしれません。
しかし、slewモードでは、本当に徐々に徐々に時刻を調整するので、数秒の時刻ずれを補正するのにも長時間かかります。
大抵のLinuxディストリビューションにおいて、slewモードで調整する時刻は1秒間に最大0.5ms(0.0005秒)です*3
すなわち1秒ずれてたとして、その1秒が補正されるまでには2000秒(約33分)かかります。
これだと時刻ずれが大きい場合、いつまでたっても正確な時刻にたどりつけません。

通常、ntpdが動作していれば、大きな時刻ずれは発生しない「はず」です。
しかし、Linuxサーバを長時間停止していたような場合は、事情が変わってきます。
Linuxサーバを起動した直後は、マザーボードの時計から時刻を拾って来ますが、この時計はあまり精度が良くないので、結構、実時刻とのズレが生じます。
このような場合にもslewモードでちんたら補正をかけてたら、いつまでも狂った時刻のまま運用する羽目になります。
なので、こういった時には、stepモードでいきなり正確な時刻に合わせる方が合理的です。

どんな時にstepモードで、どんな時にslewモードになるのか

さて、stepモード、slewモードの二種類の補正方式があるのはいいのですが、では、この補正方式はどのように切り替えられるのでしょうか。
ntpdの設定によって異なるのですが、(大抵のLinuxディストリでの)標準では、128msより小さいズレであれば、slewモードで補正されます。
では、128ms以上ならstepモードになるのかというと、さにあらず。
128ms以上ずれた状態が300秒以上続くと、そこで初めてstepモードで補正されます。

ちなみに、1000秒以上のズレが2回連続で確認されると、ntpdは動作を停止します。

変更する場合は?

これらの動作は、/etc/ntp.confにて設定します。
当該ファイルのtinkerディレクティブを変更することで、step/slewモードの切り替えやntpd動作停止のしきい値を変更できます。

tinker step 128 stepout 300 panic 1000

見れば大体わかると思いますが、「step」と「stepout」がstepモードに切り替わるしきい値、panicはntpdの動作停止のしきい値です。
なお、stepを0にすると、ずっとslewモードになります。
同様にpanicを0にすると、どれほど時刻がずれても動作停止せず時刻補正をかけるようになります。
ちなみに、stepoutは300より小さくしてはならないようです。

xオプション

stepモードでの時刻補正をできるだけ避けたい場合、/etc/ntp.confを修正することになりますが、別の手段としてntpd起動時にxオプションをつけるという手もあります。
xオプションを指定することで、stepモード切り替えのしきい値が600秒となり、滅多なことではstep動作しなくなります。
(ネット上で、xオプションをつけるとずっとslewモードになる、という記述が散見されますが、実際にはstepのしきい値が大きくなるだけで、step動作する可能性は残ります。)

起動時のxオプションを指定するには、「/etc/sysconfig/ntpd」を以下のように変更します。

OPTIONS="-x -u ntp:ntp -p /var/run/ntpd.pid -g"

ちなみにubuntuの場合は「/etc/default/ntp」に「-x」を追加します。

NTPD_OPTS='-g -x'

最後に

さて、今回記事は単なる備忘録というわけではなく、直近に迫ったイベントに備えてntpdの挙動について整理するために書きだしたものです。
「直近に迫ったイベント」については、次回取り上げる予定です。
(この時期にntpdという時点で、察してる人も多そうですが。)

 

 

*1:創作性の強い織田信長一代記。小瀬甫庵 - Wikipedia

*2:dovecotの停止とかがよく知られてます。

*3:ちなみに、昔のSolaris(2.6)では、1秒補正に16〜17秒程度しかかからなかった模様。ただしslewモードを可能にするには、パッチ適用が必要だったようです。