WindowsServer2016のうるう秒対策のslewモード設定方法

しばらく関係ないかもしれませんが、2020年にはうるう秒が挿入される可能性があるそうです。最近は、うるう秒対策が当たり前になっているので、どこの企業でもうるう秒対策をOS側で実施している可能性が高いと思いますが、今回は、最近、利用されるようになったWindows Server 2016のうるう秒対策について説明したいと思います。


Windows Serverのうるう秒対策について書かせてもらいましたが、Windows製品は基本的にうるう秒に影響を受けないのですが、サーバー上で稼働するアプリケーション、ミドルウェア、ソフトウェアによっては、うるう秒の影響を受けることがあります。


ちなみに、Windows Server 2016の場合は、Linuxと違ってかなりややこしいです。もっとシンプルにしてもらいたいのですが、簡単に説明できないくらいややこしいのです。


ということで、自分への情報整理も含めてslewモード対応についてまとめたいと思います。まず、マイクロソフトの公開されている情報です。

Windows Time サービスにおける時刻同期の仕組み
https://support.microsoft.com/ja-jp/help/2722681


こちら、対象がWindows Server 2003とありますが、2012R2でも同じ考え方が適用されるようです。


時刻修正についてですが、Windows Time サービスを使用し、NTP サーバと時刻同期を行う際は、以下のいずれかの方法で同期をしますとあります。

 

(a) 徐々に時刻を合わせる (Slew モード)
SetSystemTimeAdjustment APIをコールする事で、ターゲット時刻をローカル時刻に、徐々に時刻同期を行います。このモードによる時刻同期が実施される場合には、RTC への更新は行われません。

(b) 即座に時刻を合わせる (Step モード)
SetSystemTime API をコールすることで、即時にターゲット時刻をローカル時刻に設定します。この場合、RTC への更新も同時に行なわれます。

 

これですが、うるう秒対策とするなら、aのslewモードを設定したいということになります。


続いて、Widowsの場合は、以下 2 つの条件を満している場合、徐々に時刻を合わせる Slew モードになります。ここ【重要】です。

 

条件 1. NTP クライアントと NTP サーバーの時刻の差が MaxAllowedPhaseOffset で設定されている時間より小さい

条件 2. AbsoluteValueOfCurrentTimeOffset/PhaseCorrectRate/UpdateInterval < SystemClockRate/2 の不等式が満たされる


AbsoluateValueOfCurrentTimeOffset :
NTP クライアントが NTP サーバーに対して時刻同期要求を実施した際の NTP クライアントと NTP サーバーの時刻差のことです。

PhaseCorrectRate / UpdateInterval :
W32Time のレジストリで設定し、Slew モードにおける時刻同期設定間隔を決定するために使用されます。大きく設定した場合、NTP クライアントが NTP サーバーと同期するまでの間隔が長くなり、レジストリの値が小さい場合、早い間隔で同期いたします。

System Clock Rate :
システムのクロックレートのことです。LastClockRate (W32Time のレジストリ値) とほぼ合致します。シングル プロセッサなら約 10ms 、マルチ プロセッサなら約 15ms となります。


ちなみに、、Windows Time サービスの精度についてはこんな言及があります。

 

Windows Time サービスは、Kerberos 認証が正常に動作する範囲で NTP Client と NTP Server の時刻を同期することを主な目的とした、ゆるやかな時刻同期を提供する設計となっています。このため、Windows Time サービスにおいては、常に時刻差異が僅少である (1 秒単位の誤差など) 状態を保証することはできません。

 

そもそも、精度が高くないので、社内のNTPサーバは、LinuxCentOSを利用するようにしたいですね。ドメイン環境であれば、必然的にドメインコントローラーと同期することになってしまいますが。


さて、話を戻して、slewモードにする設定ですが、一番詳しく、分かりやすく書かれているのがこちらのMSのブログです。

Windows Time サービス – Slew モードと Step モード –

https://docs.microsoft.com/ja-jp/archive/blogs/jpntsblog/windows-time-slew-step

 

うるう秒対策につながるのですが、時間がずれた場合にすぐに調整するのがstepモード、徐々にゆっくりと時間をかけて時間を調整するのがslewモードです。


閏秒だと時間調整の為に、上位NTPサーバから時間を調整するための時間を挿入されます。そこで、即座に時間調整されてしまうと色々と過去に問題が起きたので、今ではうるう秒対策として、slewモードを設定する企業が多いです。


そして、Windowsのslewモード対策の難しさの理由は、、、まず、slewモードだけで動作させるという設定がないことです。さらに、ブログにも書かれていますが、Slew モードと Step モードのいずれが使用されるかは、NTP Client と NTP Server の時刻差によって、動的に決定されるという点です。

 


そしてその動的に使用されるのにも、【重要】と書いた条件式ですが、環境によって値が変わってくるのです。これが本当に面倒。

ドメイン コントローラーか、ドメインのメンバー サーバーか、ワークグループ環境か」

この環境の違いによって、上記の条件式で使用される各パラメーターの既定値が異なるため、Slew モードで時刻同期できる 「NTP Server との時刻のずれ」 の値も異なるとあります。今回は、ドメイン環境がないので、ワークグループのみ説明します。


【ワークグループの場合】
MaxAllowedPhaseOffset : 1

PhaseCorrectRate : 1

UpdateInterval : 360000

 

条件 1.
AbsoluteValueOfCurrentTimeOffset < 1 秒

 

条件 2.

- マルチ プロセッサーの場合

AbsoluteValueOfCurrentTimeOffset ÷ 1 ÷ 360000 < 0.015 ÷ 2

AbsoluteValueOfCurrentTimeOffset < 2700 秒

- シングル プロセッサーの場合

AbsoluteValueOfCurrentTimeOffset ÷ 1 ÷ 360000 < 0.010 ÷ 2

AbsoluteValueOfCurrentTimeOffset < 1800 秒

 

プロセッサー数は環境次第ですが、調整するのは、「MaxAllowedPhaseOffset 」とブログにも紹介されています。条件2が2700秒か1800秒なので、ドメイン環境よりも値が広いのですが、条件1が「1秒」なので、必然的に1秒でstepモードで動作してしまいます。

 

つまり、ワークグループ環境のWindows Server 2012 R2にて、なるべくslewモードで動作させたい場合は、「MaxAllowedPhaseOffset 」の値を変更してあげることで、なるべくslewモードで動作するようになりますね。


例えば、条件2に合わせるなら、2700か1800に変更すればいいですね。長々と書きましたが、結論「MaxAllowedPhaseOffset 」を調整してくださいになります。


では、同じように考えて、Windows Server 2016だとどなるのか。


条件 1.
AbsoluteValueOfCurrentTimeOffset < 1 秒

 

条件 2.
- マルチ プロセッサーの場合
AbsoluteValueOfCurrentTimeOffset ÷ 1 ÷ 100 < 0.015 ÷ 2
AbsoluteValueOfCurrentTimeOffset < 0.75 秒

 

- シングル プロセッサーの場合
AbsoluteValueOfCurrentTimeOffset ÷ 1 ÷ 100 < 0.010 ÷ 2
AbsoluteValueOfCurrentTimeOffset < 0.5 秒


なんと、条件2がかなり厳しくなっていて、シングルプロセッサなら0.5秒、そして、マルチプロセッサーの場合は、0.75秒になります。Windows Server 2012 R2よりもstepモードで動作しやすくなっています。以前、「100」だった値がもっと大きかったんですが、仕様が変わってしまいました。


まとめ

結論、ここだけ見てもらうでもいいのですが、ワークグループ環境のWindows Server 2012 R2でslewモードで動作させたい場合は、「MaxAllowedPhaseOffset 」の値を「1」から大きい数字に変更すればよかったですが、Windows Server 2016の場合は、この値だけでなく、「PhaseCorrectRate」か「UpdateInterval」を変更してあげる必要がありそうです。


ただ、上記のどちらをチューニングしたいいのかは、公式サイトではまだ言及されていません。以下は@ITの情報です。

https://www.atmarkit.co.jp/ait/articles/1207/12/news146_4.html

 

PhaseCorrectRateレジストリ値は、NTPサーバから受け取った時刻サンプルに対してシステム時刻を修正する速度を制御するもので、値が小さいとゆっくり修正し、値が大きいと素早く修正する。またUpdateIntervalレジストリ値は、修正を行うサイクル時間(どのくらいの時間間隔でクロックの修正を行うか)を指定し、値が小さいほど短い間隔で修正動作が繰り返される。

 

PhaseCorrectRateレジストリ値は、NTPサーバから受け取った時刻サンプルに対してシステム時刻を修正する速度を制御するそうなので、この値はあまり大きくしないほうがよさそうですね。MSの公開情報が追加され次第、別途、情報をアップします。