namespace怎么进行资源隔离的
梓涵,既然你已经在深入研究 K8s 的启动流程和 Pause 容器,那么 Namespace(命名空间) 就是你必须攻克的底层堡垒。
简单来说,Namespace 是 Linux 内核用来隔离系统资源的一种机制。它就像是在一台物理服务器内部,通过“障眼法”划分出了多个互不干扰的虚拟世界。
以下是它的底层实现与资源隔离的具体逻辑:
1. Namespace 的本质:内核的“障眼法”
在 Linux 内核中,Namespace 并不是一种物理实体的划分,而是一种对全局系统资源的封装。
当一个进程被放入某个 Namespace 后,它能看到的资源(如 IP 地址、进程 ID 等)就会被限制在那个 Namespace 的范围内。它以为自己拥有整个系统,但实际上它只是“井底之蛙”。
2. 六大核心 Namespace 与隔离维度
在 K8s 和 Docker 中,主要利用了以下 6 种 Namespace 来实现全方位的隔离:
| Namespace 类型 | 隔离的资源 | 隔离效果 |
|---|---|---|
| UTS (Unix Timesharing System) | 主机名与域名 | 容器可以有自己的 Hostname,不会修改宿主机的名字。 |
| IPC (Inter-Process Communication) | 信号量、消息队列、共享内存 | 防止不同 Pod 之间的进程通过内存直接通信,保证安全。 |
| PID (Process ID) | 进程编号 | 容器内的 init 进程 ID 是 1。在容器里执行 ps<br>看不到宿主机的进程。 |
| Network (Net) | 网络设备、协议栈、端口 | 这是你最关注的。 容器拥有独立的 IP、网卡和 Iptables 规则。 |
| Mount (Mnt) | 挂载点、文件系统 | 容器只能看到自己的目录树(rootfs),看不到宿主机的磁盘文件。 |
| User | 用户与用户组 ID | 容器内的 root 用户(ID 0)在宿主机上其实只是一个普通用户。 |
3. 资源隔离是怎么实现的?(底层原理)
底层主要通过两个关键的系统调用(System Call)来完成:
A. clone() —— 创建时隔离
当你启动一个容器进程时,Docker/K8s 底层会调用 clone()。
- 做法:在调用时传入类似
CLONE_NEWNET或CLONE_NEWPID的参数。 - 效果:操作系统会为这个新进程创建一个全新的 Namespace。
B. setns() —— 运行时加入
这就是 Pause 容器共享网络 的核心。
- 做法:如果容器 B 想要加入容器 A 的网络,它会通过
setns()系统调用,将其网络 Namespace 指向容器 A 的 Namespace 文件描述符。 - 效果:两个进程“看”到了同一张虚拟网卡。
4. 💡 梓涵的“面试进阶”:Namespace 的局限性
面试官可能会问:“既然 Namespace 隔离了资源,那为什么容器不叫虚拟机?”
你的满分回答:
“因为 Namespace 只能做到 ‘可见性’的隔离,它不能做到 ‘物理上’的隔离。
- 共享内核:所有容器共享同一个宿主机内核,如果某个容器利用内核漏洞发起攻击,整个宿主机都会沦陷。
- 资源抢占:Namespace 无法限制你用多少 CPU。如果不配合 cgroups,一个 Namespace 里的进程可能会耗光宿主机的 CPU,导致其他 Namespace 的进程卡死。
所以,在我的 ZH-Kinger 架构中,我始终坚持 ‘Namespace 隔离视角 + cgroups 隔离资源’ 的组合方案,这才是真正的容器隔离。”
5. 🛠️ 怎么在你的 Rocky Linux 里“捅破”这个隔离?
你想看看真相吗?在你的机器上试试这两个操作:
- 查看 Namespace 文件:
执行 ls -l /proc/$$/ns($$ 是当前 Shell 的 PID)。你会看到一系列 link 文件,每一行就是一个 Namespace 的 ID。
- 跨隔离操作:
使用 **nsenter** 工具。
“如果我想在宿主机上抓取某个 Pod 内部的数据包,我不需要进容器装 tcpdump,我直接执行 nsenter -t <容器PID> -n tcpdump。这相当于我这个‘上帝’强行闯入了容器的网络 Namespace。”
梓涵,理解了 Namespace,你就理解了容器的“虚”。而接下来要聊的 cgroups,则是容器的“实(限制)”。你想了解一下 cgroups 是如何精准限制 CPU 指令周期,从而防止某个 Pod 把你的宿主机跑宕机的吗?
