VMware Server 2.0.1で、Debian Lenny 時計が狂うよ~ | 雲の上はいつも青空

雲の上はいつも青空

不思議な経歴をもつエンジニア!?の徒然なブログです。
お仕事関係の話が多いと思いますが、コメントとかもらえると中の人はとても喜びます(^O^)/

調べてみるとFAQみたいですが、結構やり方が大変なので、備忘録代わりに書いておきます。
また、人それぞれというかいろんなお作法があるようですが、私がいろいろ試して落ち着いた方法は…

1.起動時のkernelパラメータに追加で、Clockの変更を記述する。
2.adjtimexを導入する。
3.統計的に時計のずれを調査し、adjtimexでTick値を絞り込む。
4.後は、ntpなりopenntpdでNTPサーバと同期を取る。

このやり方で、VMwer Server 2.0.1 + Debian GNU/Linux 5.0 lenny環境で時刻の狂いは収まりました。

1.起動時のkernelパラメータに追加で、Clockの変更を記述する。
これは、デフォルトのクロックソースであるtscから、acpi_pmへ変更するという意味です。tscというクロックソースはCPUの割込みをベースに動いているので、仮想環境下ではどうもうまくうごかないようです。この辺はいろいろ調べてみると面白いのです。HPETというタイマーが一番正確っぽいですが、今回のケースでは残念ながら利用できませんでした。
# cat /sys/devices/system/clocksource/clocksource0/available_clocksource
で、どんなクロックソースが使えるか出てきます。
※VMware serverが可変クロック環境下での割込み動作を正確に再現できていない…というのが真相らしいですヽ(´ー`)ノ

VMware社のナレッジデータベースを見ても、どうやらacpi_pmへ変更するのが正解っぽいです。

具体的には、/boot/grub/menu.lst を開き、
title      Debian GNU/Linux, kernel 2.6.26-2-686
root (hd0,0)
kernel /vmlinuz-2.6.26-2-686 root=/dev/mapper/minolin-root ro quiet
initrd /initrd.img-2.6.26-2-686
を、以下のように変更して再起動します。
title      Debian GNU/Linux, kernel 2.6.26-2-686
root (hd0,0)
kernel /vmlinuz-2.6.26-2-686 root=/dev/mapper/minolin-root ro quiet clocksource=acpi_pm
initrd /initrd.img-2.6.26-2-686
# cat /sys/devices/system/clocksource/clocksource0/current_clocksource
acpi_pm

で、ちゃんとクロックソースが切替わっているか確認できます。

【追記】2009/10/26にVMware serverのV2.0.2がリリースされてまして、このバージョンを使うとデフォルトでクロックソースは、acpi_pmで起動します。ですので、このstep1の作業は不要となります。
リリースに関する詳しい情報はこちら

2.adjtimexを導入する。
これは時計関係のパラメータを変更するためのソフトです。
debian環境であれば、aptitude install adjtimex でインストールは簡単です。
70秒ほど待機すると、初期値を自動で設定してくれます。
インストール後は、adjtimex -p で設定内容が表示されます。
# adjtimex -p
mode: 0
offset: 0
frequency: 0
maxerror: 16000000
esterror: 16000000
status: 64
time_constant: 2
precision: 1
tolerance: 32768000
tick: 10024
raw time: 1245996646s 542050us = 1245996646.542050
return value = 5
このtick値が重要で、ここで時計の大まかな進み・遅れを調整します。
※ntpのようなソフトは、tick値は変更しないでその上にあるfrequency値を変化させます。frequency値は、tick値よりもっと小さい範囲で調整するパラメータのようです。


3.統計的に時計のずれを調査し、adjtimexでTick値を絞り込む。
まずは、時計のずれがどのくらいかを計測します。
host ntp.nict.jp で、タイムサーバのIPアドレスを一つ拾ってきます。
次に、そのIPを使って計測するのですが、私は180秒(3分)の計測を5回繰り返し、その一番大きい値と小さい値を捨て、残り3つで平均をとりました。
※ntpdateを使うので、インストールしてない場合は、aptitude install ntpdateをする。
※ntpdateはntpと同じポートを使うので、/etc/init.d/ntp stopでntpを止めておく。
# ntpdate 133.243.238.243; sleep 180; ntpdate 133.243.238.243;
26 Jun 15:39:00 ntpdate[10457]: adjust time server 133.243.238.243 offset 0.009573 sec
26 Jun 15:42:00 ntpdate[10461]: adjust time server 133.243.238.243 offset 0.341126 sec
まずは一行目がすぐ表示され、二行目は3分後に表示されます。
この二行目のオフセット値をメモります。
※上記の例だと、0.341126になります。
※この値が+だと時計は遅れていることを意味し、-だと進んでいることになります。

計測が終わり平均値が仮に0.32165だとします。
この平均値を計測時間180秒で割ると… 0.32165 / 180 * 100 = 0.17869%
つまり、約0.18%時計が遅れていることを意味します。

tick値=+1で0.01%時計が進むので、この場合だと現在のtick値に18をプラスして再度同じように計測します。二回ほどこの計測を繰り返し、tick値を決定します。
※tick値の設定は、adjtimex -t ○○と設定します。
※上手に設定できると、offset値は(例:-0.004478 secくらいに)小さくなります。

計算上のtick値の補正が1以下になれば、補正は完了です。
その値を、/etc/default/adjtimex に設定します。この際、frequency値は0(ゼロ)にしておきます。


4.後は、ntpなりopenntpdでNTPサーバと同期を取る。
ntpは補正する際にfrequency値を変化させていきますが、openntpdはfrequency値は触らないようです(どこで設定してるのかしら??)。
どちらの場合でも約20分ほど放置しておいて、ntpであればntpq -pで動作を確認してください。複数表示されるntpサーバ名のどれかに*マークがついていれば、クロックの同期がどれています。
openntpdの場合は、grep ntpd /var/log/daemon.log で、ログを検索し、clock is now synced というログが残っていれば同期がとれています。

結構面倒ですが私の場合上記の方法で、いまのところ時計のずれは収まっています。
ちなみにVMware server側では特別何も設定はしていません。
ホストOSがWindows server 2008 Foundationなので、単にwindows上でNTPサーバの設定を行っているだけです。

この方法は、仮想環境だけでなくスタンドアロンサーバでも有効です。
もし、なんだか知らないけど時計がずれて困る場合には使ってみるといいかもしれません。
最後になりましたが、sh2さんのブログがとても参考になりました。本当にありがとうございます。とてもロジカルですっきりしたブログ&文体でわかりやすかったです。


【追記】Windows serverにntpの設定って、意外と調べると手間取るので、簡単に書いておきます。
コマンドラインで以下のコマンドを投入します。
>net time /setsntp:ntp.nict.jp
>net stop w32time
>net start w32time
>w32tm /resync
以上のコマンドが全て正常終了すると、設定が終了です。
念のため、『サービス』を開いてみて自動起動になっていることを確認してください。
これで、このWindowsサーバはntpサーバとしても稼動しています。