systemd-networkdがオンラインにならないの

sysmtedはなんでもできるつおい子なので、ネットワークの設定もやってくれる. つおい

どうやって設定書くの? ということで、 man systemd.network すると, こんな風に使える感じのサンプルが載っている

Example 2. DHCP on ethernet links

# /etc/systemd/network/80-dhcp.network
[Match]
Name=en*

[Network]
DHCP=yes

This will enable DHCPv4 and DHCPv6 on all interfaces with names starting with "en" (i.e. ethernet interfaces).

だいたいDHCPでよろしくやるとべんりなので、これをこぴぺするわけだが、これで困ったことになったという話。ちゃんと名前を明示しないと、オンラインになるまで待つserviceがタイムアウトまで待ってしまう

NFSと自動生成サービス

systemdは/etc/fstabからそれぞれのmount pointに対応したserviceを自動的に生成する。 mountもserviceの起動という形で行われる。たとえば、以下のようなfstabを書いておく

naota:/linux /remote/linux nfs defaults,hard,intr 0 0

 すると、以下のようにservice fileが自動生成される

$ sudo systemctl cat remote-linux.mount
# /run/systemd/generator/remote-linux.mount
# Automatically generated by systemd-fstab-generator

[Unit]
SourcePath=/etc/fstab
Documentation=man:fstab(5) man:systemd-fstab-generator(8)
Before=remote-fs.target

[Mount]
Where=/remote/linux
What=naota:/linux
Type=nfs
Options=defaults,hard,intr

 この時mount先がNFSなので、ここには明示的には書いていないが、"network-online.target"への依存が自動的に付加される。すなわち, networkがオンラインになってからNFSにつなぎにいく, ということになる。

systemd-networkdでのnetwork-online.target

systemd-networdを使う場合、network-online.targetの前に、systemd-networkd-wait-online.serviceが起動される。

$ sudo systemctl cat systemd-networkd-wait-online.service
# /lib/systemd/system/systemd-networkd-wait-online.service
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.

[Unit]
Description=Wait for Network to be Configured
Documentation=man:systemd-networkd-wait-online.service(8)
DefaultDependencies=no
Conflicts=shutdown.target
Requires=systemd-networkd.service
After=systemd-networkd.service
Before=network-online.target

[Service]
Type=oneshot
ExecStart=/lib/systemd/systemd-networkd-wait-online
RemainAfterExit=yes

[Install]
WantedBy=network-online.target

 このserviceは、"/lib/systemd/systemd-networkd-wait-online"を起動する、というもの。 このプログラム(systemd-networkd-wait-online)は、マシンのnetwork interfaceをなめて全て(loなどはのぞくが)つながるまで待つ。

具体的にどうやって「つながった」と判定されるのか見ていこう。/run/systemd/netif/links/*にinterfaceの数だけのファイルがある。たとえばloだとこんな感じ。

$ cat /run/systemd/netif/links/1
# This is private data. Do not parse.
ADMIN_STATE=unmanaged
OPER_STATE=carrier

特に管理対象じゃありません(ADMIN_STATE=unmaged)となっている。

一方でDHCPにつないでるやつだとこんな感じ。 DHCPIPアドレスをもらっていて、 ADMIN_STATE=configuredとなっている。

$ cat /run/systemd/netif/links/3
# This is private data. Do not parse.
ADMIN_STATE=configured
OPER_STATE=routable
NETWORK_FILE=/etc/systemd/network/80-dhcp.network
DNS=なんたらかんたら
NTP=なんとかかんとか
DOMAINS=
ROUTE_DOMAINS=
LLMNR=yes
MDNS=no
ADDRESSES=.....
ROUTES=.....
DHCP4_ADDRESS=.....
DHCP_LEASE=/run/systemd/netif/leases/3

 DHCP待ちなどのタイミングでは、これが"ADMIN_STATE=configuring"となっている。

結局のところ、systemd-networkd-wait-onlineはこのへんのファイルをなめて、ADMIN_STATE=configuring(やpending)の間ループするといった動きをする。

もしも、configuredにならない場合にはdefaultで120秒のタイムアウトで終了する

LANケーブルをさしてない口があるとつらい

といった状況でLANケーブルをさしていないportがあると、その口は"configuring"のままなのでsystemd-networkd-wait-onlineはタイムアウトするまで待ちつづける. 結果として、あちこち起動が遅れてめんどいなあという気持ちになる

それでどうするの?

Name=en*にしとくとdevice名見なくてもあれこれできるけど、オンライン待ちがうざいのでちゃんと名前を書こうねという話だった