我正在尝试在 Ubuntu 中尝试挂载命名空间。到目前为止,我可以使用以下命令创建一个空的安装命名空间:
# mkdir test
# unshare --mount
# mount none test -t tmpfs
# cd test
# pivot_root . .
# cd / <--- test becomes /
当我检查LXC
Ubuntu 容器时,该mount
命令显示以下内容:
由于挂载命名空间最初获取挂载点的副本,因此我认为/dev/sda1
容器内部是全局的(因为容器启动后就/dev/sda1
没有内部的了),但容器内部的内容与其根文件系统相对应。熟悉 LXC 的人可以解释一下 LXC 在进入容器之前会执行哪些安装操作吗?/dev/sda1
/
pivot_root
答案1
要了解 LXC 实际做了什么,让我们创建一个新容器并通过以下方式跟踪其启动过程strace(1)
:
[root@localhost /]# lxc-create -n testcontainer -t debian
[root@localhost /]# strace -e trace=clone,chdir,mount,pivot_root,execve \
-f -o lxclog \
lxc-start -n testcontainer
结果跟踪被写入勒克斯克洛格文件,这里是它最相关的部分(省略号是我添加的,其中省略了一些不重要的调用):
14671 clone(child_stack=0x7fff9379eb80, flags=CLONE_NEWNS|CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWPID|CLONE_NEWNET|SIGCHLD) = 14677
<...>
14677 mount("/var/lib/lxc/testcontainer/rootfs", "/usr/lib64/lxc/rootfs", 0x7fe4c2d10eac, MS_BIND|MS_REC, NULL) = 0
<...>
14677 chdir("/usr/lib64/lxc/rootfs") = 0
14677 pivot_root(".", "/usr/lib64/lxc/rootfs/lxc_putold") = 0
14677 chdir("/")
<...>
14677 execve("/sbin/init", ["/sbin/init"], [/* 1 var */]) = 0
首先,(PID 14671)使用 生成一个新进程(lxc-start
PID 14677)clone(2)
并将其放置在新的安装命名空间(CLONE_NEWNS
标志)中。然后在这个新的挂载命名空间中容器的根文件系统(/var/lib/lxc/testcontainer/rootfs)被绑定安装(MS_BIND
标志)到/usr/lib64/lxc/rootfs,然后成为新的根。最后,当容器初始化完成后,进程14677就成为容器的init
.
这里重要的是容器的挂载命名空间的根目录是目录的绑定挂载属于主机的根FS。这就是为什么容器的根挂载仍然有/dev/sda1作为输出中的源mount(8)
。但是,还有一个未显示的差异mount(8)
- 要查看它,请findmnt(8)
在容器内尝试:
root@testcontainer:~# findmnt
TARGET SOURCE FSTYPE OPTIONS
/ /dev/sda1[/var/lib/lxc/testcontainer/rootfs]
findmnt(8)
将其与主机系统的输出进行比较:
[root@localhost /]# findmnt
TARGET SOURCE FSTYPE OPTIONS
/ /dev/sda1
请注意,来源是一样的,但是在容器内部你还可以看到绑定挂载的源目录。