Linux命名空间深度解析
一、核心命名空间类型对比
命名空间类型 | 内核版本 | 隔离对象 | 关键系统调用 | 典型应用场景 |
---|---|---|---|---|
Mount | 2.4.19 | 文件系统挂载点 | clone(), unshare() | 容器文件系统隔离 |
PID | 2.6.24 | 进程ID空间 | clone(), unshare() | 容器进程树视图 |
Network | 2.6.29 | 网络设备/协议栈 | clone(), setns() | 容器独立网络配置 |
IPC | 2.6.19 | 进程间通信资源 | clone(), unshare() | 共享内存隔离 |
UTS | 2.6.19 | 主机名和域名 | clone(), sethostname() | 容器主机名自定义 |
User | 3.8 | 用户和组ID映射 | clone(), unshare() | 非root用户容器化 |
Cgroup | 4.6 | cgroup根目录视图 | clone(), unshare() | cgroup资源控制隔离 |
(注:Cgroup为扩展补充)
二、详细工作机制
1. Mount Namespace (CLONE_NEWNS)
作用原理:
- 维护独立的挂载点树结构(struct mount_namespace)
- 通过
/proc/<pid>/mountinfo
查看不同命名空间的挂载信息 - 采用"挂载传播"机制控制挂载事件传播:
mount --make-private /path # 默认模式
mount --make-slave /path
mount --make-shared /path
实现差异:
唯一在2.4内核就存在的命名空间类型
需要配合pivot_root或chroot实现完整文件系统隔离
2. PID Namespace (CLONE_NEWPID)
Host PIDNS(init=1)
└── Container1 PIDNS(init=100)
└── Nested Container(init=1)
- 通过/proc//status查看NsPID字段
- 必须配合挂载新的procfs:
mount -t proc proc /proc
特殊限制:
-
父命名空间可以看到子命名空间的所有进程
-
终止命名空间需要杀死所有内部进程
3. Network Namespace (CLONE_NEWNET)
网络栈隔离:
# 创建veth pair连接不同命名空间
ip link add veth0 type veth peer name veth1
ip link set veth1 netns newns
典型配置流程:
- 创建虚拟网卡(veth/vlan)
- 分配独立IP地址
- 设置路由规则
- 配置iptables规则
4. User Namespace (CLONE_NEWUSER)
UID映射机制:
Host UID:
0 1 2 ... 100000 100001 ...
| | | | |
└───┴───┴───┐ └───┬───┘
Container UID: 0 1
配置文件:
# /etc/subuid
testuser:100000:65536
能力限制:
-
即使映射为root,仍然受CAP_SYS_ADMIN等能力限制
-
需要配合其他命名空间使用才有价值
三、关键技术实现
1. 内核数据结构
struct task_struct {
struct nsproxy *nsproxy;
};
struct nsproxy {
atomic_t count;
struct uts_namespace *uts_ns;
struct ipc_namespace *ipc_ns;
struct mnt_namespace *mnt_ns;
struct pid_namespace *pid_ns;
struct net *net_ns;
};
2. 系统调用接口
- clone(): 创建新进程时指定命名空间
clone(child_func, stack, CLONE_NEWNS | CLONE_NEWPID, arg);
- unshare(): 将当前进程移出原有命名空间
unshare --pid --fork bash
- setns(): 加入已存在的命名空间
int fd = open("/proc/<pid>/ns/pid", O_RDONLY);
setns(fd, CLONE_NEWPID);
3. 持久化机制
通过绑定挂载保存命名空间引用:
# 查看所有命名空间inode
ls -l /proc/$$/ns
# 保持网络命名空间存活
touch /var/run/netns/myns
mount --bind /proc/$$/ns/net /var/run/netns/myns
四、组合使用案例
Docker容器典型配置:
$ docker run -it ubuntu
└── 启用命名空间:
Mount, PID, Network, IPC, UTS, User
└── 未隔离命名空间:
Cgroup (需额外配置)
通过lsns命令查看:
$ lsns -p <pid>
NS TYPE NPROCS PID USER COMMAND
4026531835 pid 115 1 root /sbin/init
4026532690 mnt 1 1234 root bash
4026532691 uts 1 1234 root bash