# systemd-networkd (日本語)

関連記事

- systemd
- systemd-nspawn
- ネットワーク設定
- netctl
- Bridge with netctl

バージョン 210 から、systemd は udev と networkd による基本的なネットワーク設定のサポートを含むようになりました。

systemd-networkd はネットワーク設定を管理するシステムデーモンです。ネットワークデバイスが立ち上がるとそれを検出して設定を行い、仮想ネットワークデバイスを作成することもできます。このサービスは netctl などの通常のネットワーク管理ツールと一緒に動かすことが可能で、仮想化する場合、設定によってはツールを置き換えることもできます。特に systemd-nspawn で管理するコンテナのための基本的な、もしくは複雑なネットワーク設定 (固定 IP、ブリッジ、vlan など) を設定する場合にこのサービスはとても役に立ちます。

udev の仕事のようなネットワークインターフェイスの低レベルな設定を行うのには向いていません。

networkd は VM やコンテナなどのシンプルな設定のために作られていますが、イーサネット接続でも問題なく使うことは可能です。WiFi はサポートしていませんが、wpa_supplicant と一緒に使うことでワイヤレス接続を管理することができます。

## インストール

systemd 210 以上でサービスが利用可能です。ホストやコンテナで `systemd-networkd.service` を有効化・起動することができます。

デバッグするときのために bridge-utils, net-tools, iproute2 パッケージをインストールすることが強く推奨されます。

ネットワーク設定によっては、`systemd-nspawn@.service` を編集して `ExecStart` 行にブートオプションを追加する必要があります。オプションの完全なリストは `systemd-nspawn(1)` を参照してください。

## 設定ファイル

設定ファイルは `/usr/lib/systemd/network` から、そして一時的な実行時のネットワークディレクトリ `/run/systemd/network` とローカルのネットワーク管理ディレクトリ `/etc/systemd/network` から読み込まれます。`/etc/systemd/network` 内のファイルが一番優先されます。

3つのタイプの設定ファイルが存在します。

- .network ファイル。マッチするデバイスにネットワーク設定を適用します。
- .netdev ファイル。マッチする環境に仮想ネットワークデバイスを作成します。
- .link ファイル。ネットワークデバイスが作られた時、udev は最初にマッチする .link ファイルを探します。

これらの設定ファイルは同じルールに従っています:

- `[Match]` セクションの全ての条件がマッチすれば、プロファイルが有効になります。
- 空の `[Match]` セクションはどんな場合でもそのセクションを適用することを示します (いわば `*` ジョーカーのようなものです)。
- それぞれのエントリは `NAME=VALUE` 構文によるキーです。
- 全ての設定ファイルは辞書順でまとめてソートされ処理されます。ファイルがどのディレクトリにあるかは関係ありません。
- 同じ名前のファイルは互いを置き換えます。

Tip:

- `/usr/lib/systemd/network` にあるシステムによって提供されたファイルを上書きする (アップグレードしても変わらないようにする) には、`/etc/systemd/network` に同じ名前のファイルを配置して `/dev/null` にシンボリックリンクを張って下さい。
- `VALUE` には `*` ジョーカーを使うことができます (例: `en*` は全ての Ethernet デバイスにマッチします)。
- Arch-general スレッドによれば、特定のコンテナのネットワーク設定は networkd 設定ファイルを使ってコンテナの中で設定するのがベストプラクティスです。

### network ファイル

このファイルはネットワーク設定の変数の設定、特にサーバーとコンテナの設定のために存在します。

以下は基本的な構造の MyProfile.network ファイルになります:

    /etc/systemd/network/MyProfile.network

    [Match]
    a vertical list of keys

    [Network]
    a vertical list of keys

    [Address]
    a vertical list of keys

    [Route]
    a vertical list of keys

#### [Match] セクション

よく使われるキーは:

- `Name=` デバイスの名前 (例: Br0, enp4s0)
- `Host=` マシンのホストネーム
- `Virtualization=` システムが仮想化環境で起動されているかどうかをチェックします。`Virtualization=no` キーはホストマシンでのみ適用され、逆に `Virtualization=yes` はコンテナや VM で適用されます。

#### [Network] セクション

よく使われるキーは:

- `DHCP=` は論理値を取ります。`true` に設定すると基本的な DHCPv4 サポートが有効になります。
- `DNS=` は DNS サーバーのアドレスです。このオプションは複数個指定することができます。
- `Bridge=` はリンクに追加するブリッジの名前です。

#### [Address] セクション

`[Address]` セクションでよく使われるキーは:

- `Address=` は固定の IPv4 または IPv6 アドレスとそのプレフィックス長で、`/` を使って区切ります (例: `192.168.1.90/24`)。このオプションは必須です。

#### [Route] セクション

`[Route]` セクションでよく使われるキーは:

- `Gateway=` はマシンのゲートウェイのアドレスです。このオプションは必須です。

完全なキーのリストについては、`systemd.network(5)` を参照してください。

Tip: `Address=` が Address キーだけを含み `Gateway=` セクションが Gateway キーだけを含む場合、略式表記として `[Network]` セクションに `Address=` と `Gateway=` キーを記述することができます。

### netdev ファイル

このファイルは仮想ネットワークデバイスを作成します。

以下は基本的な構造の Mydevice.netdev ファイルになります:

    /etc/systemd/network/MyDevice.netdev

    [Match]
    a vertical list of keys

    [Netdev]
    a vertical list of keys

#### [Match] セクション

よく使われるキーは `Host=` と `Virtualization=` です。

#### [Netdev] セクション

よく使われるキーは:

- `Name=` は netdev を作成するときに使うインターフェイスの名前です。このオプションは必須です。
- `Kind=` は netdev の種類になります。現在 bridge, bond, vlan, macvlan がサポートされています。このオプションは必須です。

完全なキーのリストについては、`systemd.netdev(5)` を参照してください。

### link ファイル

このファイルはカスタム udev ルールの代わりとなりデバイスが現れた時に udev によって適用されます。

以下は基本的な構造の Mydevice.link ファイルになります:

    /etc/systemd/network/MyDevice.link

    [Match]
    a vertical list of keys

    [Link]
    a vertical list of keys

`[Link]` セクションでデバイスの設定を指定した場合、`[Match]` セクションは指定した link ファイルが指定したデバイスに適用できるかどうかを決めます。

#### [Match] セクション

よく使われるキーは `MACADRESS=`, `Host=`, `Virtualization=` です。

`Type=` はデバイスのタイプです (例: vlan)

#### [Link] セクション

よく使われるキーは:

`MACAddressPolicy=` は永続的な MAC アドレスをハードウェアに設定する persistent (ほとんどのハードウェアはこちらにするべきです) またはデバイスが現れた時にランダムな MAC アドレスを与える random を指定します。

`MACAddressPoicy=` を指定しなかった場合は `MACAddress=` を使います。

Note: ほとんどの場合システムの `/usr/lib/systemd/network/99-default.link` で基本的に問題ありません。

## 使用方法

Tip: コンテナネットワークの設定を始める前に:

- netctl サービスを全て無効にしてください。無効にすることで systemd-networkd との危険な衝突を回避することができ設定のテストが楽になります。さらに、有効な netctl プロファイルが残ったまま終了する可能性が少なくなります。`$ netctl list` コマンドは全てのプロファイルのリストを表示し、有効になっているプロファイルには星印が付きます。
- `systemd-nspawn@.service` を無効にしてコンテナを起動するときは `# systemd-nspawn -bD /path_to/your_container/` コマンドとオプションを使ってください。ログオフやシャットダウンをするには、コンテナの中で `# systemctl poweroff` を実行してください。ネットワーク設定が要求を満たすようになったら、`systemd-nspawn@.service` を有効化・起動してください。
- `dhcpcd.service` が有効になっている場合は無効にしてください。このサービスは全てのインターフェイスに dhcpcd を使わせます。
- コンテナで netctl プロファイルや、`systemd-networkd.service` が有効になっていないことを確認してください。
- トラフィックをブロックするような iptables ルールが設定されていないことを確認してください。
- コンテナ上でプライベートネットワークを設定する場合はパケットフォワーディングを有効にしてください。
- 設定ファイルを作った後、networkd デーモンが動作している場合はリロードを行なって下さい `# systemctl restart systemd-networkd`。

Note: For the set-up described below,

- we will limit the output of the `$ ip a` command to the concerned interfaces
- we assume the host is your main OS you are booting to and the container is your guest virtual machine
- all interface names and IP adresses are only examples

### 基本的な DHCP ネットワーク

以下はホストとコンテナで DHCP IP を有効にします。この場合、両方のシステムが同じインターフェイスを共有し、同じ IP を共有します。

    /etc/systemd/network/MyDhcp.network

    [Match]
    Name=en*

    [Network]
    DHCP=yes

もちろん `en*` を `$ ip link` コマンドの出力でわかる Ethernet デバイスのフルネームに置き換えることは可能です。

- ホストとコンテナで:

    $ ip a

    2: enp7s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
        link/ether 14:da:e9:b5:7a:88 brd ff:ff:ff:ff:ff:ff
        inet 192.168.1.72/24 brd 192.168.1.255 scope global enp7s0
           valid_lft forever preferred_lft forever
        inet6 fe80::16da:e9ff:feb5:7a88/64 scope link
           valid_lft forever preferred_lft forever

デフォルトのホストネームは DHCP サーバーから取得され一時的なホストネームとして使用されます。

変更するには `[DHCPv4]` セクションに `UseHostname=false` を追加してください:

    /etc/systemd/network/MyDhcp.network

    [DHCPv4]
    UseHostname=false

### 2つの別々な IP で DHCP を使う

#### Bridge インターフェイス

仮想ブリッジインターフェイスを作成する:

    /etc/systemd/network/MyBridge.netdev

    [NetDev]
    Name=br0
    Kind=bridge

- ホストとコンテナで:

    $ ip a

    3: br0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default
        link/ether ae:bd:35:ea:0c:c9 brd ff:ff:ff:ff:ff:ff

インターフェイス br0 が表示されていますが DOWN になっているので注意してください。

#### Ethernet を Bridge に関連付ける

Modify the `/etc/systemd/network/MyDhcp.network` to remove the DHCP, as the bridge requires an interface to bind to with no IP, and add a key to bind this device to br0. Let's change its name to a more relevant one.

    /etc/systemd/network/MyEth.network

    [Match]
    Name=en*

    [Network]
    Bridge=br0

#### Bridge ネットワーク

Create a network profile for the Bridge

    /etc/systemd/network/MyBridge.network

    [Match]
    Name=br0

    [Network]
    DHCP=yes

#### コンテナを起動するオプションを追加する

As we want to give a separate IP for host and container, we need to Disconnect networking of the container from the host. To do this, add this option `--network-bridge=br0` to your container boot command.

    # systemd-nspawn --network-bridge=br0 -bd /path_to/my_container

#### 結果

- on host

    $ ip a

    3: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
        link/ether 14:da:e9:b5:7a:88 brd ff:ff:ff:ff:ff:ff
        inet 192.168.1.87/24 brd 192.168.1.255 scope global br0
           valid_lft forever preferred_lft forever
        inet6 fe80::16da:e9ff:feb5:7a88/64 scope link
           valid_lft forever preferred_lft forever
    6: vb-MyContainer: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP group default qlen 1000
        link/ether d2:7c:97:97:37:25 brd ff:ff:ff:ff:ff:ff
        inet6 fe80::d07c:97ff:fe97:3725/64 scope link
           valid_lft forever preferred_lft forever

- on container

    $ ip a

    2: host0: <BROADCAST,MULTICAST,ALLMULTI,AUTOMEDIA,NOTRAILERS,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
        link/ether 5e:96:85:83:a8:5d brd ff:ff:ff:ff:ff:ff
        inet 192.168.1.73/24 brd 192.168.1.255 scope global host0
           valid_lft forever preferred_lft forever
        inet6 fe80::5c96:85ff:fe83:a85d/64 scope link
           valid_lft forever preferred_lft forever

#### 注意

- we have now one IP address for Br0 on the host, and one for host0 in the container
- two new interfaces have appeared: `vb-MyContainer` in the host and `host0` in the container. This comes as a result of the `--network-bridge=br0` option. This option implies another option, `--network-veth`. This means a virtual Ethernet link has been created between host and container.
- the DHCP address on `host0` comes from the system `/usr/lib/systemd/network/80-container-host0.network` file.
- on host

    $ brctl show

    bridge name	bridge id		STP enabled	interfaces
    br0		8000.14dae9b57a88	no		enp7s0
    							vb-MyContainer

the above command output confirms we have a bridge with two interfaces binded to.

- on host

    $ ip route

    default via 192.168.1.254 dev br0
    192.168.1.0/24 dev br0  proto kernel  scope link  src 192.168.1.87

- on container

    $ ip route

    default via 192.168.1.254 dev host0
    192.168.1.0/24 dev host0  proto kernel  scope link  src 192.168.1.73

the above command outputs confirm we have activated `br0` and `host0` interfaces with an IP address and Gateway 192.168.1.254. The gateway address has been automatically grabbed by systemd-networkd

    $ cat /run/systemd/network/resolv.conf

    nameserver 192.168.1.254

### 固定 IP ネットワーク

Setting a static IP for each device can be helpful in case of deployed web services (e.g FTP, http, SSH). Each device will keep the same MAC address across reboots if your system `/usr/lib/systemd/network/99-default.link` file has the `MACAdressPolicy=persistent` option (it has by default). Thus, you will easily route any service on your Gateway to the desired device. First, we shall get rid of the system `/usr/lib/systemd/network/80-container-host0.network` file. To do it in a permanent way (e.g even after upgrades), do the following on both host and container.

    # cp /usr/lib/systemd/network/80-container-host0.network /etc/systemd/network
    # ln -sf /dev/null /etc/systemd/network/80-container-host0.network

Then, enable and start `systemd-networkd` on your container.

The needed configuration files:

- on host

    /etc/systemd/network/MyBridge.netdev
    /etc/systemd/network/MyEth.network

A modified MyBridge.network

    /etc/systemd/network/MyBridge.network

    [Match]
    Name=br0

    [Network]
    DNS=192.168.1.254
    Address=192.168.1.87/24
    Gateway=192.168.1.254

- on container

    /etc/systemd/network/MyVeth.network

    [Match]
    Name=host0

    [Network]
    DNS=192.168.1.254
    Address=192.168.1.94/24
    Gateway=192.168.1.254

Et voila!

## 参照

- systemd.networkd man ページ
- systemd-networkd のメイン開発者、Tom Gundersen の G+ ホームページ
- Core OS のブログにおける Tom Gundersen の投稿

Categories:

- Networking (日本語)
- Virtualization (日本語)