为什么`systemd-nspawn -n` 网络命名空间不显示在`ip netns list` 中?

hum*_*ace 6 iproute namespace network-namespaces systemd-nspawn

tl;dr Linux 有命名空间,特别是network namespaces. 似乎-n在运行时通过标志创建的命名空间在使用时systemd-nspwawn没有显示ip netns list(既不在主机中,也没有在假定创建的命名空间中)。它要么systemd-nspawn或ip netns不实际使用Linux的命名空间处理(这是我认为是这样的:https://lwn.net/Articles/531114/#series_index)?

长话短说:
我使用以下命令从我的 Arch Linux 中运行 Arch Linux 的“轻量级容器”:

systemd-nspawn -nbUD /mntpointArchLinuxSysFs
Run Code Online (Sandbox Code Playgroud)

数据/mntpointArchLinuxSysFs已被引导,并且“运行/启动”良好。man systemd-nspawn告诉我-noptions-flag 意味着:

-n, --network-veth

veth在主机和容器之间创建一个虚拟以太网链接(“ ”)。以太网链路的主机端将作为以容器名称(如 指定--machine=)命名的网络接口可用 ,前缀为“ ve-”。以太网链路的容器端将命名为“ host0”。该--network-veth选项意味着 --private-network.

反过来,隐含--private-network的解释如下

--private-network

Disconnect networking of the container from the host. This makes all network interfaces unavailable in the container, with the
Run Code Online (Sandbox Code Playgroud)

环回设备和用 指定--network-interface=和配置的设备除外 --network-veth。如果指定了此选项,则该CAP_NET_ADMIN能力将被添加到容器保留的能力集中。后者可以通过使用禁用--drop-capability=。如果未指定此选项(或由下面列出的选项之一隐含),则容器将具有对主机网络的完全访问权限。

这似乎是通过Linux 命名空间实现的一项壮举,尤其是Linux 网络命名空间,即启动的进程(即init容器所在的/mntpointArchLinuxSysFs/bin/init和所有子进程都在不同的网络命名空间中,即现在--private-network并且只有veth(虚拟)以太网对)作为与host命名空间/系统的剩余连接。

使用lsns显示确实systemd-nspawn创建了一个命名空间

root@host$> lsns | grep net
4026531992 net       183     1 root     /sbin/init
4026532332 net         1   824 rtkit    /usr/lib/rtkit-daemon
4026532406 net         7  4697 vu-mnt-0 /usr/lib/systemd/systemd
Run Code Online (Sandbox Code Playgroud)

但是ip netns list确实拒绝“一起玩”:

root@host$> ip netns list
root@host$>
Run Code Online (Sandbox Code Playgroud)

然后我是为了理解创建一个虚拟命名空间通过ip netns这样

root@host$> ip netns add dummy_netns
root@host$> ip netns list
dummy_netns
root@host$>
Run Code Online (Sandbox Code Playgroud)

显示网络命名空间,但讽刺的是在lsns.

总之,似乎不清楚“网络名称空间”一词在 中是如何使用的systemd-nspawn,ip netns因为我的测试似乎表明它们可能不是同一回事?也许这个词有歧义?

更新

systemd-nspawn手册页的这一部分建议恕我直言,但是实际上两者iproute和systemd-nspawn在网络名称空间方面都指的是同一件事。

--network-namespace-path= 获取表示容器应在其中运行的内核网络命名空间的文件的路径。指定的路径应引用(可能是绑定安装的)网络命名空间文件,如下面的内核所公开的/proc/$PID/ns/net。这使容器进入给定的网络命名空间。典型的用例之一是在/run/netns创建者下提供网络命名空间ip-netns(8),例如,--network-namespace-path=/run/netns/foo。请注意,此选项不能与其他与网络相关的选项一起使用,例如 --private-network 或 --network-interface=。

尽管最后一部分声明它不能--private-network再次与该选项一起使用似乎暗示了某种区别。这里发生了什么?

sjy*_*sjy 2

和systemd-nspawn都ip-netns使用命名空间,特别是网络命名空间。正如ip-netns 手册中所解释的,区别在于ip-netns处理命名网络名称空间。

按照惯例,命名网络命名空间是一个/var/run/netns/NAME可以打开的对象。打开后产生的文件描述符/var/run/netns/NAME引用指定的网络命名空间。保持文件描述符打开可以使网络命名空间保持活动状态。

匿名网络命名空间

命名空间(7)手册解释说,一般来说,命名空间是与其中进程的生命周期相关的抽象:

每个进程都有/proc/[pid]/ns/一个子目录,其中包含每个命名空间的一个条目,支持通过setns(2)...打开此目录中的文件之一(或绑定安装到这些文件之一的文件)会返回相应命名空间的文件句柄pid指定的进程。只要此文件描述符保持打开状态,命名空间就会保持活动状态,即使命名空间中的所有进程都终止也是如此。

在我的系统上,最近启动的systemd进程 ( ) 是使用默认模板单元pgrep -f -n systemd\$启动的容器的 init 进程,它启用,因此(它还添加)。此命令显示容器的匿名网络命名空间与根网络命名空间不同,并且由容器的根用户拥有:systemd-nspawn@.service--network-veth--private-network--private-users

# ls -l /proc/1/ns/net /proc/$(pgrep -f -n systemd\$)/ns/net
lrwxrwxrwx 0 root           /proc/1/ns/net -> net:[4026532008]
lrwxrwxrwx 0 vu-container-0 /proc/700/ns/net -> net:[4026532656]
Run Code Online (Sandbox Code Playgroud)

当容器终止时,这个匿名网络命名空间就会消失。但是,如果我想让它成为一个可以在ip-netns容器生命周期内进行管理的命名网络命名空间,我可以将其绑定挂载在以下位置/run/netns:

# mount --bind /proc/$(pgrep -f -n systemd\$)/ns/net /run/netns/container
# ip netns list
container (id: 1)
Run Code Online (Sandbox Code Playgroud)

使用 systemd 创建命名网络名称空间

您还指出了systemd-nspawn的--network-namespace-path选项,它相当于systemd.unit(5)NetworkNamespacePath=中记录的设置。它只能将容器和单元分配给已存在的网络命名空间。由于进程只能位于一个命名空间中,因此与创建匿名网络命名空间并隔离其中的容器等选项不兼容。--network-namespace-path--private-network

看来systemd 将在 v246 之后的某个未来版本的 systemd 中获得Namespace=设置(v245 于 2020 年 3 月发布)。这将允许单元创建自己的命名网络命名空间,而不是使用 分配给现有命名空间NetworkNamespacePath=或创建新的匿名命名空间PrivateNetwork=。Namespace=%i合并此功能后,将其添加到模板中是有意义的systemd-nspawn@.service,以便默认命名容器的网络命名空间。