为什么 K8S 必须把 containerd 的 cgroup 驱动改成 systemd?

作者:互联网

2026-03-24

AI模型库

今天分享一个比较底层的原理: 为什么 Kubernetes 必须把 containerd 的 cgroup 驱动改成 systemd?

现在很多人在部署K8S集群 时都会执行这样一步:

containerd config default > /etc/containerd/config.toml
  • 1.

然后修改一行配置:将默认的false改为true

SystemdCgroup = true
  • 1.

但大多数教程只告诉你:必须改,不然会出问题。

却很少有人真正解释:为什么一定要改?

甚至很多集群 不改也能运行,但过一段时间就开始出现各种“玄学问题”,有经验的老手可能深有体会。

接下来就来聊聊为什么一定要改。

1. 资源管理核心:cgroup

Kubernetes 能做到:Pod 限制 CPU / Memory/资源隔离/OOM 控制/Pod 驱逐(Eviction)/HPA 自动扩缩容等

底层依赖的其实只有一个东西:Linux cgroup(Control Groups)。

简单理解:

  • cgroup 就是 Linux 用来控制进程资源的机制
  • cgroup可以用于限制 CPU/内存/ IO和统计资源

容器本质就是:

进程 + namespace + cgroup
  • 1.

所以:容器资源控制 = cgroup

2. Linux 里 cgroup 有两种管理方式

在 systemd 出现之前,Linux 的 cgroup 是这样管理的:

管理方式

说明

cgroupfs

内核直接挂载管理

systemd

systemd 接管 cgroup

在现代 Linux 系统中几乎全部由 systemd 接管 cgroup。

你可以执行:

mount | grep cgroup
  • 1.

如果看到类似:

cgroup2 on /sys/fs/cgroup type cgroup2
  • 1.

说明系统使用的是:cgroup v2(统一层级)。

而 systemd 就是这棵树的管理者。

3. containerd 默认不用 systemd

containerd 默认配置是:

SystemdCgroup = false
  • 1.

也就是说:containerd 不会通过 systemd 创建 cgroup,而是自己直接在/sys/fs/cgroup下面创建目录。

这就产生了一个非常严重的问题:系统有两个“管理者”。

4. 资源管理出现“两套体系”

这时系统会变成这样:

systemd
 └── kubelet
      └── Pod cgroup
  • 1.
  • 2.
  • 3.

而 containerd:

containerd
 └── 自己创建 container cgroup
  • 1.
  • 2.

于是:Pod 的 cgroup 和容器的 cgroup 不在同一体系。

这会导致 Kubernetes 的资源管理 完全失效。

5. 不修改会出现哪些问题?

很多生产环境遇到的“玄学问题”,其实都来自这里。

(1) Pod 明明设置了 limit,但机器内存还是被打爆

例如:

resources:
  limits:
    memory: 512Mi
  • 1.
  • 2.
  • 3.

但服务器内存仍然被打满。

原因是:containerd 创建的容器 cgroup 不受 kubelet 管控。

(2) 节点频繁 OOM

系统 OOM 时:

Out Of Memory Kill
  • 1.

但 Kubernetes 看不到这些信息。

原因是:systemd 统计不到 containerd 创建的 cgroup。

(3) metrics-server 监控数据异常

例如:

  • CPU 使用率不准
  • Memory 使用率异常

因为:

metrics-server -> kubelet -> systemd cgroup
  • 1.

但容器在:

containerd 自建 cgroup
  • 1.

数据来源不同。

(4) Pod 驱逐(Eviction)失效

Kubernetes 在内存不足时会驱逐 Pod:

Eviction Manager
  • 1.

但如果 container cgroup 不在 systemd 管理下:kubelet 根本找不到对应资源信息。

(5) kubelet 日志出现奇怪错误

例如:

failed to find cgroup
failed to update stats
cgroup driver mismatch
  • 1.
  • 2.
  • 3.

6. 为什么 Docker 时代很少遇到这个问题?

因为从 Docker 1.12 开始:

Docker 默认使用:

systemd cgroup driver
  • 1.

所以很多人过去没有踩过这个坑。

但 containerd 的默认配置仍然是:cgroupfs。

这就导致:Kubernetes + containerd 很容易踩坑。

7. Kubernetes 官方要求

Kubernetes 官方明确建议:kubelet 和 container runtime 必须使用相同的 cgroup driver。

并且在 systemd 系统上:推荐使用 systemd driver。

修改 SystemdCgroup = true 是,让 containerd 的 cgroup 归 systemd 管理。

否则 Kubernetes 的资源管理体系就会 失效一半。

读到这里,有没有那么一点理解。

相关标签:

AI 大模型 资讯