network.targetとnetwork-online.target（備忘録）

# はじめに
備忘録です！！

# 実行環境
```
[root@tabi ~]# cat /etc/redhat-release
Rocky Linux release 8.4 (Green Obsidian)
```

# network.targetとnetwork-online.target
- [半年前の自分に教えたい systemd のハマりどころ](https://speakerdeck.com/arosh/ban-nian-qian-falsezi-fen-nijiao-etai-systemd-falsehamaridokoro)
	- ネットワークを利用できるまで待つ必要があるサービス
		- Wants=Network-online.target
		- After=Network-online.target
	- ネットワークを利用できるまで待つ必要のないサービス
		- After=Network.target
- [systemdのオプション](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/system_administrators_guide/sect-managing_services_with_systemd-unit_files)
	- Requires
		- 前提Unitが起動に失敗した場合、このUnitを起動しない
	- Wants
		- 前提Unitが起動に失敗しても、このUnitを起動する
## 起動順序
1. `network-pre.target`
2. `NetworkManager.service`
3. `network.target`
4. `network-online.target`
## NetworkManager（ネットワーク管理スタック）
- Linuxにおけるネットワーク管理のための仕組み
- manの説明等にあるネットワーク管理スタックはおそらくNetworkManagerを示している？

- 定義してある場所
	- `/sys/fs/cgroup`はLXCの内容なので、一旦スキップ
	- `/etc/systemd/system/multi-user.target.wants/NetworkManager.service`は`/usr/lib/systemd/system/NetworkManager.service`のシンボリックリンクなので、`/usr/lib/systemd/system/NetworkManager.service`を見ればOK
```
[root@tabi ~]# find / -name NetworkManager.service
/sys/fs/cgroup/pids/system.slice/NetworkManager.service
/sys/fs/cgroup/memory/system.slice/NetworkManager.service
/sys/fs/cgroup/blkio/system.slice/NetworkManager.service
/sys/fs/cgroup/devices/system.slice/NetworkManager.service
/sys/fs/cgroup/systemd/system.slice/NetworkManager.service
/etc/systemd/system/multi-user.target.wants/NetworkManager.service
/usr/lib/systemd/system/NetworkManager.service

[root@tabi ~]# ls -al /etc/systemd/system/multi-user.target.wants/NetworkManager.service
lrwxrwxrwx. 1 root root 46 10月  1  2021 /etc/systemd/system/multi-user.target.wants/NetworkManager.service -> /usr/lib/systemd/system/NetworkManager.service
```

- 内容
	- Afterに`network-pre.target`があるため、`network-pre.target`のあとに`NetworkManager.service`が起動する
		- Shutdown時は、`NetworkManager.service`を停止してから、`network-pre.target`を停止する
```
[root@tabi ~]# cat /usr/lib/systemd/system/NetworkManager.service
[Unit]
Description=Network Manager
Documentation=man:NetworkManager(8)
Wants=network.target
After=network-pre.target dbus.service
Before=network.target network.service

[Service]
Type=dbus
BusName=org.freedesktop.NetworkManager
ExecReload=/usr/bin/busctl call org.freedesktop.NetworkManager /org/freedesktop/NetworkManager org.freedesktop.NetworkManager Reload u 0
#ExecReload=/bin/kill -HUP $MAINPID
ExecStart=/usr/sbin/NetworkManager --no-daemon
Restart=on-failure
# NM doesn't want systemd to kill its children for it
KillMode=process
CapabilityBoundingSet=CAP_NET_ADMIN CAP_DAC_OVERRIDE CAP_NET_RAW CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_MODULE CAP_AUDIT_WRITE CAP_KILL CAP_SYS_CHROOT

ProtectSystem=true
ProtectHome=read-only

# We require file descriptors for DHCP etc. When activating many interfaces,
# the default limit of 1024 is easily reached.
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target # これを書くことで、/etc/systemd/system/multi-user.target.wantsの下にシンボリックリンクとして作成される
Also=NetworkManager-dispatcher.service

# We want to enable NetworkManager-wait-online.service whenever this service
# is enabled. NetworkManager-wait-online.service has
# WantedBy=network-online.target, so enabling it only has an effect if
# network-online.target itself is enabled or pulled in by some other unit.
Also=NetworkManager-wait-online.service
```

## network.target
- ネットワーク管理スタックが起動していることだけ確認している
	- ネットワークに接続できるかどうかは別
- 起動時に利用するというよりは、終了時にネットワークを利用するようなサービスにAfterで起動順序を定義することで、コネクションを終了できる
	- 綺麗にというか、エラーとしてではなく、正しい手順を踏んで終了できるみたいな意味合い（その辺は詳しくないので、合っているか不明）

- 内容
	- [RefuseManualStart](https://www.freedesktop.org/software/systemd/man/systemd.unit.html#RefuseManualStart=)
		- boolean引数を取る。trueの場合、このユニットは間接的にしか起動または停止できない。この場合、ユーザーが要求した明示的な起動や終了は拒否されますが、他のユニットの依存関係として起動または停止された場合は、起動や終了が成功します。これは主に、ユーザーが明示的に起動することを意図していないユニットを誤って起動したり、非活性化することを意図していないユニットを誤って非活性化したりしないようにするための安全機能です。これらのオプションのデフォルトはfalseである。
```
[root@tabi ~]# cat /usr/lib/systemd/system/network.target
#  SPDX-License-Identifier: LGPL-2.1+
#
#  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=Network
Documentation=man:systemd.special(7)
Documentation=https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget
After=network-pre.target
RefuseManualStart=yes
```

- `man systemd.special`
```
このユニットは、ネットワーク機能がいつ利用可能になるかを示すことになっていますが、それが何を意味するのかは非常に弱く定義されています。したがって、シャットダウン時にネットワークアクセスを必要とするサービスファイルを書くときに便利で、このターゲットの後に自分自身を配置する必要がありますが、それを引き込むことはできません。より詳しい情報は、Running Services After the Network is up[1] を参照してください。また、上記のnetwork-online.targetも参照してください。
```

- [Running Services After the Network is up[1]](https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget/)
```
network.targetは、スタートアップ時にはほとんど意味を持ちません。ネットワーク管理スタックに到達した後に、そのスタックが立ち上がっていることを示すだけです。network.targetに到達したときに、ネットワークインターフェイスがすでに設定されているかどうかは未定義です。systemd におけるユニットのシャットダウン順序は起動時の順序と逆なので、After=network.target と指定されたユニットは、システムの電源が切れたときにネットワークがシャットダウンされる前に停止していることを確認することができます。これにより、進行中の接続が突然失われ、未定義の状態になるのではなく、サービスが停止する前に接続をきれいに終了させることができます。network.targetは受動的なユニットで、直接起動することはできず、ネットワークを利用しようとするサービスから引き込まれることもありません。ネットワーク管理サービスによって引き込まれます。そのため、ネットワークを使用するサービスは、ユニットファイルに After=network.target 依存関係を置き、Wants=network.target や Requires=network.target を使用しないようにする必要があります。
```

## network-online.target
- ネットワークが利用できるようになったことを確認している
	- ネットワーク管理スタックで確認している

- 内容
	- Afterに`network.target`があるため、ネットワーク管理スタックが利用できる状態で動いている
```
[root@tabi ~]# cat /usr/lib/systemd/system/network-online.target
#  SPDX-License-Identifier: LGPL-2.1+
#
#  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=Network is Online
Documentation=man:systemd.special(7)
Documentation=https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget
After=network.target
```

- `man systemd.special`
```
設定されたネットワーク接続を厳密に必要とするユニットは、network-online.targetを（Wants=型の依存関係によって）引き込み、それ以降に自分自身を配置する必要があります。このターゲットユニットは、ネットワークが十分に設定されるまで、それ以降の実行を遅延させるサービスを取り込むことを目的としています。このために何が必要かは、ネットワーク管理サービスの実装に任されています。

このユニットとnetwork.targetの違いに注意してください。このユニットはアクティブなユニットで（つまり、この機能のプロバイダーではなく、消費者によって引き込まれる）、おそらく実行にかなりの遅延を追加するサービスを引き込みます。これに対して、network.targetは受動的なユニットで（つまり、消費者ではなく、機能の提供者によって引き込まれる）、通常、実行をそれほど遅らせません。通常、network.targetはほとんどのシステムのブートに含まれていますが、network-online.targetは、少なくとも1つのユニットが必要とする場合を除き、そうではありません。詳しくは、ネットワークが立ち上がった後のサービスの実行[1]も参照してください。

リモートネットワークファイルシステム用のすべてのマウントユニットは、自動的にこのユニットに引き込まれ、このユニットの後に自分自身を並べます。単に他のホストに機能を提供するネットワークデーモンは、一般にこのユニットを取り込む必要はないことに注意してください。

systemd は "$network" 機能を参照する LSB ヘッダーを持つ全ての SysV init スクリプトサービスユニットに、このターゲットユニットに対する Wants= と After= タイプの依存性を自動的に追加します。

このユニットは本来のシステム起動ロジックの間だけ有効であることに注意してください。システムの起動が完了した後は、システムのオンライン状態を追跡することができなくなります。
このため、ネットワーク接続のモニター・コンセプトとしては使用できず、純粋に1回限りのシステム起動のコンセプトとなります。 
```

- [Running Services After the Network is up[1]](https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget/)
```
network-online.targetは、ネットワーク管理ソフトウェアが定義する "up "状態になるまで、積極的に待機するターゲットです。通常、設定された、何らかのルーティング可能なIPアドレスを示します。その主な目的は、ネットワークがセットアップされるまでサービスの起動を積極的に遅らせることである。これはアクティブターゲットであり、ネットワークのアップを必要とするサービスによって引き込まれる可能性がありますが、ネットワーク管理サービス自体によって引き込まれることはないという意味です。デフォルトでは、/etc/fstab で定義されたすべてのリモートマウントは、ネットワーク共有に接続しようとする前に、ネットワークが起動していることを確認するために、このサービスを引き込みます。通常、どのサービスもそれを必要とせず、リモートマウントポイントが設定されていない場合、このターゲットはブートに引き込まれないので、ネットワークが利用できない場合のブート中の遅延を避けることができることに注意してください。例えば、ネットワークサーバーソフトウェアは、一般的にこのターゲットを引き込むべきではありません（サーバーソフトウェアは通常、ルーティング可能なネットワークインターフェースが立ち上がる前でも、ローカル接続を受け入れることができるからです）。
```


## network-pre.target
- よく分からん
- ネットワーク管理スタックが起動する前に動作している
- 内容
	- [RefuseManualStart](https://www.freedesktop.org/software/systemd/man/systemd.unit.html#RefuseManualStart=)
```
[root@tabi ~]# cat /usr/lib/systemd/system/network-pre.target
#  SPDX-License-Identifier: LGPL-2.1+
#
#  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=Network (Pre)
Documentation=man:systemd.special(7)
Documentation=https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget
RefuseManualStart=yes
```

- `man systemd.special`
```
このパッシブターゲットユニットは、例えばファイアウォールを設定する目的で、ネットワークが設定される前に実行したいサービスによって引き込まれることがあります。すべてのネットワーク管理ソフトウェアは、このターゲットの後に自分自身を命令するが、引き込まれることはない。
```

- [Running Services After the Network is up[1]](https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget/)
```
network-pre.targetは、ネットワークインターフェイスが設定される前にサービスを注文するために使用することができるターゲットです。このターゲットの主な目的は、ネットワークインターフェースが立ち上がる前にファイアウォールを確立したいファイアウォールサービスと一緒に使うことです。これは受動的なユニットで、直接起動することはできず、ネットワーク管理サービスによって引き込まれるわけでもなく、その前に実行したいサービスによって実行されます。したがって、ネットワーク管理サービスはAfter=network-pre.targetを設定すべきですが、Wants=network-pre.targetやRequires=network-pre.targetは避けてください。ネットワークが設定される前に実行したいサービスは、Before=network-pre.targetを設定し、Wants=network-pre.targetを設定して、それを引き込むようにする必要があります。こうすることで、ネットワークが立ち上がる前に注文する必要があるサービスが実際にない限り、ターゲットは引き込まれないので、不要な同期ポイントを回避することができます。
```