容器技术基石

命名空间与 cgroup

底座认知 · 第 01 篇

容器的「隔离」与「限制」到底是如何实现的

目 录

一、容器的本质

二、命名空间:实现隔离

三、cgroup:实现限制

3.1 cgroup v1 与 v2

3.2 生产要点:cgroup v2 与容器运行时

四、容器如何组合使用它们

五、与 K8s 的衔接

5.1 内存限制与 OOMKilled

5.1.1 区分两种内存耗尽

5.1.2 与 QoS 等级的关系

5.1.3 排查与解决

一、容器的本质

容器并不是「一个更轻的虚拟机」。它的本质是:一个运行在宿主机上的普通进程,只是被操作系统施加了两类机制,从而呈现出「独立」的外观。

  1. 命名空间(Namespace):让进程「看不到」宿主机的其他资源,实现隔离
  2. cgroup:让进程「用不了」超过配额的系统资源,实现限制

二者相辅相成,共同构成了容器的基础。本篇逐个拆解它们的工作原理与生产意义。

二、命名空间:实现隔离

命名空间把全局系统资源「各切一份」给不同进程组,使每个命名空间内的进程只看到属于自己的那一份,就像住进独立房间。

命名空间

隔离的资源

典型效果

PID

进程编号

容器内 PID 1 是应用进程,看不到宿主其他进程

Mount

挂载点

容器有自己的根文件系统

Network

网络栈

独立的网卡、IP、路由

UTS

主机名与域名

容器可有自己的 hostname

IPC

进程间通信

独立的信号量、消息队列

User

用户与 UID

容器内可映射非 root 权限

对运维最重要的是 PID、Mount、Network 三者:它们分别决定了进程隔离、文件系统隔离和网络栈隔离,也是排障时最常涉及的层面。

三、cgroup:实现限制

cgroup 是 Linux 内核的资源控制器,用于对一组进程做 CPU、内存、磁盘 IO、网络带宽等资源的配额与统计。它决定了「容器最多能用多少资源」。

3.1 cgroup v1 与 v2

cgroup 有两个版本,结构差异显著。主流新系统(如 Rocky Linux 9、CentOS Stream、Ubuntu 22.04+)默认使用 v2。

对比维度

cgroup v1

cgroup v2

层次结构

每个子系统独立树

统一树(单层次)

控制器

CPU/内存等各有独立挂载点

统一在 /sys/fs/cgroup 下

线程控制

不支持(仅进程)

支持线程级细分

并发安全

较弱

原生原子写、更安全

代表系统

CentOS 7、Ubuntu 20.04

Rocky 9、Ubuntu 22.04+

3.2 生产要点:cgroup v2 与容器运行时

在 cgroup v2 系统上使用 containerd,必须把 runc 配置为使用 systemd cgroup 驱动,否则可能资源隔离失效。验证命令:

  1. 确认系统是 v2:cat /sys/fs/cgroup/cgroup.controllers
  2. 确认运行时 cgroup 驱动:crictl info | grep cgroupDriver,应输出 systemd

四、容器如何组合使用它们

当 runc 启动一个容器时,会依次创建所需的命名空间,把进程「关」进隔离环境,再将其放入 cgroup 树中分配资源限额。一个典型流程是:

创建命名空间 → 挂载 rootfs → 设置 cgroup 限额 → 执行容器入口进程

这意味着:隔离让容器「像独立机器」,限制让容器「吃不下超出的资源」,二者结合才形成可安全共存的资源环境。

五、与 K8s 的衔接

K8s 并不直接操作这些内核机制,而是通过容器运行时(containerd)间接使用。但理解它们对排查有直接价值:

  1. Pod 中容器「看不到」宿主其他进程 → 正常现象,源于 PID 命名空间
  2. 容器被限制内存后 OOMKilled → 与 cgroup 内存限制有关
  3. kubelet 的资源 requests/limits 最终通过 cgroup 落地

5.1 内存限制与 OOMKilled

容器被限制内存后出现 OOMKilled,正是 cgroup 内存限制与内核 OOM 机制共同作用的结果。完整链路:容器内存使用量超过 cgroup 内存上限 → cgroup 无法再分配内存 → 内核 OOM Killer 介入,把超限容器进程杀掉(SIGKILL)→ K8s 检测到容器退出,状态记为 OOMKilled。

触发条件是容器的 limits.memory:K8s 会把它落到容器的 cgroup 上。当容器实际内存超过上限即触发 OOM Killer,kubectl get pod 中 STATUS 显示 OOMKilled,LAST STATE 的 Exit Code 为 137(等于 128 + 9,即被 SIGKILL 信号杀死)。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐