如何在私有挂载传播的不相交Mount Namespace间注入挂载?
跨不相交Mount Namespace注入绑定挂载的解决方案(容器诊断场景)
场景回顾
- 主机:挂载命名空间
mountns1、PID命名空间pidns1,根目录为/ - Container1:挂载命名空间
mountns2、PID命名空间pidns2,主机侧根目录对应/var/containers/container1-root,挂载传播模式为private;内部/c1volume挂载仅在mountns2可见,主机无法访问 - Container2:挂载命名空间
mountns3、共享主机pidns1,主机侧根目录对应/var/containers/container2-root,挂载传播模式为private;拥有特权,可通过nsenter进入主机mountns1
目标:让mountns2内的进程访问/var/containers/container2-root的文件系统,同时保留container1的pidns2,无需container1的PID 1进程配合,从容器工具层外部注入。
现有尝试的问题分析
- 主机侧直接bind-mount到
container1-root:因mountns2的private传播规则,主机侧挂载不会同步到mountns2 - 创建新命名空间:无法保留container1原有
pidns2和/c1volume的私有挂载 - 常规
pivot_root/unshare/nsenter组合:未掌握正确的命名空间切换顺序,导致无法同时保留目标PID命名空间并操作目标挂载命名空间
可行解决方案
核心思路:利用container2的特权与共享主机pidns1的特性,直接进入container1的mountns2执行挂载操作——因挂载操作在目标命名空间内完成,不受挂载传播规则限制,且无需依赖container1的PID 1进程。
具体操作步骤
- 获取container1的任意进程PID:通过容器运行时API(如
docker inspect container1 --format '{{.State.Pid}}'、ctr containers inspect container1 -q | xargs ctr task ls -q)获取container1的任意运行中进程PID(记为C1_PID) - 在container2内执行跨命名空间挂载:
若需先确保目标路径存在,可先执行:# 进入container1的mountns2,直接将container2的主机侧根目录绑定挂载到container1的目标路径 nsenter -t ${C1_PID} -m -- mount -o bind /var/containers/container2-root /var/containers/container1-root/c2volumensenter -t ${C1_PID} -m -- mkdir -p /var/containers/container1-root/c2volume
方案原理
- 挂载操作直接在
mountns2内执行,绕过了挂载传播规则的限制,挂载会立即在mountns2内可见 - 仅切换挂载命名空间(
-m参数),未改变PID命名空间,因此container1的pidns2完全保留 - 借助container2的特权(需
CAP_SYS_ADMIN能力)与共享的主机pidns1,可直接访问主机/proc文件系统,从而进入container1的mountns2
验证步骤
- 在container1的
mountns2内执行命令(可通过诊断工具或nsenter -t ${C1_PID} -m -p -- bash进入container1的环境) - 查看
/c2volume路径,确认可访问container2的文件系统 - 验证
pidns2保留:执行ps -ef,进程ID应与container1内部一致,而非主机侧PID
内容的提问来源于stack exchange,提问作者Craig Ringer
相关产品推荐
相关产品推荐

