容器技术已经成为现代云计算和微服务架构的基石,而 Linux 内核提供的 namespace 和 cgroup 正是容器实现资源隔离与限制的两大核心机制。面试中,候选人是否真正理解这两者,往往能区分出“会用 Docker”和“懂容器原理”的工程师。本文将以面试题的形式,深入剖析 namespace 与 cgroup 如何协同支撑容器隔离。
一、面试题:请简述 namespace 和 cgroup 在容器中的作用与区别
这是一道高频面试题,看似简单,但能完整回答的人并不多。标准答案可以概括为:
- namespace 负责视图隔离,让容器内的进程只能看到属于自己的系统资源(如进程号、网络接口、文件系统挂载点等)。
- cgroup 负责资源限制,控制容器能使用多少 CPU、内存、磁盘 I/O 等物理资源。
- 两者一个管“看得见什么”,一个管“用得了多少”,共同构成容器的隔离基础。
下面分别展开。
二、namespace:容器“看不见”别人的秘密
1. 什么是 namespace
Namespace 是 Linux 内核的一项特性,它将对全局系统资源的视图进行封装,使得每个 namespace 内的进程都认为自己拥有独立的全局资源。换句话说,namespace 让进程“以为”自己是系统中唯一的存在。
2. 常见的 namespace 类型
Linux 目前实现了多种 namespace,容器常用的有:
- PID namespace:进程号隔离。容器内的第一个进程 PID 为 1,它看不到宿主机或其他容器的进程。
- Mount namespace:文件系统挂载点隔离。容器拥有独立的根文件系统视图。
- Network namespace:网络隔离。每个容器有独立的网卡、IP、路由表、端口空间。
- UTS namespace:主机名与域名隔离。容器可以有自己的 hostname。
- IPC namespace:进程间通信隔离。信号量、消息队列等相互独立。
- User namespace:用户和用户组 ID 隔离。容器内 root 可以映射为宿主机的普通用户,提升安全性。
- Cgroup namespace:cgroup 视图隔离,让容器内看到的 cgroup 层级从自己的根开始。
3. 面试追问:如何验证 namespace 隔离
面试官常会追问:“你怎么证明两个进程在不同 namespace?” 可以回答:
- 使用
ls -l /proc/<pid>/ns/查看某进程所属的各 namespace 的 inode 号。 - 若两个进程的同一类型 namespace inode 号相同,则它们共享该 namespace;不同则隔离。
- 使用
unshare或nsenter命令手动创建或进入 namespace 进行验证。
例如:
# 查看 PID 为 1234 的进程的 namespace
ls -l /proc/1234/ns/
# 手动创建一个新的 PID、Mount、Network namespace 并运行 bash
unshare --pid --mount --net --fork --mount-proc bash
三、cgroup:容器“用不了太多”的保障
1. 什么是 cgroup
Cgroup(control group)是 Linux 内核用于限制、记录和隔离进程组所使用物理资源(CPU、内存、I/O 等)的机制。它按层级组织,一个 cgroup 可以包含多个进程,也可以有子 cgroup。
2. cgroup 的核心能力
- 资源限制:如
memory.limit_in_bytes限制内存上限。 - 优先级分配:如 CPU 权重、blkio 权重。
- 资源统计:记录 CPU 使用时间、内存峰值等。
- 控制:冻结/恢复进程组。
3. cgroup v1 与 v2
面试中常被问到版本差异:
- cgroup v1:每个资源控制器(cpu、memory、blkio 等)有独立的层级树,管理复杂,且存在一致性缺陷。
- cgroup v2:统一层级,所有控制器挂载在同一棵树下,支持更精细的资源分配和压力通知(PSI),是现代发行版和容器运行时的默认选择。
4. 面试追问:如何为容器设置内存限制
以 Docker 为例,底层就是通过 cgroup 实现:
docker run -it --memory="512m" --cpus="1.5" ubuntu bash
该命令会在 cgroup 中创建对应限制:内存不超过 512MB,CPU 不超过 1.5 核。若进程试图申请超过限制的内存,会被 OOM killer 终止。
四、namespace 与 cgroup 如何协同工作
容器运行时(如 runc、containerd)创建容器的典型流程如下:
- 创建 cgroup:为即将启动的容器进程组创建 cgroup,写入 CPU、内存等限制值。
- 创建 namespace:调用
clone()或unshare(),传入CLONE_NEWPID、CLONE_NEWNET等标志,为新进程创建新的 namespace。 - 将进程加入 cgroup:把新创建的进程 PID 写入 cgroup 的
cgroup.procs文件。 - 执行容器进程:在隔离的 namespace 中启动应用进程,同时受 cgroup 资源约束。
用一个比喻总结:namespace 是给容器建了一间间独立的房间,cgroup 是给每个房间装了电表和水表。房间之间看不见彼此,用电用水也各有上限。
五、常见面试陷阱与加分回答
- 陷阱一:“容器是轻量级虚拟机。” —— 错。容器与宿主机共享内核,只是通过 namespace 和 cgroup 实现了隔离,并非虚拟化硬件。
- 陷阱二:“namespace 能限制 CPU。” —— 错。namespace 只做视图隔离,资源限制必须靠 cgroup。
- 加分回答:提到 user namespace 对安全的重要性,以及 cgroup v2 对 rootless 容器的支持。还可以提及 seccomp、capabilities 等辅助隔离机制,表明知识体系完整。
六、总结
| 机制 | 作用 | 隔离维度 | 典型命令/文件 |
|---|---|---|---|
| namespace | 视图隔离 | PID、网络、挂载、UTS、IPC、User | unshare、/proc/pid/ns/ |
| cgroup | 资源限制 | CPU、内存、I/O、进程数 | --memory、/sys/fs/cgroup/ |
理解 namespace 与 cgroup 的分工与协作,是掌握容器底层原理的关键。面试中若能清晰阐述“一个管隔离,一个管限额”,并辅以具体命令和内核机制,定能让面试官眼前一亮。
未经允许不得转载:任鹏个人博客 » Linux 面试题:namespace 与 cgroup 如何支撑容器隔离

