Linux 面试题:namespace 与 cgroup 如何支撑容器隔离

容器技术已经成为现代云计算和微服务架构的基石,而 Linux 内核提供的 namespacecgroup 正是容器实现资源隔离与限制的两大核心机制。面试中,候选人是否真正理解这两者,往往能区分出“会用 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;不同则隔离。
  • 使用 unsharensenter 命令手动创建或进入 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)创建容器的典型流程如下:

  1. 创建 cgroup:为即将启动的容器进程组创建 cgroup,写入 CPU、内存等限制值。
  2. 创建 namespace:调用 clone()unshare(),传入 CLONE_NEWPIDCLONE_NEWNET 等标志,为新进程创建新的 namespace。
  3. 将进程加入 cgroup:把新创建的进程 PID 写入 cgroup 的 cgroup.procs 文件。
  4. 执行容器进程:在隔离的 namespace 中启动应用进程,同时受 cgroup 资源约束。

用一个比喻总结:namespace 是给容器建了一间间独立的房间,cgroup 是给每个房间装了电表和水表。房间之间看不见彼此,用电用水也各有上限。

五、常见面试陷阱与加分回答

  • 陷阱一:“容器是轻量级虚拟机。” —— 错。容器与宿主机共享内核,只是通过 namespace 和 cgroup 实现了隔离,并非虚拟化硬件。
  • 陷阱二:“namespace 能限制 CPU。” —— 错。namespace 只做视图隔离,资源限制必须靠 cgroup。
  • 加分回答:提到 user namespace 对安全的重要性,以及 cgroup v2 对 rootless 容器的支持。还可以提及 seccompcapabilities 等辅助隔离机制,表明知识体系完整。

六、总结

机制 作用 隔离维度 典型命令/文件
namespace 视图隔离 PID、网络、挂载、UTS、IPC、User unshare/proc/pid/ns/
cgroup 资源限制 CPU、内存、I/O、进程数 --memory/sys/fs/cgroup/

理解 namespace 与 cgroup 的分工与协作,是掌握容器底层原理的关键。面试中若能清晰阐述“一个管隔离,一个管限额”,并辅以具体命令和内核机制,定能让面试官眼前一亮。

未经允许不得转载:任鹏个人博客 » Linux 面试题:namespace 与 cgroup 如何支撑容器隔离

赞 (0) 打赏

评论 0

取消
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏