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-networkRun Code Online (Sandbox Code Playgroud)Disconnect networking of the container from the host. This makes all network interfaces unavailable in the container, with the环回设备和用 指定
--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再次与该选项一起使用似乎暗示了某种区别。这里发生了什么?
和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-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,以便默认命名容器的网络命名空间。