Azure での Linux VM の時刻同期

適用対象: ✔️ Linux VM ✔️ フレキシブル スケール セット ✔️ 均一スケール セット

時刻同期は、セキュリティとイベントの関連付けで重要になります。 場合によっては、分散トランザクションの実装で使用されます。 複数のコンピューター システム間での時刻の精度は、同期によって実現されます。 同期は、再起動や、時刻をフェッチするコンピューターとタイム ソースとの間のネットワーク トラフィックなど、複数の要因に影響を受ける可能性があります。

Azure は、Windows Server 2016 を実行しているインフラストラクチャによってサポートされます。 Windows Server 2016 では、時刻を修正し、ローカル クロックを調整して UTC と同期するために使用されるアルゴリズムが改善されています。 Windows Server 2016 の正確な時刻機能では、正確な時刻を確保するためにホストで VM を制御する VMICTimeSync サービスの動作が大幅に改善されています。 この改善には、VM の開始時や VM の復元時の初期時刻の精度の向上と、割り込み待ち時間の修正が含まれます。

Note

Windows Time サービスの概要については、こちらの概要ビデオをご覧ください。

詳細については、「Windows Server 2016 の正確な時刻」を参照してください。

概要

コンピューター クロックの精度は、そのコンピューター クロックと協定世界時 (UTC) 標準時間との誤差で測定されます。 UTC は、300 年に 1 秒しか誤差が生じない正確な原子時計の世界各国のサンプルによって定義されます。 しかし、UTC を直接読み取るには特殊なハードウェアが必要です。 代わりに、タイム サーバーが UTC と同期され、他のコンピューターはそこにアクセスすることで、拡張性と堅牢性が提供されます。 すべてのコンピューターで時刻同期サービスが実行されており、サーバーの使用時刻が認識され、コンピューター クロックを修正する必要があるかどうかが定期的に確認され、必要に応じて調整されます。

Azure ホストは内部の Microsoft タイム サーバーに同期されています。このサーバーでは、GPS アンテナを使用して、Microsoft が所有する Stratum 1 デバイスから時刻を取得します。 Azure の仮想マシンでは、そのホストに依存して正確な時刻 (ホスト時刻) を VM に渡すことも、VM でタイム サーバーから直接時刻を取得することも、あるいはこれらの両方を組み合わることもできます。

スタンドアロン ハードウェアでは、Linux OS によって、起動時にホスト ハードウェア クロックのみが読み取られます。 その後、クロックは、Linux カーネルの割り込みタイマーを使用して維持されます。 この構成では、クロックは時間の経過と共に誤差が生じます。 Azure の新しい Linux ディストリビューションでは、VM で VMICTimeSync プロバイダーを使用できます。このプロバイダーは LIS (Linux Integration Services) に含まれており、ホストからより頻繁にクロック更新についてクエリを実行するためのものです。

仮想マシンとホストとのやりとりがクロックに影響する場合もあります。 メモリ保持メンテナンス中に、VM は最大で 30 秒間一時停止します。 たとえば、メンテナンスの開始前に、VM クロックには午前 10 時 00 分 00 秒と示され、この状態が 28 秒間続きます。 VM の再開後、VM のクロックはまだ午前 10 時 00 分 00 秒と示されており、28 秒遅れていることになります。 これを修正するため、VMICTimeSync サービスでは、ホストで何が発生しているのかを監視し、補正する Linux VM の時刻機構を更新します。

時刻同期が動作しないと、VM のクロックでエラーが蓄積されます。 VM が 1 つのみであれば、ワークロードで高精度のタイムキーピングが必要でない限り、影響は大きくならない場合があります。 しかし、ほとんどの場合、相互接続された VM が複数あり、それらの VM ではトランザクションを追跡するために時間を使用し、その時間はデプロイ全体で一貫している必要があります。 VM 間の時間が異なると、次のような影響が見られる場合があります。

  • 認証が失敗します。 Kerberos または証明書に依存するテクノロジのようなセキュリティ プロトコルでは、システム全体で時間が一貫していることが前提となります。
  • ログ (またはその他のデータ) が時間に関して一致しない場合、システムで何が発生したかを把握するのは困難です。 異なる時間に同じイベントが発生したように見え、関連付けが困難になります。
  • クロックに誤差がある場合、請求額を正しく計算できません。

構成オプション

時刻の同期では、Linux VM で時刻同期サービスを実行することと、同期する正確な時刻情報のソースが必要です。 通常、ntpd または chronyd は時刻同期サービスとして使用されます。しかし、他にも使用できるオープン ソースの時刻同期サービスがあります。 正確な時刻情報のソースは、Azure ホストまたはパブリック インターネットを使用してアクセスされる外部タイム サービスです。 VMICTimeSync サービス自体は、前述のようにホスト メンテナンスのために一時停止した後を除き、Azure ホストと Linux VM の間で継続的な時刻同期を提供しません。

従来、Linux を使用する Azure Marketplace のほとんどのイメージは、次の 2 つの方法のいずれかを使用して構成されています。

  • 既定では、時刻同期サービスは実行されません。
  • ntpd は時刻同期サービスとして実行され、ネットワークを通してアクセスされる外部 NTP タイム ソースに対して同期しています。 たとえば、Ubuntu 18.04 LTS の Marketplace イメージでは、ntp.ubuntu.com が使用されます。

ntpd が正しく同期していることを確認するには、ntpq -p コマンドを実行します。

Linux を使用する一部の Azure Marketplace イメージは chronyd を時刻同期サービスとして使用するように変更されています。また、chronyd は外部 NTP タイム ソースではなく Azure ホストと同期するように構成されています。 Azure ホスト時間は、通常、正確かつ確実に維持され、パブリック インターネットを使用した外部 NTP タイム ソースへのアクセスに固有の可変ネットワーク遅延なしでアクセス可能であるため、同期に最適なタイム ソースです。

VMICTimeSync は並列で使用され、次の 2 つの関数を提供します。

  • ホスト メンテナンス イベントの後、Linux VM の時刻機構を直ちに更新します。
  • IEEE 1588 Precision Time Protocol (PTP) ハードウェア クロック ソースを、Azure ホストから正確な時刻を提供する /dev/ptp デバイスとしてインスタンス化します。 Chronyd は、このタイム ソース (最新の Linux イメージの既定の構成) と同期するように構成できます。 カーネル バージョン 4.11 以降 (または RHEL 7 の場合はバージョン 3.10.0-693 以降) の Linux ディストリビューションでは、/dev/ptp デバイスがサポートされます。 Azure ホスト時間に対して、/dev/ptp をサポートしない以前のバージョンのカーネルでは、外部タイム ソースに対してのみ同期を実行できます。

既定の構成は変更できます。 ntpd と外部タイム ソースを使用するように構成されている古いイメージは、Azure ホスト時間に対しては、chronyd と /dev/ptp デバイスを使用するように変更できます。 同様に、アプリケーションまたはワークロードで必要になった場合に、外部の NTP タイム ソースを使用するように構成することもできます。

ツールとリソース

時刻同期構成を確認するための基本的なコマンドがいくつかあります。 Linux ディストリビューションのドキュメントには、そのディストリビューションで時刻同期を構成する最適な方法が詳しく説明されています。

統合サービス

統合サービス (hv_utils) が読み込まれているかどうかを確認します。

$ sudo lsmod | grep hv_utils

次のように表示されます。

hv_utils               24418  0
hv_vmbus              397185  7 hv_balloon,hyperv_keyboard,hv_netvsc,hid_hyperv,hv_utils,hyperv_fb,hv_storvsc

PTP クロック ソースを確認する

新しいバージョンの Linux では、Azure ホストに対応する PTP (Precision Time Protocol) クロック ソースを VMICTimeSync プロバイダーの一部として利用できます。 以前のバージョンの Red Hat Enterprise Linux 7.x では、Linux Integration Services をダウンロードし、それを使って更新されたドライバーをインストールできます。 PTP クロック ソースを使用できる場合、Linux デバイスの形式は /dev/ptpx になります。

どの PTP クロック ソースを使用できるかを確認します。

$ ls /sys/class/ptp

この例では、返される値は ptp0 であるため、これを使用してクロック名を確認します。 デバイスを確認するには、クロック名を調べます。

$ sudo cat /sys/class/ptp/ptp0/clock_name

これにより hyperv 、つまり Azure ホストが返されます。

一部の Linux VM 内では、複数の PTP デバイスが一覧表示される場合があります。 1 つの例は、高速ネットワークの場合、Mellanox mlx5 ドライバーも /dev/ptp デバイスを作成します。 初期化の順序は Linux が起動するたびに変わる可能性があるため、Azure ホストに対応する PTP デバイスが /dev/ptp0 になる場合や /dev/ptp1 になる場合があり、chronyd を正しいクロック ソースで構成することが難しくなります。 この問題を解決するために、最新の Linux イメージの udev ルールによって、Azure ホストに対応するどの /dev/ptp エントリにもシンボリックリンク /dev/ptp_hyperv が作成されるようになっています。 Chrony では、/dev/ptp0 または /dev/ptp1 の代わりにこの /dev/ptp_hyperv シンボリックリンクを使用するよう、常に構成する必要があります。

/dev/ptp_hyperv デバイスが作成されない問題が発生した場合は、udev ルールと以下の手順を使用してデバイスを構成できます。

注: この udev ルールは、新しいバージョンの systemd には実装されているため、ほとんどの Linux ディストリビューションにおいては不要です

udev ルール ファイルを作成します。

$ sudo cat > /etc/udev/rules.d/99-ptp_hyperv.rules << EOF
ACTION!="add", GOTO="ptp_hyperv"
SUBSYSTEM=="ptp", ATTR{clock_name}=="hyperv", SYMLINK += "ptp_hyperv"
LABEL="ptp_hyperv"
EOF

仮想マシンを再起動するか、次のようにして udev ルールをリロードします。

$ sudo udevadm control --reload
$ sudo udevadm trigger --subsystem-match=ptp --action=add

chrony

Ubuntu 19.10 (およびそれ以降のバージョン) と Red Hat Enterprise Linux 8.x では、PTP ソース クロックを使用するように chrony が構成されています。 以前の Linux リリースでは、chrony ではなく、PTP ソースがサポートされない ntpd (Network Time Protocol Daemon) が使用されています。 これらのリリースで PTP を有効にするには、chrony.conf で次のステートメントを使用して chrony を手動でインストールして構成する必要があります。

refclock PHC /dev/ptp_hyperv poll 3 dpoll -2 offset 0 stratum 2

/dev/ptp_hyperv シンボリックリンクが使用可能な場合は、/dev/ptp0 の代わりに使用して、Mellanox mlx5 ドライバーによって作成された /dev/ptp デバイスとの混同を避けてください。

階層情報は、Azure ホストから Linux ゲストに自動的には伝達されません。 前の構成行では、Azure ホスト タイム ソースが階層 2 として扱われることを指定しています。これで、Linux ゲストではそれ自体を階層 3 として報告します。 Linux ゲストでそれ自体を異なる方法で報告するように必要がある場合は、構成行の階層設定を変更できます。

既定では、chronyd は、時間の誤差を修正するために、システム クロックを加速または減速します。 誤差が大きすぎる場合、chrony は誤差の修正に失敗します。 これを解決するために、 /etc/chrony.confmakestep パラメーターを変更して、誤差が、指定されたしきい値を超えた場合に時刻同期を強制的に適用することができます。

makestep 1.0 -1

ここでは、chrony は、誤差が 1 秒よりも大きい場合に時間の更新を強制します。 変更を適用するには、chronyd サービスを再起動します。

$ sudo systemctl restart chronyd && sudo systemctl restart chrony

場合によっては、systemd-timesyncd サービスがまだ有効になっていて、再起動時に同期を行おうとすることがあります。syslog に次のようなメッセージが引き続き表示される場合:

systemd-timesyncd[945]: Network configuration changed, trying to establish connection.
Aug  1 12:59:45 vm-name systemd-timesyncd[945]: Network configuration changed, trying to establish connection.
Aug  1 12:59:45 vm-name systemd-timesyncd[945]: Network configuration changed, trying to establish connection.
Aug  1 12:59:45 vm-name systemd-timesyncd[945]: Network configuration changed, trying to establish connection.
Aug  1 12:59:45 vm-name systemd-timesyncd[945]: Network configuration changed, trying to establish connection.
Aug  1 12:59:45 vm-name systemd-timesyncd[945]: Synchronized to time server 185.125.190.56:123 (ntp.ubuntu.com)

次を使用して無効にすることができます。

$ sudo systemctl disable systemd-timesyncd

ほとんどの場合、systemd-timesyncd による試行は起動時に行われますが、chrony が起動すると上書きされ、chrony が既定の時刻同期ソースになります。

Ubuntu および NTP の詳細については、時刻同期に関するページを参照してください。

Red Hat および NTP の詳細については、NTP の構成に関するページを参照してください。

chrony の詳細については、chrony の使用に関するページを参照してください。

systemd

19.10 より前の SUSE と Ubuntu では、時刻同期は systemd を使用して構成されます。 Ubuntu の詳細については、時刻同期に関するページを参照してください。 SUSE の詳細については、SUSE Linux Enterprise Server 12 SP3 に関するリリース ノートの第 4.5.8 条を参照してください。

cloud-init

cloud-init を使用して VM をプロビジョニングするイメージでは、ntp セクションを使用して時間同期サービスを設定できます。 cloud-init で chrony をインストールし、Ubuntu VM の PTP クロック ソースを使用するように構成する例を次に示します。

#cloud-config
ntp:
  enabled: true
  ntp_client: chrony
  config:
    confpath: /etc/chrony/chrony.conf
    packages:
     - chrony
    service_name: chrony
    template: |
       ## template:jinja
       driftfile /var/lib/chrony/chrony.drift
       logdir /var/log/chrony
       maxupdateskew 100.0
       refclock PHC /dev/ptp_hyperv poll 3 dpoll -2 offset 0 stratum 2
       makestep 1.0 -1

その後、ARM テンプレートの osProfile セクションで使用するために、上記の cloud-config を base64 にすることができます。

[Convert]::ToBase64String((Get-Content -Path ./cloud-config.txt -Encoding Byte))
"osProfile": {
  "customData": "I2Nsb3VkLWNvbmZpZwpudHA6CiAgZW5hYmxlZDogdHJ1ZQogIG50cF9jbGllbnQ6IGNocm9ueQogIGNvbmZpZzoKICAgIGNvbmZwYXRoOiAvZXRjL2Nocm9ueS9jaHJvbnkuY29uZgogICAgcGFja2FnZXM6CiAgICAgLSBjaHJvbnkKICAgIHNlcnZpY2VfbmFtZTogY2hyb255CiAgICB0ZW1wbGF0ZTogfAogICAgICAgIyMgdGVtcGxhdGU6amluamEKICAgICAgIGRyaWZ0ZmlsZSAvdmFyL2xpYi9jaHJvbnkvY2hyb255LmRyaWZ0CiAgICAgICBsb2dkaXIgL3Zhci9sb2cvY2hyb255CiAgICAgICBtYXh1cGRhdGVza2V5IDEwMC4wCiAgICAgICByZWZjbG9jayBQSEMgL2Rldi9wdHBfaHlwZXJ2IHBvbGwgMyBkcG9sbCAtMgogICAgICAgbWFrZXN0ZXAgMS4wIC0x"
}

Azure 上の cloud-init の詳細については、「Azure での Linux VM に対する cloud-init サポートの概要」を参照してください。

次のステップ

詳細については、「Windows Server 2016 の正確な時刻」を参照してください。