Linux内核 命名空间机制
Linux Namespace 是内核提供的轻量级资源隔离机制核心是让不同进程组看到独立的系统资源视图是容器Docker、K8s的底层基石。它隔离的是进程对资源的可见性而非物理资源本身因此比虚拟机更轻量化本质为全局系统资源PID、网络、挂载等划分独立作用域进程只能访问所属命名空间内的资源对其他空间不可见。内核实现每个进程通过task_struct中的nsproxy指针关联一组命名空间实例内核在系统调用与资源访问时按当前进程的命名空间做过滤与映射。生命周期命名空间由引用计数管理最后一个进程退出时自动销毁子进程默认继承父进程的所有命名空间。内核核心数据结构1. struct nsproxy命名空间代理所有命名空间的统一入口每个进程的task_struct持有一个nsproxy指针指向当前所属的命名空间集合struct nsproxy { atomic_t count; // 引用计数 struct uts_namespace *uts_ns; // UTS命名空间 struct ipc_namespace *ipc_ns; // IPC命名空间 struct mnt_namespace *mnt_ns; // 挂载命名空间 struct pid_namespace *pid_ns_for_children; // PID命名空间子进程用 struct net *net_ns; // 网络命名空间 struct cgroup_namespace *cgroup_ns; // Cgroup命名空间 struct user_namespace *user_ns; // 用户命名空间基础 struct time_namespace *time_ns; // 时间命名空间 };2. 各类型命名空间结构体每种隔离资源对应独立内核结构维护该空间的资源状态与映射PIDstruct pid_namespace维护 PID 分配、层级、init 进程Mountstruct mnt_namespace维护独立挂载树Netstruct net独立网络栈、设备、路由Userstruct user_namespaceUID/GID 映射表IPCstruct ipc_namespace独立 System V IPC 对象UTSstruct uts_namespace独立 hostname/domainname关键机制详解1. PID 命名空间分层架构每个空间有独立 PID 号段首个进程为PID 1init负责回收僵尸进程。嵌套子空间进程在父空间有全局 PID如子空间 PID1 → 父空间 PID1234 → 根空间 PID5678/proc/[pid]/status中NSpid字段可见。销毁init 进程退出时内核终止该空间所有进程。让一组进程看到独立的进程号空间容器里看到 PID 从 1 开始宿主机看到容器进程是正常全局 PID容器内部看不见宿主机其他进程一句话给进程套一层 PID 映射表。内核基本结构每个 PID namespace 在内核里是一个独立结构struct pid_namespace { struct kref kref; // 引用计数 struct pidmap pidmap[PIDMAP_ENTRIES];// PID 分配位图 int last_pid; // 上次分配的 PID struct task_struct *child_reaper; // 本空间的 init 进程PID 1 struct pid_namespace *parent; // 父 namespace // ... };关键点每个 namespace 有自己的 PID 分配器有层级关系子 → 父 → 根 namespace有固定的init 进程PID 1PID分配与存储内核并不只存一个 PID而是给每个进程在所有祖先 namespace 中各分配一个 PID。结构struct pid保存一个数字而struct upid保存每个层级的编号struct pid { rwlock_t lock; unsigned int level; // 命名空间深度 struct upid numbers[]; // 每个 ns 对应的 PID };例如根 nsPID 1234父 nsPID 100子 nsPID 1内核会完整保存整条链。可见性规则最重要子 namespace 完全看不见父 / 兄弟父 namespace 可以看见子看到的 PID 是当前 ns 对应的编号这就是为什么容器里 ps 只能看到自己宿主机 ps 能看到容器。嵌套层级原理PID namespace 是树状结构根 NS (level 0) ├─ 容器A NS (level 1) │ └─ 容器A内嵌套容器 (level 2) └─ 容器B NS (level 1)一个进程在每一层都有一个 PID/proc/[pid]/status里的NSpid字段会列出所有层级 PID示例NSpid: 14528 42 1表示根 ns14528父 ns42本 ns1内核关键逻辑内核在遍历进程、分配 PID、发送信号时都会获取当前进程的task_struct-nsproxy-pid_ns用这个 ns 去查找 / 分配 / 展示 PID本质就是所有涉及 PID 的内核行为都以当前进程所在 PID namespace 为基准。2. User 命名空间权限隔离核心User NamespaceCLONE_NEWUSER是所有容器隔离的权限基石是 Linux 安全容器的核心实现UID/GID 隔离、权限映射、Capability 隔离、安全边界隔离让容器内root ≠ 宿主机 root。是其他命名空间的基础允许非特权用户创建命名空间。通过/proc/[pid]/uid_map/gid_map做内外 UID 映射如0 1000 1表示容器内 root (0) 映射到宿主机 uid1000。权限进程在空间内的能力capabilities受限于映射后的真实权限。核心作用独立的UID / GID 编号空间内外 ID 映射容器内0(root)→ 宿主机普通非特权用户Capability 能力隔离容器内即使是 root也只拥有受限权限允许普通非特权用户创建其他所有命名空间mnt/pid/net/ipc 等隔离安全 KEY、LSM、资源限额、用户组体系关键结论没有 User NS容器就是弱隔离容器 root 极易提权击穿宿主机。进程关联task_struct └→ nsproxy └→ user_ns // struct user_namespace每个进程都绑定一个user_namespace是权限检查的最高上下文。关键结构体struct user_namespace { struct uid_gid_map uid_map; // UID 映射表 struct uid_gid_map gid_map; // GID 映射表 struct user_namespace *parent;// 父 user ns树状层级 struct cap_set inheritable; // 权限能力集 // 安全、LSM、proc、cgroup 关联 bool ns_capable_setid; // ... };映射单元struct uid_gid_map { u32 nr_extents; struct uid_gid_extent extent[UID_GID_MAP_MAX_EXTENTS]; }; // 一段映射规则 struct uid_gid_extent { u32 first; // 容器内起始ID u32 lower; // 宿主机起始ID u32 count; // 映射数量 };UID/GID 映射机制核心1. 双向映射From 容器 → 宿主机内核做ns uid → 全局 uid转换读写文件、权限检查、磁盘持久化用宿主机真实 IDFrom 宿主机 → 容器全局 ID 反向翻译为容器内 IDps、ls -n展示容器内编号2. 映射文件/proc 接口/proc/[pid]/uid_map /proc/[pid]/gid_map标准容器映射示例# uid_map 0 1000 65536含义容器内 UID065535映射到宿主机 UID1000100065535 容器里的 root (0)在宿主机上就是普通用户 1000。3. 无映射 nobody如果不配置 map容器内所有未映射 ID 都会被内核强制映射为65534(nobody)天然防越权。Capability 权限隔离Linux 不再靠传统 root/sudo而是拆分细粒度 Capability。User NS 会裁剪、隔离 Cap新 user ns 内的进程默认不继承父命名空间的高权限 Cap只被授予一组受限安全 Cap如 CAP_CHOWN、CAP_SETUID 等容器内 root在当前 user ns 内拥有完整 Cap但对父 user ns / 宿主机资源无任何特权举例容器内执行mount只能在自己的 mnt ns 里生效无法挂载宿主机真实磁盘、无法修改宿主机文件权限。层级模型树状User NS 天然层级化根 User NS宿主机顶层真实权限 ├─ 容器A User NS子级权限受限 │ └─ 嵌套容器 User NS孙子级 └─ 容器B User NS权限规则子 ns 不能修改父 ns 资源父 ns 可以管控、限制子 ns 权限权限检查逐级向上校验3. Network 命名空间隔离完整网络协议栈是容器网络、虚拟化网络、多租户网络隔离的底座每个 NetNS 拥有独立网卡、IP、路由、ARP、iptables、TCP/UDP 栈、端口、socket默认完全隔离互不监听、互不路由、互不冲突底层内核协议栈代码全局共用只是网络资源实例隔离新空间默认仅含lo 回环接口DOWN 状态需手动启用与配置。跨空间通信用veth pair虚拟以太网对连接两个空间一端在宿主机、一端在容器空间。隔离范围全栈隔离网络设备lo、物理网卡、虚拟网卡veth、tap、macvlan、ipvlan三层网络IP 地址、路由表、网关、ARP、邻居表四层传输TCP/UDP/ICMP 独立端口空间不同 netns 可重复占用同一端口防火墙 / 转发独立 iptables、nftables、netfilter 规则网络配置/proc/sys/net内核参数隔离tcp_tw_reuse、ip_forward 等Socket 连接每个 ns 的 socket 完全隔离不能直接跨 ns 通信默认行为新建net ns只自动创建独立 lo 设备默认 DOWN无任何物理网卡、无路由、无防火墙规则必须手动启用 loip link set lo up挂载虚拟网卡、配置 IP / 路由端口隔离宿主机 80 端口 和 容器 80 端口 互不冲突跨 NetNS 通信核心方案1. veth pair容器默认一对虚拟以太网卡像一根网线两端一端留在宿主机 root netns一端移入容器 netns实现容器 ↔ 宿主机 二层互通2. macvlan / ipvlan让容器直接复用物理网卡独立 MAC/IP直连局域网3. 网桥 bridge宿主机创建虚拟网桥多个容器 veth 接入网桥实现容器之间互通4. SDN/OverlayVXLAN、Geneve跨主机容器网络5. 本地 UNIX 域套接字unix socket不受 netns 隔离可跨 ns 通信4. Mount 命名空间新空间复制父空间挂载树后续 mount/umount 仅影响当前空间。挂载传播支持shared/slave/private/unbindable控制挂载事件在父子空间的传播。隔离文件系统挂载视图核心每个 ns 拥有独立挂载树新的mount/umount仅作用于当前 ns不影响宿主机 / 其他容器是容器隔离根目录、OverlayFS、只读挂载、临时文件系统隔离的底层基础内核标识CLONE_NEWNS最早、最基础的命名空间。进程维度task_struct→nsproxy→mnt_nsstruct nsproxy { struct mnt_namespace *mnt_ns; // 当前进程所属挂载命名空间 // ...其他ns };挂载命名空间本体struct mnt_namespace { struct mount *root; // 该ns的根挂载节点 struct list_head list; // 所有挂载项链表 struct mount_event event; unsigned int mount_seq; // 挂载序列每次mount1 enum mnt_propagation_type propagation; // 挂载传播默认属性 // 引用计数、用户ns关联、生命周期 };关键挂载对象struct vfsmount文件系统挂载实例struct mount挂载点实体维护父子挂载层级、挂载传播标记全局不再只有一棵统一挂载树每个 mnt_ns 一棵独立挂载树挂载树复制机制Copy-on-Write 思想通过clone(CLONE_NEWNS)创建新挂载 ns 时复制父进程完整挂载树初始视图完全一致复制是浅拷贝底层文件系统、超级块、inode 全局共享后续当前 ns 内执行mount/umount/bind mount只会修改自己这棵树完全隔离。区别物理资源磁盘、块设备全局共享挂载视图、挂载点列表、目录覆盖关系完全隔离。视图隔离效果容器内挂载/tmp、/dev/shm、临时磁盘宿主机看不到宿主机挂载硬盘默认不会自动穿透到容器容器内umount /sys不会影响宿主机系统。、挂载传播Mount Propagation—— 重中之重Mount ns 不是完全隔绝内核提供挂载传播属性控制挂载事件跨 ns 传递是容器、systemd 关键机制。四种传播类型类型宏作用MS_PRIVATE私有完全隔离挂载变更不互通容器默认MS_SHARED共享挂载事件双向同步父子 ns 互相传递MS_SLAVE从属只能接收父 ns 挂载事件自身变更不向外扩散MS_UNBINDABLE不可绑定不允许 bind mount禁止跨目录挂载典型场景容器默认private容器内部挂载、卸载完全隔离是安全隔离基础。宿主机 /run/media 等shared/slaveU 盘插入、自动挂载能被所有需要的 ns 感知。bind 挂载、容器目录映射依赖传播属性控制是否泄露宿主机目录。修改传播属性命令# 设置目录为私有容器标准做法 mount --make-private /挂载层级 根目录隔离原理新 mnt ns 继承父的/根挂载容器通过pivot_root/chroot结合独立挂载树先在私有挂载 ns 内挂载 OverlayFS读写层 镜像只读层用pivot_root切换根目录替换为容器文件系统再挂载独立/proc /sys /dev实现完整环境隔离。关键区别chroot只是目录视图限制无法隔离挂载、无法隐藏宿主机挂载点Mount NS pivot_root真正隔离完整文件系统挂载拓扑。生命周期mnt_namespace基于引用计数管理当所有绑定该 ns 的进程全部退出、无文件句柄引用时内核自动销毁该挂载树销毁不会卸载全局真实文件系统仅销毁当前 ns 的挂载拓扑。Mount NS 与其他容器组件配合 User NS非特权用户也能创建私有挂载、绑定挂载提升容器安全性。 PID NS独立进程视图 独立 /proc 挂载彻底隔离进程信息。 Cgroup隔离视图 资源限制构成完整容器底座。OverlayFS Mount NS每层镜像只读挂载 容器私有读写层实现容器镜像分层。全局挂载树 与 NS 挂载树 关系1. 初始状态根命名空间init_ns系统启动后只有根 Mount NS全局只有一棵唯一挂载树所有进程默认共享这棵树所有/ /home /tmp /sys /proc都在这棵树上2. 创建新 Mount NSCLONE_NEWNSclone(CLONE_NEWNS) / unshare(CLONE_NEWNS)内核关键动作浅拷贝根 NS / 父 NS 的整棵挂载树复制所有mount节点的拓扑关系底层super_block、dentry、inode完全共享不复制数据生成一个全新mnt_namespace新进程 / 当前进程绑定到新 mnt_ns3. 隔离本质✅ 底层资源全局共享磁盘、inode、sb✅ 挂载对象多个 NS 可以引用同一个mount❌ 挂载操作隔离新 NS 内执行mount / umount / bind mount只修改当前 NS 自己的挂载树不影响父 NS、其他容器挂载树的「覆盖」机制关键Linux 挂载是覆盖式原目录存在原有 dentry 与内容在该目录执行 mount → 新文件系统覆盖该目录上层原目录内容被隐藏仅在卸载后恢复结合 NS容器内单独挂载/etc覆盖宿主机同目录完全不受影响因为二者挂载树拓扑独立挂载传播多 NS 挂载树的联动规则如果完全隔离U 盘自动挂载、容器挂载宿主机目录会失效内核引入挂载传播控制挂载事件是否跨 NS 同步。四种类型MS_PRIVATE 私有容器默认挂载树完全隔离双向不通容器安全基础。MS_SHARED 共享父子 NS 挂载树双向同步一方 mount另一方自动看到。MS_SLAVE 从属只能继承父 NS 挂载自身修改不会往外扩散。MS_UNBINDABLE禁止 bind 挂载防止目录穿透泄露。典型流程宿主机/media设为shared→ U 盘插入自动挂载到/media/usb→ 所有 shared/slave 的子 NS 自动看到该挂载→ 私有容器看不到隔离生效多 Mount NS 整体架构图示[根Mount NS 挂载树] 全局原始挂载拓扑 │ ├─ 复制生成 → [容器A mnt_ns 挂载树]私有 └─ 复制生成 → [容器B mnt_ns 挂载树]私有 底层super_block / inode / dentry 全局共用 上层每棵挂载树 挂载点、覆盖关系、卸载、新增挂载 完全独立内核关键执行逻辑用户访问文件当进程 open (/tmp/file)取当前进程 →nsproxy-mnt_ns以当前 NS 的挂载树为基准做路径解析逐级匹配挂载点应用挂载覆盖规则最终找到对应 super_block inode核心结论路径解析、挂载可见性全部绑定在当前进程的 Mount 命名空间上创建与管理的三大系统调用1. clone ()创建新进程 新命名空间创建子进程并指定新命名空间是容器启动的核心调用// 创建新UTSPID命名空间的子进程 pid clone(child_func, stack, CLONE_NEWUTS | CLONE_NEWPID | SIGCHLD, arg);2. unshare ()当前进程脱离旧空间创建新空间不创建新进程直接为当前进程切换到新命名空间unshare命令底层unshare(CLONE_NEWNET | CLONE_NEWNS); // 脱离当前网络与挂载空间3. setns ()加入已存在的命名空间通过命名空间文件描述符/proc/[pid]/ns/xxx将进程加入指定空间nsenter命令底层int fd open(/proc/1234/ns/net, O_RDONLY); setns(fd, CLONE_NEWNET); // 加入PID1234的网络空间
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2549959.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!