我使用CLONE_NEWPID
和创建一个新流程chroot
/mnt/
除此之外,我使用该ip netns
命令创建一个新的 netns。
例如
ip netns add test1
知道如何让 chrooted 进程或其子进程看到这个新的 netns 吗?
根据我在 strace 上看到的内容,我尝试了:
touch /mnt/var/run/netns/test1
ip netns exec test1 mount --bind /proc/self/ns/net /mnt/var/run/netns/test1
但没有成功
答案1
请注意,这/var/run
是一个符号链接/run
,应该提前“解析”或可能使用各种命令/mnt/var/run
指向。/run
乍一看,来自初始命名空间的这个更简单的命令(而不是像最后一个注释中所解释的那样永远无法工作的 OP)应该足以允许ip netns exec
从 chroot 工作PID命名空间:
mount --bind /run/netns/test1 /mnt/run/netns/test1
但事实并非如此。这与PID命名空间,但要chroot。实际上,当不切换到新的时,整个问题是一样的PID完全没有命名空间。
ip netns exec
不只操纵网络命名空间,但也必须操作山命名空间和使用安装(2)系统调用的原因我在 SF Q/A 中解释过:无法创建嵌套网络命名空间。
问题:chroot
/proc
应安装在 chroot 内才能正确操作。至少/proc
从 chroot 中安装后,使用strace
可以看到ip netns exec test1 ...
将进入一个新的山命名空间并无法重新挂载/
:
getuid() = 0
openat(AT_FDCWD, "/run/netns/test1", O_RDONLY|O_CLOEXEC) = 3
setns(3, CLONE_NEWNET) = 0
close(3) = 0
unshare(CLONE_NEWNS) = 0
mount("", "/", 0x5595a749373f, MS_REC|MS_SLAVE, NULL) = -1 EINVAL (Invalid argument)
write(2, "\"mount --make-rslave /\" failed: "..., 49) = 49
exit_group(-1) = ?
+++ exited with 255 +++
重新安装失败并显示EINVAL
:因为chroot,/
不再是挂载点。
请注意,网络命名空间部分本身没有问题。例如,从 chroot 端执行此操作:
nsenter --net=/run/netns/test1 ip link
将成功并显示测试1的网络接口,但如果需要的话,不会/sys/
像会做的那样切换可用的相关条目(如我之前的链接中所述)。ip netns exec
解决方案:在自身之上添加绑定挂载
修复:绑定挂载chroot以自身为目标,强制将其变成挂载点,最好是在私有模式下,以避免交互(特别是当系统转为/
共享)之前做chroot。
我用 shell 命令重现了下面的工作设置。
我省略了一些样板,比如可能从 tmpfs 等安装/run
(又名 init ),但实际上应该从 chroot 内安装。/mnt/run
/proc
第 1 项中的第一个:
~# unshare --fork --pid bash
~# echo $$
1
~# mount --bind --make-private /mnt /mnt
~# chroot /mnt bash
/# mount -t proc proc /proc
那么在一个不相关的术语2中:
~# ip netns add test1
~# mkdir -p /mnt/run/netns
~# touch /mnt/run/netns/test1
~# mount --bind /run/netns/test1 /mnt/run/netns/test1
再次在第 1 学期:
/# ip netns exec test1 ip link
1: lo: <LOOPBACK> mtu 65536 qdisc noqueue state DOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
笔记:
如前所述,此问题与PID命名空间。删除该命令
unshare --fork --pid bash
将解决仅使用chroot没有PID命名空间。安装命令应该绝不从命令中运行
ip netns exec
。请记住,它ip netns exec
本身会创建一个临时安装命名空间。结束时无论坐骑完成什么都会消失ip netns exec
。这在我之前的链接中也有解释。这样做仍然可以:nsenter --net=/run/netns/test1 mount --bind /proc/self/ns/net /mnt/var/run/netns/test1
但当然不需要,因为它是完全相同的实体,可以通过在国家科学基金虚拟文件系统:
~# stat -f -c %T /run/netns/test1; stat -c %i /run/netns/test1 nsfs 4026533129 ~# nsenter --net=/run/netns/test1 sh -c 'stat -f -L -c %T /proc/self/ns/net; stat -L -c %i /proc/self/ns/net' nsfs 4026533129