需用 unshare --pid --mount-proc --net=ns1 --fork bash 启动带独立 /proc 和 netns 的 shell;ip netns exec 不创建新 mount/pid 命名空间,故无法隔离 /proc、/sys;组合 user+net+pid 时须配置 uid_map/gid_map 并设 setgroups=deny。

netns 里怎么让进程看到自己的 /proc 和 /sys
默认创建的 ip netns 只隔离网络栈,/proc 和 /sys 仍是宿主机视图,导致 ps、lsmod 或容器内工具行为异常。必须手动挂载独立的伪文件系统。
实操建议:
- 先用
unshare --pid --mount-proc --user --fork bash启动带独立/proc的 shell,再进 netns;否则mount --bind到已有 netns 的/proc会失败(因为已挂载) - 进 netns 后执行:
mkdir -p /var/run/netns/ns1 mount -t proc proc /proc mount -t sysfs sysfs /sys
- 注意:挂载前确保
/proc目录为空且未被占用,否则报错Device or resource busy -
/proc挂载后,ps aux显示的 PID 是该命名空间内的 PID(从 1 开始),但实际进程仍运行在宿主机 PID 命名空间中——这是预期行为,不是 bug
为什么 ip netns exec 不继承 mount 或 pid 命名空间
ip netns exec 本质是用 setns() 系统调用切换到目标 netns,但它不创建新 mount 或 pid 命名空间,也不重挂载 /proc。所以你在 netns 里看到的仍是宿主机的挂载点和进程列表。
常见错误现象:
- 在 netns 中执行
df -h,显示的是宿主机磁盘使用情况,而非“隔离环境”的存储视图 - 用
ip netns exec ns1 ps aux看到所有宿主机进程,而非仅该 netns 内启动的进程 - 试图在 netns 内
mount --bind新路径失败,提示Permission denied(因未启用--mount权限)
解决方向:不用 ip netns exec,改用 unshare 组合命令,例如:
unshare --net=/var/run/netns/ns1 --pid --mount-proc --fork bash
多个命名空间组合时 uid_map 和 setgroups 的坑
当你同时用 --user + --net + --pid,内核要求必须配置 user namespace 的 uid/gid 映射,否则 setns() 失败或进程无法访问网络设备。
关键参数差异:
- 没配
/proc/self/uid_map就执行ip link set dev veth0 netns ns1,会报错:Operation not permitted -
setgroups必须设为deny才能写gid_map,否则报错:Operation not permitted - 典型初始化顺序:
unshare --user --net --pid --fork bash echo "0 1000 1" > /proc/self/uid_map echo "deny" > /proc/self/setgroups echo "0 1000 1" > /proc/self/gid_map
- uid_map 中第二列(host UID)必须是你当前 shell 的真实 UID,否则 netns 内
ping或ss会因权限不足失败
netns + pidns 下 systemd 服务起不来的原因
在完整隔离的 netns + pidns 中直接运行 systemd --system 几乎必然失败,不是配置问题,而是设计限制:systemd 需要访问 /dev/kmsg、/run/systemd 等全局路径,且依赖 cgroup v1/v2 的挂载状态。
实用替代方案:
- 不要在 netns 中启动完整 systemd,改用
dbus-run-session+ 单个守护进程(如dnsmasq -k -C /etc/dnsmasq.d/ns1.conf) - 若真需 init-like 行为,用
init=/bin/bash启动最小 init,再手动exec主进程,避免 fork 多进程带来的 pidns 混乱 - 检查
/proc/1/cgroup:如果显示的是宿主机 cgroup 路径(如/system.slice),说明未进入独立 cgroup,systemd 会拒绝启动 - 绝大多数场景下,“netns + 手动启动单个网络服务”比“netns + systemd”更稳定、更易调试
复杂点在于命名空间不是开关式隔离,而是叠加式约束——漏掉任意一层(比如忘了 --mount-proc 或 uid_map),就可能让某个看似无关的系统调用突然失败,而且错误信息往往不指向根本原因。










