SyntaxHighlighter

2016年8月30日火曜日

Windows Server の NTP クライアントをちゃんと設定する

Windows Server の NTP クライアントの設定方法について、ここにまとめておきます。

一部の設定は w32tm コマンドでも設定可能ですが、レジストリを直接いじらないと変えられない設定値もあるので、 全部レジストリをいじる前提で記載します。 なお、変更を反映するには Windows Time サービスの再起動が必要です。

対象 OS のバージョンは 2012 R2 です。それ以外のバージョンでは挙動やデフォルト値が異なる可能性がありますので注意してください。

前提

  • 組織内またはキャリアやプロバイダの NTP サーバを上位 NTP サーバとして参照する設計とします。 自分自身が最上位の NTP サーバとなったり、Windows 以外の OS から NTP サーバとして参照される想定ではありません。
  • 外部(上位) NTP サーバの FQDN を ntp1.example.net, ntp2.example.net として記載します。
  • シングルフォレスト、シングルドメイン想定です。
  • ドメインコントローラに余計なミドルウェアやアプリケーションは乗せていない前提です。
  • PDC エミュレータの FSMO を持つドメインコントローラは固定されている前提です。 頻繁に FSMO の移動を行うことが想定されている場合や、PDC の障害時に FSMO を移動して、復旧後も元に戻さない運用を想定している場合は、 ドメインコントローラ全てを「PDC 以外のドメインコントローラ」と考えて本文を読んでください。
  • 本文中の「必須」は文字通り必須の設定で、設定しないとまともに動作しません。
    「推奨」は私個人の推奨であり、私の所属する組織や、Microsoft や、その他の組織の推奨という意味ではありません。 また、設定しなくても最低限の時刻同期は行えます。 責任は持ちませんのでご了承ください。
  • 本文中に記載している数値のうち、0x 付きの数値は16進数、付いていないものは10進数です。
  • ある程度のスキルレベルを持った技術者向けに記載しています。 AD や NTP に関する基礎的な知識がない方や、 レジストリの編集方法やそのリスクをわかっていないとか16進数がわからないレベルの方は誤読により誤った設定になってしまう可能性があるので他サイトをあたってください。

まず、クライアントの種類を以下の通り分類します。それぞれで設定が異なります。

  1. ドメインコントローラ(PDCエミュレータ(以下単にPDCと記載))
    PDC エミュレータの FSMO を持つドメインコントローラです。管理ドメイン下の全ての Windows マシンのマスターソースになります。
  2. ドメインコントローラ(PDC以外)
    PDC 以外のドメインコントローラは、PDC から時刻を取得します。そして、メンバーサーバへ時刻を提供します。 デフォルト設定では PDC がダウンしたら終わりなので、この記事では PDC がダウンしている場合には外部 NTP サーバから時刻同期するよう設定します。
  3. ドメインのメンバーサーバ
    メンバーサーバはログイン時に使用したドメインコントローラ(PDCとは限らない)から時刻を取得します。
  4. ワークグループのサーバ
    ワークグループのサーバのデフォルト設定ははっきり言って使い物にならないのでメンバーサーバと同等の設定にします。

次に、設定項目について説明します。 説明はいいから結論を!という方はまとめへどうぞ。

参照先 NTP サーバの設定

参照先サーバを決定するレジストリ項目は2つ。両方ともキーの場所は HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Parameters です。

まず、Type エントリ。このエントリの設定次第では、次の NtpServer エントリの設定は何の意味も持ちません。 クライアント種別ごとのデフォルト値と推奨値は以下の通り。

Type
クライアント種別デフォルト値推奨値
1. PDCNT5DSNTP(必須)
2. DCNT5DSAllSync(推奨)
3. メンバーサーバNT5DSNT5DS(推奨)
4. ワークグループNTPNTP(必須)

NT5DS はドメインの階層構造に従ってドメインコントローラから時刻を取得する設定です。この設定値になっている場合、次で説明する NtpServer の値は無視されます。 メンバーサーバは、例えドメインコントローラの時刻がずれていたとしてもドメインコントローラ以外と時刻同期するべきではありません。 ドメインコントローラとの時刻差が 5 分以上になると認証に問題が発生する可能性があるためです。 よって NT5DS のままにしておくことを強く推奨します。

NTP は次で説明する NtpServer に設定されているサーバから時刻を取得します。上位にドメインコントローラがいない、PDC とワークグループのサーバではこの値にすることが必須です。

AllSync は、ドメインコントローラと NtpServer に設定されたサーバの両方と時刻同期をする設定です。 PDC 以外のドメインコントローラは、平常時は PDC のドメインコントローラと時刻同期を行い、PDC と同期できない場合に外部 NTP サーバを参照するようこの値に設定します。

Type が NTP または AllSync の場合に参照されるのが NtpServer エントリです。

NtpServer
クライアント種別デフォルト値推奨値
1. PDCtime.windows.com,0x9ntp1.example.net,0x8 ntp2.example.net,0x8
2. DCntp1.example.net,0xa ntp2.example.net,0xa
3. メンバーサーバ設定不要
4. ワークグループPDCのFQDN,0x8 ntp1.example.net,0xa
ntp2.example.net,0xa
※スペースの都合で改行していますが実際には1行です

NTP サーバを、複数の場合はスペースで区切って記載します。サーバの FQDN の末尾に , に続いて記載されている 16 進数の数値は動作モードを決定するフラグです。 優先的に使用するサーバには 0x8 を付与し、0x8 のサーバに接続できない場合にだけ使用するサーバに 0xa を付けます。

PDC の場合、上位 NTP サーバは今回の例だとどちらでも良いので両方に 0x8 を付けています。

PDC 以外の DC の場合は、PDC がダウンしている場合のみ外部 NTP サーバを利用するので両方に 0xa を付けています。 Type を AllSync にしていれば PDC には勝手に同期するのでこのエントリに PDC の FQDN を記載する必要はありません。

メンバーサーバは、前述した通り Type が NT5DS であればこのレジストリに何が設定されていても参照されないので、設定不要です。

ワークグループのサーバは、PDC を優先的に参照 (0x8) し、PDC がダウンしている場合には外部 NTP サーバを参照 (0xa) する設定です。 こちらは明示的に PDC の FQDN を記載してあげる必要があります。 ただ、PDC を参照することは必須ではないので、PDC と同期したくない(またはできない)場合は PDC 部分は消して、他サーバのフラグを 0x8 にしても全く問題ありません。

なお、フラグ部分を奇数にすると、等間隔での時刻同期を行うモードになります。 デフォルトに使われているのも 0x9 ですし、ワークグループ環境で GUI で参照先 NTP サーバを設定した場合にも自動的に 0x9 が付くし、 いろんなサイトでも 0x9 を付けるよう書いてあったりするしで、つい 0x9 にしてしまいたくなる人もいると思いますが、そこはぐっとこらえて 0x8 にしてください。 理由は次項で説明します。 0x8 でも等間隔で同期したければできますのでご安心を。

同期間隔の設定

前項の NtpServer の設定でフラグを 0x1 または 0x9 にしなかった場合(Type が NT5DS の場合も含む)、 同期間隔は MinPollInterval エントリ~ MaxPollInterval エントリの間になります。 キーのパスは HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Config です。 初回は MinPollInterval エントリの間隔で同期を行い、安定していくにつれて MaxPollInterval エントリの間隔に収束していきます。 一定間隔で同期をしたければ、MinPollInterval エントリと MaxPollInterval エントリを同じ数値にすれば良いです。 数値は 2 のべき乗の数値(指数)で指定します。例えば 5 だったら 2 の 5 乗で 32 秒ということになります。 クライアント種別ごとのデフォルト値と推奨値は以下の通り。括弧内の数値はべき乗計算結果です。

MinPollInterval
クライアント種別デフォルト値推奨値
1. PDC0x6 (64s)0x4 (16s)
2. DC0x6 (64s)0x4 (16s)
3. メンバーサーバ0xa (1024s=約17分)0x6 (64s)
4. ワークグループ0xa (1024s=約17分)0x6 (64s)

MaxPollInterval
クライアント種別デフォルト値推奨値
1. PDC0xa (1024s=約17分)0x8 (256s=約4.2分)
2. DC0xa (1024s=約17分)0x8 (256s=約4.2分)
3. メンバーサーバ0xf (32768s=約9.1時間)0xa (1024s=約17分)
4. ワークグループ0xf (32768s=約9.1時間)0xa (1024s=約17分)

推奨値は、ドメインコントローラの2種に関しては、Min は設定可能な下限が 4 なので 4 にしました。 Max は、nict の FAQ に、1 時間に 20 回を超えるポーリングをしたいなら事前連絡が必須と書かれていたので、 事前連絡不要な範囲での最小値である 8 にしました(7 だと 2 分強間隔なので 20 回を超える)。 メンバーサーバとワークグループのサーバの推奨値は、Linux の ntpd のデフォルトの Min, Max に合わせました。 推奨といっても以上のような根拠なので、お好みで変えてください。 経験上、物理サーバーやオーバーコミットしていない仮想環境(負荷も低い)では、推奨値どころかデフォルト値のままでも問題になったことはありません(保証はしませんよ)。 逆にオーバーコミットしまくりの仮想環境では、推奨値ぐらいの設定にすることは必須かと思います。 場合によってはもっと間隔を狭めてもいいかもしれません。

個人的に非推奨ですが、NtpServer で奇数のフラグを使った場合は、上記の MinPollInterval ~ MaxPollInterval の間隔ではなく、 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpClient キーの SpecialPollInterval エントリに設定された間隔で同期されます。 この設定値は 2 のべき乗ではなく普通に秒数です。 デフォルト値は、ドメイン環境では DC かどうかに関わらず 3600(1時間)、ワークグループ環境では 604800(7日)です。
なぜ非推奨かというと、SPIKE 状態から復旧できないという不具合があるからです。 不具合の詳細については以下の公式情報を参照してください。
KB2638243
この記事の推奨通り、フラグに奇数を使わなければ SpecialPollInterval は使わないので不具合には該当しません。
また、時刻同期が行えているのかの確認で w32tm /query /status コマンドを実行すると思いますが、このとき表示される「ポーリング間隔」に、 SpecialPollInterval は反映されません。 NtpServer でフラグに 0x9 を指定して、SpecialPollInterval を 60 に設定した場合、1分ごとに w32tm /query /status コマンドを打てば、 ちゃんと1分間隔で時刻同期されていることが「最終正常同期時刻」を見ればわかりますが、「ポーリング間隔」は 60s ではなく MinPollInterval ~ MaxPollInterval の設定値が表示されます。 もちろんこれは試験時や運用時に混乱の元になります。これも奇数フラグと SpecialPollInterval が非推奨である理由の1つです。

step/slew の設定

以下の2つの条件式を両方とも満たす場合、slew で時刻同期され、どちらか片方だけでも満たさないと step で時刻同期されます。 英語の部分がレジストリで設定する値です。

  1. 時刻差 < MaxAllowedPhaseOffset
  2. 時刻差 < システムクロックレート ÷ 2 × PhaseCorrectRate × UpdateInterval

まず最初の条件式に出てくる MaxAllowedPhaseOffset について説明します。 キーのパスは HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Config です。 値に設定する数値は秒数です。

MaxAllowedPhaseOffset
クライアント種別デフォルト値推奨値
1. PDC3002
2. DC3002
3. メンバーサーバ300変更不要
4. ワークグループ1300

DC は、自身が NTP サーバとなる存在なので、slew で同期することよりも信頼性の高い時刻を提供することが第一です。 デフォルト値の 300 秒のままでも、条件式2によって、マルチプロセッサで約 5.25 秒、シングルプロセッサで約 3.5 秒で step に切り替わりますが、 より短く 2 秒に設定することを推奨します。 2 秒の根拠は、うるう秒挿入で必ず発生する 1.α秒のずれ(0.α秒は通常発生する分のずれ)は slew で同期するほうがいろんなものへの影響が少ないと思うからです。

メンバーサーバとワークグループのサーバは、精度の高い時刻を維持することより、上に乗っているアプリに影響を出さないほうが重要なので、 できるだけ slew で時刻を合わせるほうが良いでしょう。 ただ、メンバーサーバは DC との時刻差が 5 分を超えると認証に問題が発生するので、300 秒を上限とします。 ワークグループもそれに合わせます。 300 秒を超えようとなんだろうと、絶対に step は NG!というアプリ要件があれば、slew で同期可能な時刻を増やすのではなく(無限にはできませんから)、閾値を超えたら時刻同期を行わない設定をします(後述)。

次に、条件式2についての説明です。

まずシステムクロックレートですが、これは正確には w32tm /query /status /verbose コマンドをうち、 表示される「クロック レート」を確認する必要があります。 マルチプロセッサでは約 15ms、シングルプロセッサでは約 10ms です。

PhaseCorrectRate エントリと UpdateInterval エントリのキーのパスはともに HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Config です。

PhaseCorrectRate
クライアント種別デフォルト値推奨値
1. PDC7変更不要
2. DC7変更不要
3. メンバーサーバ12
4. ワークグループ12

UpdateInterval
クライアント種別デフォルト値推奨値
1. PDC100変更不要
2. DC100変更不要
3. メンバーサーバ3000020000(マルチプロセッサ)
30000(シングルプロセッサ)
4. ワークグループ36000020000(マルチプロセッサ)
30000(シングルプロセッサ)

DC の場合、条件式1のほうでより短い閾値にしているのでこちらは変更不要です。

メンバーサーバは、デフォルト値だとマルチプロセッサの場合で約225秒、シングルプロセッサの場合で約150秒が閾値になります。 上記の推奨値のように変更すると約300秒になります。 実際のシステムクロックレートは 15ms や 10ms ジャストではないので誤差は出ます(300 より大きくなる)が、 MaxAllowedPhaseOffset で 300 に抑えているので 300 秒が step への切り替わり閾値になります。

ワークグループの場合は、デフォルト値だとマルチプロセッサの場合で約45分、シングルプロセッサの場合で約30分が閾値になります。 300秒を超えているので変更しなくても良いのですが、UpdateInterval が長すぎて時刻同期に時間がかかりそうなのでメンバーサーバと合わせています。

時刻同期をしない閾値の設定

時刻差がどれだけあろうとも絶対に step では同期させたくないという要件がある場合、前項で説明した slew で同期される範囲内の時間に、 「これ以上時刻差がある場合、同期自体を行わない」という閾値を設ける必要があります。 キーのパスは HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Config です。

MaxPosPhaseCorrection
クライアント種別デフォルト値推奨値
1. PDC0x0002a300(48時間)変更不要
2. DC0x0002a300(48時間)変更不要
3. メンバーサーバ0xffffffff(無期限)変更不要
4. ワークグループ0xd2f0(15時間)変更不要

MaxNegPhaseCorrection
クライアント種別デフォルト値推奨値
1. PDC0x0002a300(48時間)変更不要
2. DC0x0002a300(48時間)変更不要
3. メンバーサーバ0xffffffff(無期限)要件により 0x12c(300) 以下に設定
4. ワークグループ0xd2f0(15時間)要件により 0x12c(300) 以下に設定

MaxPosPhaseCorrection は、進めることのできる時間の閾値です。 通常、時刻が進む分には step でも問題は発生しないので変更不要と考えます。

MaxNegPhaseCorrection は、遅らせることができる時間の閾値です。 slew 設定の範囲内でないと、step で同期される、つまり時間の遡りが発生する可能性があるので注意してください。

なお、この項目は特殊な要件がある場合にのみ使用するのでまとめのほうには記載していません。

Windows Time サービスの自動起動の設定

Windows Time サービスにはデフォルトでトリガーが設定されていて、 ワークグループ環境では常時起動されません。 トリガーを削除し、スタートアップの種類を「自動」に設定する必要があります。 コマンドで実行する方法もありますが、ここでは他と合わせてレジストリで説明します。

まずトリガーを削除するには、以下のサブキーをキーごと削除します。
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TriggerInfo

スタートアップの種類を「自動」にするには、以下のキーの「Start」の値を「0x3」から「0x2」に変更します。
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time

なお、ドメイン環境ではトリガーで自動起動するので特に設定する必要はありません。

まとめ

推奨設定をまとめておきます。なお、どんな環境でも必須なものに◎、強く推奨するものに○を付けていますので参考にどうぞ。

1. ドメインコントローラ(PDC)

  • 上位 NTP サーバとして ntp1.example.net と ntp2.example.net を同じ優先度で参照
  • 時刻同期間隔は 16s ~ 256s
  • NTP サーバとの時刻差が 2s 以上ある場合 step モードで同期
キー:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Parameters

-データ
TypeNTP
NtpServerntp1.example.net,0x8 ntp2.example.net,0x8

キー:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Config

-データ
 MinPollInterval0x4
 MaxPollInterval0x8
 MaxAllowedPhaseOffset0x2
 PhaseCorrectRate0x7 ※デフォルト
 UpdateInterval0x64 (100) ※デフォルト

2. ドメインコントローラ(PDC以外)

  • PDC との同期ができない場合に限り ntp1.example.net と ntp2.example.net を同じ優先度で参照
  • 時刻同期間隔は 16s ~ 256s
  • NTP サーバとの時刻差が 2s 以上ある場合 step モードで同期
キー:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Parameters

-データ
TypeAllSync
NtpServerntp1.example.net,0xa ntp2.example.net,0xa

キー:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Config

-データ
 MinPollInterval0x4
 MaxPollInterval0x8
 MaxAllowedPhaseOffset0x2
 PhaseCorrectRate0x7 ※デフォルト
 UpdateInterval0x64 (100) ※デフォルト

3. ドメインのメンバーサーバ

  • 参照 NTP サーバはデフォルト設定
  • 時刻同期間隔は 64s ~ 1024s
  • NTP サーバとの時刻差が 300s 以上ある場合 step モードで同期
キー:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Parameters

-データ
TypeNT5DS ※デフォルト
 NtpServertime.windows.com,0x9 ※デフォルト

キー:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Config

-データ
 MinPollInterval0x6
 MaxPollInterval0xa
 MaxAllowedPhaseOffset0x12c(300) ※デフォルト
 PhaseCorrectRate0x2
 UpdateInterval20000(マルチプロセッサ)
30000(シングルプロセッサ) ※デフォルト

4. ワークグループのサーバ

  • Windows Time サービスを自動起動するように設定
  • 上位 NTP サーバとして PDC を優先的に参照、次点で ntp1.example.net と ntp2.example.net を同じ優先度で参照
  • 時刻同期間隔は 64s ~ 1024s
  • NTP サーバとの時刻差が 300s 以上ある場合 step モードで同期
キー:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time

-データ
Start0x2

・HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TriggerInfo キーを削除

キー:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Parameters

-データ
TypeNTP
NtpServerPDCのFQDN,0x8 ntp1.example.net,0xa ntp2.example.net,0xa

キー:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Config

-データ
 MinPollInterval0x6
 MaxPollInterval0xa
MaxAllowedPhaseOffset0x12c(300)
 PhaseCorrectRate0x2
 UpdateInterval20000(マルチプロセッサ)
30000(シングルプロセッサ)

その他の注意事項

  • NTP の設定がどうであろうと、OS 起動時は BIOS から時刻が取得されますので、 BIOS の時刻を正しい状態に維持しておくことは非常に重要です(電池切れ注意)。
    仮想環境の場合は、ESXi ホストから時刻を取得するので、ESXi ホストの時刻もきちんと NTP 設定して正確に維持しておくこと。
  • 仮想環境の場合。VMware Tools による定期的な時刻同期はデフォルトで無効になっており、あえて有効にしない限りは時刻同期されませんが、 実はその設定を有効にしていなくても、vMotion 実行時やスナップショット作成・削除時などのイベント時に勝手に時刻同期されてしまいます。 ESXi ホストの NTP も OS の NTP もきちんと設定されていて正確な時刻を維持できているなら特に問題は発生しないはずですが、 そういったイベント時でも同期されないよう設定しておいたほうが無難かもしれません。設定方法は以下の VMware の KB を参照してください。
    時刻同期の無効化 (2076744) | VMware KB

他のサイトの説明との食い違いについての覚書

非難する目的ではなく、自分用に、惑わされないように記録を残しておきたいという意図で記載しています。

  • ドメイン環境での時刻同期間隔がデフォルトで1時間であるという情報が多々ありますが、 SpecialPollInterval のデフォルト値が1時間であることから誤解が広まっているものと思われます。 実際にはデフォルトでは MinPollInterval ~ MaxPollInterval で、詳細は本文参照ですが少なくとも1時間ではありません。
  • ドメイン環境での step 閾値がデフォルトで5分であると書いてあるサイトがありますが、 条件式1のことしか認識していないものと思われます。
  • ドメイン環境の MinPollInterval と MaxPollInterval のデフォルト値を 6, 10 と書いてあるサイトがありますが、 実際には DC とメンバーサーバでは異なっていて、DC が 6, 10 で、メンバーサーバはワークグループと同じ 10, 15 です。
  • NtpServer に付けるフラグで、0x8 は 2008 から無くなったと書いているサイトがありますが、 公式情報としては見つけられず、公式以外の情報もそのサイト以外には見つかりませんでした。 使ってもエラーにならないし、デフォルトで設定されている NtpServer の値も time.windows.com,0x9 のままだし、 GUI で設定した場合も自動的に 0x9 が付与されるので、気にせず使ってよいと考えています。 (0x9 は 0x1 + 0x8 という意味なので、0x8 が廃止されたのであれば 0x9 が設定されるのはおかしい)

おまけ1:設定用スクリプト

この記事のおすすめ設定を適用する PowerShell スクリプトです。 ファイルを開いて、先頭付近の設定項目を編集(最低限参照先 NTP サーバを記載)して実行してください。 メンバーサーバとワークグループサーバでは自動的にシステムクロックレートを取得して最適な UpdateInterval にしてくれます。 あんまりがっつり試験してないのでご利用はくれぐれも自己責任で。改変自由。ただし再配布は基本禁止で。 使ってみて何かバグを見つけたらフィードバックもらえると嬉しいです。

win2012r2_setntp_scripts_1.0.zip

おまけ2:確認用 w32tm コマンド

時刻同期できているか確認する
w32tm /query /status
クロックレートなどより詳細を表示したい場合
w32tm /query /status /verbose
NtpServer に設定されている全ての NTP サーバとの通信状況を確認する
w32tm /query /peers
設定を確認する
w32tm /query /configuration

1 件のコメント:

  1. 自社内のドメイン環境下において、時刻同期がPDCとできていない不具合に気づき、基本的な事から情報収集しておりました。
    本記事はドメイン環境下における時刻同期設定のベストプラクティスだと思います。

    返信削除