LoginSignup
3
3

More than 3 years have passed since last update.

NTPサーバ名をDHCPで取得して設定する方法

Last updated at Posted at 2020-09-19

動機

孤立したローカルネットワーク内にある複数のホスト(Linux)の時刻合わせのため、そのうちの1台でNTPサーバを動かし、他をNTPクライアントで時刻同期をとることとした。各クライアントホストでは、DHCPで配信されたNTPサーバアドレスを設定することにした。

クライアントの設定の方が難儀だった。

NTPサーバの設定、およびDHCPサーバでNTPサーバ情報を配信する設定に関しては、色々な所に書かれている。一方でクライアントの設定に関しては環境依存が大きく適切な情報を見つけるのに時間を要した。クライアント側(Linux)が起動時に行なっている処理は、概ね下記のような手順をとっているようだ。

  1. DHCPクライアントが終了時にスクリプト(hook)を起動する。
  2. DHCPクライアントが起動したスクリプトがNTPクライアントの設定ファイルを更新する。
  3. 更新された設定ファイルを読んで、NTPクライアントが起動される。

ここで環境依存が発生するのは、DHCPクライアント(dhclient(ISC-DHCP), dhcpcd, NetworkManagerのinternal dhcp client, ...)と、NTPクライアント(ntpd, openntpd, chrony, systemd-timesyncd, ...)の組み合わせが多いことによる。Linuxディストリビューションによってはバージョンアップの際にデフォルトとして採用するDHCP,NTPパッケージを変わることがあるようで、それに気づかないとハマる。デフォルトでない(=使用されない)DHCPクライアントやNTPクライアントのパッケージもインストールされていたりすると、使用されることのない設定ファイルを書き換えて所期した動作をせず悩むということがおきる。

Raspberry Pi OS の場合

Raspberry Pi OS (64bit, Debian buster based)では、デフォルトのDHCPクライアント=dhcpcd, NTPクライアント=systemd-timesyncdとなっている。DHCPで呼ばれるhookは、/lib/dhcpcd/dhcpcd-hooks/50-ntp.confのようである。このファイルには、ntpd,openntpd,chrony用の記述はあるがsystemd-timesyncd用の記述がない。公式サイトのフォーラムの情報を元に、下記を追記したところ、システム起動時にNTPサーバが動的に設定されて時刻合わせがされるようになった。/etc/dhcp/dhclient-exit-hooks.d/timesyncdというファイルが存在してそれらしい実装が含まれているが、こちらは使われていないので注意が必要である。

/tmp/dhcpcd_ntp_conf(修正部分;diff出力)
--- /etc/dhcpcd.conf.orig   2019-11-13 23:44:50.000000000 +0900
+++ /etc/dhcpcd.conf    2020-09-16 08:28:53.595999273 +0900
@@ -30,7 +30,7 @@ option classless_static_routes
 option interface_mtu

 # Most distributions have NTP support.
-#option ntp_servers
+option ntp_servers

 # A ServerID is required by RFC2131.
 require dhcp_server_identifier
/lib/dhcpcd/dhcpcd-hooks/50-ntp.conf(追記)
# Set NTP servers for systemd-timesyncd

confd=/run/systemd/timesyncd.conf.d

if [ -n "$new_ntp_servers" ] ; then
    set_servers() {
        mkdir -p "$confd"
        ( echo "# Created by dhcpcd hook";echo "[Time]"; echo "NTP=$new_ntp_servers" ) > "$confd/dhcp-ntp.conf"
        # Tell timesyncd it has an updated configuration
        systemctl try-reload-or-restart systemd-timesyncd
    }
    if $if_up; then
        set_servers
    fi
fi

ちなみに、systemd-timesyncdのデフォルトの設定ファイル(/lib/systemd/system/systemd-timesyncd.service.d/disable-with-time-daemon.conf)では、他のNTPクライアントやVirtualBoxのサービスの実行ファイルが存在していたら何もしないようになっているので、50-ntp.confは置き換えでなく追記にしておいた方が無難とおもわれる。

Ubuntu MATE 20.04 LTS の場合

Raspberry Pi用のイメージ(ubuntu-mate-20.04.1-beta2-desktop-arm64+raspi.img)の場合、使われているのはNetworkManagerのinternal dhcp clientと、systemd-timesyncdの組み合わせのようである。デフォルトでdhclientもインストールされており、/etc/dhcp/dhclient-exit-hooks.d/timesyncdも用意されているので、コマンドラインで手動でdhclientを実行すると時刻の同期がされる。そこで、/etc/NetworkManager/NetworkManager.conf[main]セクションにdhcp=dhclientと追記してinternal dhcpの代わりにdhclientが使われるようにすれば良いかと思いきや、ログを見るとdhclientがエラーを吐いており、また思ったタイミングでhookが呼ばれない。

しかたがないのでdhclientを使うのは諦め、/etc/dhcp/dhclient-exit-hooks.d/timesyncdを参考にNetworkManagerのDispatherスクリプトを用意することにした。公式マニュアルにしたがって環境変数や判定文字列を修正して、/etc/NetworkManager/dispatcher.d/90-dhcp-timesyncdを作成する。

/etc/NetworkManager/dispatcher.d/90-dhcp-timesyncd
#!/bin/sh

TIMESYNCD_CONF=/run/systemd/timesyncd.conf.d/01-dhclient.conf

timesyncd_servers_setup_remove() {
    if [ -e $TIMESYNCD_CONF ]; then
        rm -f $TIMESYNCD_CONF
        systemctl try-restart systemd-timesyncd.service || true
    fi
}

timesyncd_servers_setup_add() {
    if [ ! -d /run/systemd/system ]; then
        return
    fi

    old_ntp_servers=$(sed -ne 's/^NTP=//gp')
    if [ -e $TIMESYNCD_CONF ] && [ "x$DHCP4_NTP_SERVERS" = "x$old_ntp_servers" ]; then
        return
    fi

    if [ -z "${DHCP4_NTP_SERVERS}" ]; then
        timesyncd_servers_setup_remove
        return
    fi

    mkdir -p $(dirname ${TIMESYNCD_CONF})
    cat <<EOF > ${TIMESYNCD_CONF}.new
# NTP server entries received from DHCP server
[Time]
NTP=$DHCP4_NTP_SERVERS
EOF
    mv ${TIMESYNCD_CONF}.new ${TIMESYNCD_CONF}
    systemctl try-restart systemd-timesyncd.service || true
}

logger -i -t "$0"  "action=${NM_DISPATCHER_ACTION}:NTP=${DHCP4_NTP_SERVERS}"

case $NM_DISPATCHER_ACTION in
    up|dhcp4-change)
        timesyncd_servers_setup_add
        ;;
    down)
        timesyncd_servers_setup_remove
        ;;
    *)  :
        ;;
esac

このファイルは、オーナーをrootにして実行パーミッションを与えておく必要がある。

% ls -l /etc/NetworkManager/dispatcher.d/90-dhcp-timesyncd
-rwxr-xr-x 1 root root 1140 Apr  2 02:55 /etc/NetworkManager/dispatcher.d/90-dhcp-timesyncd

このスクリプトを置くことで、時刻の同期がされるようになった。

JetPack 4.4 (Ubuntu 18.04 LTS based)の場合

Ubuntuの一つ前のバージョンでも使われているのはNetworkManagerと、systemd-timesyncdの組み合わせのようである。そのため、前節(Ubuntu MATE 20.04 LTS)と同じスクリプトで動くと思いきや、そのままでは期待した通りに動作してくれなかった。networkmanager-dispatcherのバージョンの違いのせいか、環境変数$NM_DISPATCHER_ACTIONがセットされないようである。そのため、かわりに実行時の第2引数を評価するように下記のように修正することで期待した動作がされるようになった。

NetworkManager-dispatcherのバージョン違いに対応
--- Ubuntu_MATE-20.04LTS/etc/NetworkManager/dispatcher.d/90-dhcp-timesyncd  2020-09-20 21:52:17.950941231 +0900
+++ JetPack-4.4/etc/NetworkManager/dispatcher.d/90-dhcp-timesyncd   2020-09-22 01:18:46.160691469 +0900
@@ -34,9 +34,9 @@ EOF
     systemctl try-restart systemd-timesyncd.service || true
 }

-logger -i -t "$0"  "action=${NM_DISPATCHER_ACTION}:NTP=${DHCP4_NTP_SERVERS}"
+logger -i -t "$0"  "action=${NM_DISPATCHER_ACTION:-${2}}:NTP=${DHCP4_NTP_SERVERS} $@"

-case $NM_DISPATCHER_ACTION in
+case ${NM_DISPATCHER_ACTION:-$2} in
     up|dhcp4-change)
         timesyncd_servers_setup_add
         ;;

余談だが、Ubuntu 18.04 LTSのNetworkManagerは、internal dhcp clientではなく、dhclientを利用しているようだ。

Ubuntu Server 20.04 LTSの場合

systemd-networkdのinternal dhcp clinetとsystemd-timesyncdの組み合わせとなっている模様。とくに何もしなくてもDHCPのNTPサーバが設定されるようになっている。systemd-networkd-dispatcherに関してはあまり情報を見つけられなかったので、どのような仕組みでDHCPで取得されたアドレスがsystemd-timesyncdに渡されているのかは未解明。

CentOS 7.8 (20.03), CentOS 8.2 (20.04)の場合

NetworkManagerchronyの組み合わせになっていて、何もしなくてもDHCPのNTPサーバが設定されるようになっている。余談だが、CentOS 7では、dhclientが使われていて、CentOS 8ではNetworkManagerのinternal dhcp clientが使われているようだある

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3