Linux Namespace 是容器隔离核心机制,提供 PID、Mount、Network、UTS、IPC、User 六种资源视图隔离,需动手实践理解其进程视角差异与组合使用陷阱。

Linux Namespace 是实现容器隔离的核心机制,它让进程拥有独立的视图——比如自己的 PID、网络、挂载点、用户 ID 等,而无需依赖虚拟机。理解它不靠死记概念,关键在于动手看到“同一个系统,不同进程看到的世界为何不同”。
Namespace 的六种类型与各自作用
目前 Linux 提供 6 种主要 Namespace(另有 cgroup 和 time 正在演进中),每一种都封装一类系统资源的视角:
-
PID Namespace:进程 ID 空间隔离。子命名空间中 init 进程(PID=1)只看到自己空间内的进程,对宿主机 PID 完全不可见;父空间能看到全部,但需用
setns()或nsenter才能进入子空间视角。 -
Mount Namespace:文件系统挂载点隔离。
unshare --mount后执行mount只影响当前命名空间,不影响宿主机或其他命名空间。常配合MS_REC | MS_PRIVATE防止挂载传播。 -
Network Namespace:网络栈隔离。包含独立的 netdev、IP 地址、路由表、iptables 规则、socket 等。用
ip netns add创建后,需手动配 veth 对或使用nsenter -n进入调试。 -
UTS Namespace:主机名和域名隔离。
unshare --uts hostname mycontainer后,uname -n返回新名字,且不影响其他命名空间。 - IPC Namespace:进程间通信资源隔离(消息队列、信号量、共享内存)。避免不同环境间 IPC key 冲突,尤其在多租户服务中很实用。
-
User Namespace:UID/GID 映射隔离。普通用户可在其中以 root(UID 0)运行,但该 root 在宿主机上可能映射为 100000,从而实现无特权容器。需开启内核选项
CONFIG_USER_NS=y并注意 Capabilities 限制。
手动生成最小隔离环境:从 unshare 到 chroot
不用 Docker,仅靠 shell 工具就能搭出一个带 PID、Mount、UTS、IPC、User 隔离的轻量环境。以下是可直接运行的实验步骤(建议在干净的测试机或 VM 中操作):
- 创建专用工作目录:
mkdir -p ~/ns-root/{proc,dev,sys,etc,bin} - 复制基础命令(如 busybox)到
~/ns-root/bin/,确保静态链接或带依赖;挂载必要伪文件系统:mount -t proc proc ~/ns-root/proc、mount -t sysfs sysfs ~/ns-root/sys、mount -o bind /dev ~/ns-root/dev - 启用 User Namespace 映射:echo "100000:1000:65536" > /etc/subuid && echo "100000:1000:65536" > /etc/subgid
- 一次性启动隔离 shell:
unshare --user --pid --mount --uts --ipc --fork --root=~/ns-root --setgroups=deny --map-root-user /bin/bash - 进入后立即执行
mount -t proc proc /proc(因 mount ns 隔离,需重新挂载),再运行hostname container-a和ps aux,观察 PID 从 1 开始、主机名已变、看不到宿主机进程。
Namespace 组合使用的典型陷阱
多个 Namespace 联合使用时,行为并不总是直觉所想,几个高频踩坑点需特别注意:
-
Mount Namespace 不自动继承挂载传播属性:默认是
shared,子空间的挂载会传播回父空间。实验中务必加mount --make-rprivate /或创建时指定--mount-proc,否则umount /proc可能意外卸载宿主机 proc。 -
PID Namespace 与信号传递受限:子空间中 kill -1(SIGHUP)无法终止父空间进程;同样,父空间用
kill -9杀子空间 PID=1 进程会失败,必须先进入其 PID ns 再操作。 -
User Namespace + Capabilities 需显式授权:即使 UID 映射为 0,新 namespace 默认没有
CAP_SYS_ADMIN,所以不能直接 mount 或 sethostname,需在 unshare 时加--cap-add=SYS_ADMIN(若内核支持)或提前用capsh授权。 - Network Namespace 未激活时无法访问外网:新建 netns 默认只有 lo 接口,必须手动添加 veth 对并配置 IP、启用转发、设置 iptables NAT,否则 ping 8.8.8.8 必然超时。
如何验证当前进程处于哪些 Namespace 中
每个进程在 /proc/[pid]/ns/ 下有符号链接,指向对应 Namespace 的 inode。通过比对 inode 可判断是否同属一个空间:
- 查看本 shell 的所有 Namespace:
ls -l /proc/$$/ns/,输出类似net -> net:[4026532000] - 对比两个进程是否共享网络空间:
readlink /proc/1234/ns/net与readlink /proc/5678/ns/net,若 inode 相同(数字一致),说明它们在同一个 netns - 用
nsenter进入指定 Namespace 调试:nsenter -t 1234 -n -p -u -i -m /bin/bash(依次进入 net/pid/uts/user/mnt) - 检查 User Namespace 映射:
cat /proc/1234/status | grep -E "Uid|Gid|NSpid",结合/proc/1234/uid_map查看 UID 映射规则










