systemd-networkd入門
概要
systemd-networkdや関連ツールおよびサービスの基礎的なところから、設定ファイルの書き方、各設定項目の意味などをなるべく具体例を含めつつ書いていきます。
目次
- はじめに
- systemd-networkdを使うにあたって
- .networkファイルの基礎
- systemd.network(5)の日本語訳プラスアルファ
- .netdevファイルの基礎
- systemd.netdev(5)の日本語訳プラスアルファ
- systemd-udevdについて
- .linkファイルの基礎
- systemd.link(5)の日本語訳プラスアルファ
- 最後に
はじめに
まだ書き始めたばかりですが公開してしまいます。随時更新していきます。
自己紹介とか
Yu Watanabeと申します。systemdを開発しているエンジニアの一人です。最近は特にsystemd-networkdやsystemd-udevdの開発をメインに行っています。
Zennへの最初の投稿としてsystemd-networkdについて書いてみます。Zennどころか技術系の記事を投稿したこと自体が初めてですので、暖かく見守っていただければと思います。
もしも内容が充実してきたら無料の本に転換するかもしれません(そういうことしてもいいのかな?)。後半はmanページの日本語訳になる予定ですので、今のところ、有料化はする予定はありません。てか、そういうことってしていいの?サポートはもちろん大歓迎です。
この文章の目的等
この文章は一人でも多くの方にsystemd-networkdを使っていただきたい、という目的で書いています。systemd-networkdの基本的な使い方から設定ファイル(.networkや.netdev)の書き方まで説明してみます。また、systemd-networkdではなくsystemd-udevdが用いるものですが、.linkファイルについても説明できればいいなと思っています。一朝一夕に書ききれる内容では無いので、公開後もちょくちょく更新していきたいと思っています。
また、本書後半のmanページの翻訳をするにあたって、manページの間違いを正したり不足している説明をupstreamにbackportしていくことも目的の一つです。
最後に、systemd-networkdの開発をしているにも関わらず私はネットワークの知識が豊富かと問われれば全くそんなことはありません。私にとってこの文章を書くもう一つの目的は、私自身のネットワーク関連の知識を充実させるためにあります。
間違いの指摘やバグ報告など
この文章の間違いを指摘して下さるのは大歓迎です。日本語の修正やtypoの指摘,Markdownの書き方のアドバイスなどもwelcomeです。しかし、本ページの内容に関してsystemdのメーリングリストに投稿したりGitHubのissueを作成するのはやめてください。このページのコメント欄やtwitterなどで私宛にご連絡下さい。
systemd-networkdそのもののバグを見つけた場合は、最新の2リリース(2020-09-27現在だとv246およびv245)を使用している場合についてはupstreamにてissueを作成していただけると助かります。それより古いものを使用している場合は、使用しているディストリビューションのバグトラッカー(Red Hat Bugzillaなど)にご連絡下さい。また、バグかどうか自信がない場合や英語にバリアを感じる場合などは、本ページのコメント欄やtwitterなどでまず私に相談していただいても構いません。
著作権とか
本書はYu Watanabeの著作物ですが、コピーしたり他のWikiなどに転載したり自由にしていただいて構いません。売れるもんだったら勝手に売って儲けてくれたって構わないです。その際に私の名前をmentionしてくれたり、私に連絡をいただけるととても嬉しいです。
本書はgithub連携機能を用いて書いています。gitのレポジトリの方からcloneするなりして使っていただいても結構です。
必要となるバックグラウンドや環境について
ネットワークの超基礎的なところを理解していれば大丈夫なように書くつもりです。とは言え、どこまでが'超基礎的'なのかは主観によると思いますので、ご容赦を。
必要となる環境は比較的新しいsystemdを採用しているLinuxです。systemd-networkdはsystemdを前提としているため、systemdを使用していないディストリビューションでは使用できません。
タイムラグは必然的に生じてしまいますが、現在のmasterブランチのsystemdを対象として書き、随時更新していく予定です。
なお、私がこの原稿を書いているシステムは、Fedora 32 (with systemd-245.8-2.fc32.x86_64)にsystemd-networkdとsystemd-udevdだけ現在のgitのmasterブランチのソースからコンパイルしたものになっています。
systemd-networkdを使うにあたって
本章ではsystemd-networkdを使うための準備や、関連コマンドおよびサービスについて説明していきたいと思います。
systemd-networkd.serviceを有効化する
まず、systemd-networkdが有効化されているかどうか調べてみましょう。
$ systemctl status systemd-networkd.service
このとき、
$ systemctl status systemd-networkd.service
● systemd-networkd.service - Network Service
Loaded: loaded (/usr/lib/systemd/system/systemd-networkd.service; enabled; vendor preset: disabled)
Active: active (running) since Sun 2020-09-27 22:56:09 JST; 2h 19min ago
Docs: man:systemd-networkd.service(8)
Main PID: 556 (systemd-network)
Status: "Processing requests..."
Tasks: 1 (limit: 9383)
Memory: 62.2M
CPU: 4.941s
CGroup: /system.slice/systemd-networkd.service
└─556 /usr/lib/systemd/systemd-networkd
(以下略)
のように表示されていれば、既にsystemd-networkd.serviceが有効化されていて(Loaded欄のユニットファイル名直後がenabledになっている。presetはここではどうでもよい)、また、起動しています(Active欄がactiveになっている)。
もしも、
$ systemctl status systemd-networkd.service
Unit systemd-networkd.service could not be found.
と表示された場合は、そもそもsystemd-networkdがインストールされていません。systemd-networkdをインストールして下さい。ちなみに、Fedora 32ではsystemdのメインrpmにsystemd-networkdが含まれているので、別途インストールする必要はありません。Fedora 34からはsystemd-networkdは別パッケージで提供されることになりそうです(より正確にはsystemd-246.6-2.fc34以降。See also)。RHEL8ではsystemd-networkdは提供されていないらしいです(未確認)。次節を参考にするなどしてソースからコンパイルして下さい。
もしも、systemd-networkd.serviceが無効化されている(Loaded欄がdisabledになっている)場合は、
$ sudo systemctl enable systemd-networkd.service
として有効化しましょう。また、systemd-networkd.serviceが無効化されている場合、ほとんどの場合において、NetworkManager.serviceやifupdownなど、別のネットワーク管理のためのserviceが起動・有効化されているはずです。それらを停止・無効化しておきましょう。例えば以下のような感じで。
$ sudo systemctl disable NetworkManager.service
$ sudo systemctl stop NetworkManager.service NetworkManager-dispatcher.service
その後、
$ sudo systemctl start systemd-networkd.service
としてserviceを起動しましょう。
最新のsystemd-networkdをビルドして試すには
使用しているディストリビューションが提供しているsystemdのバージョンが古く、最新のsystemd-networkdを試したい場合や、そもそもディストリビューションがsystemd-networkdを提供していない場合などは以下の方法が参考になるかもしれません。
また、この方法は、自分の使用しているsystemd-networkdにバグが有り、最新のコードで修正されているかどうか確認したい場合にも役に立つかもしれません。
なお、以下はsystemd-networkdなどのserviceだけを最新にする方法です。systemd自体(PID 1)も最新にしたい場合は、最新のコードからrpmを作成することをオススメします。
まず、適宜systemdのビルドに必要な環境を構築して下さい。例えばFedoraだと、
$ sudo dnf install dnf-plugins-core
$ sudo dnf builddep systemd
とすることで必要なものがインストールされます。
適当な場所にgithubからコードをダウンロードしてきます。以降では~/systemd
にダウンロードしたとします。
$ cd
$ git clone https://github.com/systemd/systemd.git
ホームディレクトリでは 無い 場所にビルドディレクトリを作成し、所有権を変更します。以降では/var/build
, ユーザはyuwataとします。
$ sudo mkdir /var/build
$ sudo chown yuwata:yuwata /var/build
ビルドします。
$ cd /var/build
$ meson ~/systemd .
$ ninja
ディストリビューションがsystemd-networkdを提供していない場合は、ユニットファイルをコピーします。
$ sudo cp /var/build/units/systemd-networkd.service /etc/systemd/system/.
$ sudo cp ~/systemd/units/systemd-networkd.socket /etc/systemd/system/.
systemd-networkd-wait-online.serviceなども必要に応じてコピーします。
ユニットファイルを編集します。
$ sudo systemctl edit systemd-networkd.service
適当なエディタが起動するので、以下のように記載してExecStart=
を書き換えます。
[Service]
ExecStart=
ExecStart=/var/build/systemd-networkd
このとき、必ず空のExecStart=
行が要ります。必要に応じてsystemd-networkd-wait-online.serviceなども編集して下さい。
networkctlによる状態確認
systemd-networkdと対になるコマンドラインツールがnetworkctl
です。
まずは、networkctl
単体で走らせてみましょう。(前節でビルドしたものを使用する場合は/var/build/networkctl
とフルパスを指定して下さい。)
.networkファイルを何も作成していない状況だと、
$ networkctl
IDX LINK TYPE OPERATIONAL SETUP
1 lo loopback carrier unmanaged
2 enp0s31f6 ether no-carrier unmanaged
3 wlp59s0 wlan degraded unmanaged
3 links listed.
のような出力になるはずです。上記の例では有線のポートenp0s31f6
と無線LANポートwlp59s0
の2つのネットワークインターフェイスが存在することを示しています。unmanaged
というのはsystemd-networkdが管理していないインターフェイス、ということを意味しています。詳しくは次の節で。
詳細な.networkファイルの書き方は後の章で述べるとして、例えば、以下のような.networkファイルを作成してみましょう。
- /etc/systemd/network/50-wired.network
[Match]
Name=enp0s31f6
[Network]
DHCP=yes
- /etc/systemd/network/50-wireless.network
[Match]
Name=wlp59s0
[Network]
DHCP=yes
.networkファイルを再読込(v244以上)もしくはsystemd-networkd.serviceを再起動します。
$ sudo networkctl reload
or
$ sudo systemctl restart systemd-networkd.service
再度networkctl
で状態を表示してみましょう。
$ networkctl
IDX LINK TYPE OPERATIONAL SETUP
1 lo loopback carrier unmanaged
2 enp0s31f6 ether no-carrier configuring
3 wlp59s0 wlan routable configured
3 links listed.
SETUP欄がunmanaged
からconfiguring
もしくはconfigured
に変わっていると思います。上記の例では有線のケーブルが刺さってないため、enp0s31f6
はconfiguring
になっています。
無線LANポートwlp59s0
の詳細な情報を表示してみましょう。
$ networkctl status wlp59s0
● 3: wlp59s0
Link File: /usr/lib/systemd/network/99-default.link
Network File: /etc/systemd/network/50-wireless.network
Type: wlan
State: routable (configured)
Alternative Names: wlxXXXXXXXXXXXX
Path: pci-0000:3b:00.0
Driver: iwlwifi
Vendor: Intel Corporation
Model: Wireless 8265 / 8275 (Dual Band Wireless-AC 8265)
HW Address: XX:XX:XX:XX:XX:XX (Intel Corporate)
MTU: 1500 (min: 256, max: 2304)
WiFi access point: WIFI_SSID (YY:YY:YY:YY:YY:YY)
Queue Length (Tx/Rx): 1/1
Address: 192.168.86.250
fe80::xxxx:xxxx:xxxx:xxxx
Gateway: 192.168.86.1 (COMPANY_NAME)
DNS: 192.168.86.1
Search Domains: lan
(ログは省略)
systemdやkernelのバージョンやネットワーク環境によって表示される項目や内容は変わりますが、概ね上記のような感じになるはずです。なお、networkctl -s status wlp59s0
のように-s
オプションを追加することでそのインターフェイスの統計情報を表示することも出来ます。
インターフェイス名を指定せずにstatus
コマンドを実行するとシステムに割り当てられている全てのIPアドレスの情報などが表示されます。ただし、下記の例ではenp0s31f6
にケーブルが刺さっていないので、wlp59s0
がDHCPで取得した情報のみが表示されています。
$ networkctl status
● State: routable
Address: 192.168.86.250 on wlp59s0
fe80::xxxx:xxxx:xxxx:xxxx on wlp59s0
Gateway: 192.168.86.1 (COMPANY_NAME) on wlp59s0
DNS: 192.168.86.1
Search Domains: lan
(ログは省略)
operational stateとsetup stateについて
networkctl
で表示されるOPERATIONAL
欄とSETUP
欄の意味について説明したいと思います。基本的にはnetworkctl(1)の部分的な翻訳プラスアルファです。
まずはoperational stateから。
- missing
デバイスが存在しない。(基本的にはお目にかかれないはずです。デバイスを削除しつつ同時にnetworkctl
を叩くようなracyな状況では原理的には可能か?) - off
デバイスの電源がオフ。 - no-carrier
デバイスの電源はオンだが、キャリアが存在しない。例えば、有線LANポートの場合はケーブルが刺さっていない、無線LANポートの場合はアクセスポイントに接続していない、など。 - dormant
キャリアは存在するが、通常のトラフィックを流す準備が出来ていない。例えば、802.1X認証が完了していない、など。kernelのoperstateについてのドキュメントのIF_OPER_DORMANTの説明を参照。 - degraded-carrier
bridgeもしくはbondのmasterインターフェイスにおいて、1つ以上のslaveインターフェイスがoff, no-carrier, dormantのどれかの状態にある。 - carrier
キャリアが存在する。bridgeもしくはbondのmasterインターフェイスにおいては、全てのslaveインターフェイスがcarrierもしくはそれ以上の状態にある。 - degraded
キャリアが存在し、ローカル接続において有効なアドレスが割当てられている。 - enslaved
キャリアが存在し、bridgeもしくはbondのmasterインターフェイスのslaveインターフェイスとして割当てられている。
- routable
キャリアが存在し、ルート可能なアドレスが割当てられている。
余談ですが、operational stateは、内部的にはcarrier stateとaddress stateの2つから決定されています。networkd-link.cより。
/* Mapping of address and carrier state vs operational state
* carrier state
* | off | no-carrier | dormant | degraded-carrier | carrier | enslaved
* ------------------------------------------------------------------------------
* off | off | no-carrier | dormant | degraded-carrier | carrier | enslaved
* address_state degraded | off | no-carrier | dormant | degraded-carrier | degraded | enslaved
* routable | off | no-carrier | dormant | degraded-carrier | routable | routable
*/
次に、setup stateについて。
- pending
systemd-udevdがまだデバイスの初期化を完了していない。systemd-networkdはまだこのデバイスを管理するかどうか決定していない。 - failed
systemd-networkdがデバイスを管理するのに失敗。基本的にはどこかがバグってる状態。 - configuring
デバイスの設定中。 - configured
デバイスの設定が完了。 - unmanaged
systemd-networkdはこのデバイスを管理していない。 - linger
既にこのデバイスは削除されているが、このデバイスの情報がsystemd-networkdのメモリ上に残っている。
systemd-networkd-wait-online.serviceの使用方法
systemd-network-generator.serviceについて
トラブルシューティング
まずはjournalログを確認してみましょう。例えば、
$ journalctl -b -u systemd-networkd.service
でsystemd-networkd.serviceについてのログが表示されます。システム全体のログを表示したければjournalctl -b
だけでOKです。余談ですが、一番下までスクロールするのが面倒であれば、-r
オプションもオススメ。また、バグ投稿時などにホスト名を隠したければ、--no-hostname
オプションも便利です。他には-f
or --follow
オプションもいいかも。詳しくはjournalctl(1)を見て下さい。
もしも、それらしいエラーメッセージが見つからなかったり、エラー内容がよくわからない場合は、デバッグログを出力させるようにしてみましょう。systemdの提供するサービスおよびツールはSYSTEMD_LOG_LEVEL=
環境変数でログレベルを変更できます。これをdebug
に設定すればデバッグログを出力することが出来ます。
サービスに対して環境変数を設定するには、例えば、
$ sudo systemctl edit systemd-networkd.service
として、起動したエディタ上で、
[Service]
Environment=SYSTEMD_LOG_LEVEL=debug
と記載し、
$ sudo systemctl restart systemd-networkd.service
でサービスを再起動しましょう。この方法はsystemd-networkd-wait-online.serviceやsystemd-udevd.serviceなど他のサービスに対しても使えます。
なお、networkctl
やudevadm
などのコマンドラインツールに対しては、
$ SYSTEMD_LOG_LEVEL=debug networkctl
とすることでデバッグログを表示できます。
デバッグログを出力させたら、再度journalctl
でログを表示させてみましょう。なお、ネットワークインターフェイスやnetdevが大量にありログを追いかけにくい場合は、
$ networkctl status eth0
などとすることで特定のインターフェイスのログのみ表示することもできます(v245以上)。このとき、オプションで-n 1000
などとすることで出力する行数を指定できます。
.networkファイルの基礎
systemd.network(5)の日本語訳プラスアルファ
.netdevファイルの基礎
systemd.netdev(5)の日本語訳プラスアルファ
systemd-udevdについて
.linkファイルの基礎
systemd.link(5)の日本語訳プラスアルファ
最後に
是非systemd-networkdを使ってみて下さい。
更新履歴
- 2020-09-27 1章と2章の半分ぐらい。
途中まで書いていて思ったけど、現状書けてる範囲って、たぶんArchとかGentooのWikiにあるんじゃないだろうか。。。悔しいから今日は見ない。 - 2020-09-28 著作権について軽くコメント。
Discussion