令和の時代にネットワークデバイス名をeth*にする(解決編)

[前回の記事](https://qiita.com/liqsuq/items/bb2d9d3bebc49bc80d0e)を書いてしばらくしてから思いつきました、「tmp\*に退避する位ならinitramfsでは予測可能な命名でもいいのでは？」と。

そうした場合、

- 別々のudevルールで設定できるので上手く設定すればinitramfsを更新しても問題ない。
- 1度目の命名をわざわざ全てのデバイスに対して行わなくてよい。(勝手にeth\*が空いてくれる)
- 万が一2度目の命名に失敗してもtmp\*ではなく予測可能な命名になる。

# 手順1
まずsystemd/udevの予測可能な命名を有効にするため、`cat /proc/cmdline`を実行する等して`net.ifnames=0`になっていないことを確認してください。

# 手順2
2段階udev命名を行うために、使用予定の全てのドライバをinitramfsに含めます。[前回の対処法ex3](https://qiita.com/liqsuq/items/bb2d9d3bebc49bc80d0e)ではmodprobe.dのsoftdepを使って横着しましたが今回は正攻法でやります。

## RHEL系の場合
```: /etc/dracut.conf
add_drivers+="e1000e tg3 ixgbe igb"
```

## Debian系の場合
```: /etc/initramfs-tools/modules
e1000e
tg3
ixgbe
igb
```

# 手順3
「initramfsでは予測可能な命名になり、ルートマウント後はユーザ定義の命名ルールを使用する」挙動を設定します。initramfsでは(lib)/80-net-setup-link.rulesが有効となり、ルートマウント後は(etc)/50-net-fixed.rulesが動作する様にすればいい訳です。そのために50-net-fixed.rulesのinitramfsへの**書き込みを確実に防ぐ**必要があります。

```: /etc/udev/rules.d/50-net-fixed.rules
ACTION=="add", SUBSYSTEM=="net", DRIVERS=="?*", ATTR{address}=="aa:aa:aa:aa:aa:aa" , NAME="eth0"
:
```

## RHEL系の場合
デフォルトでは自作のudevルールは自動でinitramfsに書き込まれないのでそのままinitramfsを更新します。[前回記事](https://qiita.com/liqsuq/items/bb2d9d3bebc49bc80d0e#rhel%E7%B3%BB%E3%81%AE%E5%A0%B4%E5%90%88)で/etc/dracut.conf.d/net-fixed-rules.confを作成していた場合は削除してください。

```
$ sudo dracut -f
```

## Debian系の場合
ちょっとややこしいです。initramfs-tools-coreパッケージの/usr/share/initramfs-tools/hooks/udevフックによって、/etc/udev/rule.d/以下のudevルールは/lib/udev/rules.d/以下に同名のルールが存在しない場合に/lib/…に移動してinitramfsに書き込まれます。そのため/lib/…の方に空ファイルを作成します。

```
$ sudo touch /lib/udev/rules.d/50-net-fixed.rules
```

その後initramfsを更新します。

```
$ sudo update-initramfs -u -k all
```

# 動作確認
異種のネットワークデバイス(オンボード/Intel X520-DA/Intel I350/Broadcom BCM5720)を挿してそれらを任意のeth\*に振り直して確認しました(括弧内はポート番号)。

|ドライバ|デバイス|予測可能な命名|振り直し後|
|:----|:---|:---|:---|
|e1000e|オンボード|enp0s25|eth0|
|tg3|BCM5721(1)|enp9s0f0|eth1|
|tg3|BCM5721(2)|enp9s0f1|eth2|
|ixgbe|X520-DA(1)|ens4f0|eth3|
|ixgbe|X520-DA(2)|ens4f1|eth4|
|igb|I350(1)|ens1f0|eth5|
|igb|I350(2)|ens1f1|eth6|
|igb|I350(3)|ens1f2|eth7|
|igb|I350(4)|ens1f3|eth8|

以下のログの通り、initramfsで予測可能な命名→ルートマウント→eth\*に振り直しと動作しています。何パターンか振り直し方を変えてもちゃんと動作してくれました。

```
... kernel: tg3 0000:03:00.1 ens4f1: renamed from eth1
... kernel: tg3 0000:03:00.0 ens4f0: renamed from eth0
... kernel: e1000e 0000:00:19.0 enp0s25: renamed from eth0
... kernel: ixgbe 0000:01:00.0 ens1f0: renamed from eth1
... kernel: ixgbe 0000:01:00.1 ens1f1: renamed from eth4
... kernel: igb 0000:09:00:1 enp9s0f1: renamed from eth2
... kernel: igb 0000:09:00:0 enp9s0f0: renamed from eth0
... kernel: igb 0000:09:00:2 enp9s0f2: renamed from eth3
... kernel: igb 0000:09:00:3 enp9s0f3: renamed from eth1
    :
... systemd[1]: Starting Remount Root and Kernel File Systems...
    :
... kernel: tg3 0000:03:00.1 eth2: renamed from ens4f1
... kernel: tg3 0000:03:00.0 eth1: renamed from ens4f0
... kernel: ixgbe 0000:01:00.1 eth4: renamed from ens1f1
... kernel: ixgbe 0000:01:00.0 eth3: renamed from ens1f0
... kernel: igb 0000:09:00.1 eth6: renamed from enp9s0f1
... kernel: igb 0000:09:00.3 eth8: renamed from enp9s0f3
... kernel: igb 0000:09:00.0 eth6: renamed from enp9s0f0
... kernel: igb 0000:09:00.2 eth7: renamed from enp9s0f2
... kernel: e1000e 0000:00:19.0 eth0: renamed from enp0s25
```

:::note alert
RHEL系の場合古い環境を引き継いでいて、70-persistent-net.rulesがあったりifcfg-\*にHWADDR行があるとudevルール優先順位の都合で想定通りに動きません。うまく動作しない場合、これらの設定でeth\*に命名されていないかチェックしてください。
:::

# 結び
トリッキーですが一応安定して動く解決策が見つかりました。しかし「ユーザ操作によるeth\*命名はカーネルが予約している名前空間の侵害」というスタンスは変わりません。可能な限り回避すべきです。