青蛙小白
博客 / 2025/11

查看Linux系统cgroup的版本

2025/11/11 · — 字 · 阅读约 — 分钟 ·
目录

最近Docker Engine v29.0.0 和 containerd 2.2.0 均宣布 cgroup v1 is deprecated,支持将持续到 2029 年 5 月,但建议尽快迁移到 cgroup v2。

对于运维团队来说,现在就是规划迁移的最佳时机。

什么是 cgroup

cgroup (Control Groups) 是 Linux 内核提供的一种资源管理机制,用于限制、记录和隔离进程组使用的物理资源。它是容器技术的核心基础之一,Docker、Kubernetes 等容器平台都依赖 cgroup 来实现资源隔离和限制。

核心功能

cgroup 提供四大类功能:

  • 资源限制 (Resource Limiting): 限制进程组可以使用的资源量,比如 CPU、内存的上限
  • 优先级分配 (Prioritization): 控制进程组的资源分配优先级,确保关键服务获得足够资源
  • 资源统计 (Accounting): 统计进程组使用的资源量,用于计费、监控或性能分析
  • 进程控制 (Control): 可以冻结进程组或重启进程组,实现批量管理

可控制的资源类型

cgroup 可以精细控制多种系统资源:

  • CPU: 限制 CPU 使用份额、绑定特定 CPU 核心
  • 内存: 限制内存使用上限、控制 swap 使用
  • 网络: 控制网络流量和优先级
  • 块设备 I/O: 限制磁盘读写操作的速率
  • 设备访问: 控制对设备文件的访问权限
  • 进程数量: 限制进程组可以创建的进程数量

这些能力使得 cgroup 成为容器技术、系统资源管理的关键组件。systemd 也使用 cgroup 来管理系统服务的资源。

为什么 Docker 和 containerd 要弃用 cgroup v1

Docker Engine v29.0.0 和 containerd 2.2.0 的release note中都将 cgroup v1 标记为弃用状态,这个决定背后有几个重要原因:

1. 技术架构的演进

cgroup v2 采用了全新的统一层级架构,相比 v1 的混合层级模型有显著优势:

  • 更简单的管理模型: 单一控制树替代多个独立的层级树
  • 更好的性能: 内核级别的优化,减少了资源管理开销
  • 更一致的行为: 强制进程在所有资源控制器中的位置一致

2. Linux 内核社区的推荐

Linux 内核社区已经将重心转移到 cgroup v2 的开发和维护上。cgroup v1 虽然仍在维护,但新功能主要在 v2 中实现。

3. 简化代码库维护

同时维护两套 cgroup 接口增加了代码库的复杂度。通过弃用 v1, 可以减少技术债务,更专注于新特性开发。

4. 行业标准化趋势

现代 Linux 发行版正在逐步默认启用 cgroup v2:

  • Ubuntu 22.04 LTS 及以上版本
  • Fedora 31 及以上版本
  • RHEL/CentOS 9 及以上版本
  • Debian 11 及以上版本

虽然支持会持续到 2029 年 5 月,但这给了企业用户充足的迁移时间。对于新项目, 可直接使用 cgroup v2。

检查系统的 cgroup 版本

在规划迁移之前,首先需要确认系统当前使用的 cgroup 版本。下面介绍几种常用的检查方法。

方法 1: 使用 stat 命令

这是最直接的检查方法:

stat -fc %T /sys/fs/cgroup/

输出解读:

  • cgroup2fs - 系统使用 cgroup v2 (统一层级)
  • tmpfs - 系统使用 cgroup v1 (混合层级)

这个命令通过检查 /sys/fs/cgroup/ 的文件系统类型来判断。cgroup v2 使用专门的 cgroup2fs 文件系统,而 v1 则挂载为 tmpfs

方法 2: 通过 Docker 检查

如果使用的是 Docker,可以直接查询:

docker info | grep -i cgroup

示例输出:

Cgroup Driver: systemd
Cgroup Version: 2

这个方法不仅显示版本,还能看到 Docker 使用的 cgroup 驱动 (driver)。常见的驱动有 systemdcgroupfs

方法 3: 检查内核挂载点

通过查看挂载信息可以更详细地了解 cgroup 配置:

mount | grep cgroup

cgroup v2 的典型输出:

cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime,nsdelegate,memory_recursiveprot)

只有一个挂载点,所有资源控制器都在统一的 cgroup2 文件系统中。

cgroup v1 的典型输出:

tmpfs on /sys/fs/cgroup type tmpfs (rw,nosuid,nodev,noexec,mode=755)
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,name=systemd)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
...

可以看到多个挂载点,每个资源控制器 (cpu、memory、blkio 等) 都有独立的层级树。

方法 4: 检查发行版版本

不同的 Linux 发行版在不同版本开始默认使用 cgroup v2:

cat /etc/os-release

默认使用 cgroup v2 的发行版:

发行版起始版本
Ubuntu22.04 LTS+
Fedora31+
RHEL/CentOS9+
Debian11+
Arch Linux滚动更新

如果系统版本在此列表中,很可能已经在使用 cgroup v2。但最好还是通过前面的方法明确确认。

统一层级 vs 混合层级

理解这两种架构的区别,是掌握 cgroup 版本差异的关键。

统一层级 (Unified Hierarchy) - cgroup v2

cgroup v2 使用单一的统一层级树:

  • 单一控制树: 所有的资源控制器 (CPU、内存、IO 等) 都在同一个层级树中管理
  • 一致的结构: 进程在所有资源控制器中的位置是相同的
  • 简化管理: 只需要在一个地方管理进程的资源限制

目录结构示例:

/sys/fs/cgroup/
├── user.slice/
│   └── user-1000.slice/
│       └── session-1.scope/
│           ├── cpu.max          # CPU 控制
│           ├── memory.max       # 内存控制
│           └── io.max           # IO 控制
└── system.slice/
    └── docker.service/
        ├── cpu.max
        ├── memory.max
        └── io.max

在这个结构中,每个 cgroup 都包含所有资源控制器的配置文件。想要限制 docker.service 的资源,只需要在一个目录下设置相应的参数。

混合层级 (Hybrid Hierarchy) - cgroup v1

cgroup v1 使用多个独立的层级树:

  • 多个控制树: 每个资源控制器 (CPU、内存、IO 等) 都有自己独立的层级树
  • 独立管理: 同一个进程在不同资源控制器中可能处于不同的层级位置
  • 复杂性高: 需要在多个地方分别配置和管理

目录结构示例:

/sys/fs/cgroup/
├── cpu/                    # CPU 控制器的独立树
│   ├── docker/
│   └── user.slice/
├── memory/                 # 内存控制器的独立树
│   ├── docker/
│   └── system.slice/
├── blkio/                  # IO 控制器的独立树
│   ├── docker/
│   └── user.slice/
└── cpuacct/               # CPU 统计的独立树
    ├── docker/
    └── system.slice/

在 v1 中,要限制 docker 容器的资源,需要分别在 cpu/docker/memory/docker/blkio/docker/ 等多个目录下设置。

迁移到 cgroup v2

如果还在使用 cgroup v1,并且计划迁移到 v2,下面是一些实用建议。

迁移前的准备

1. 评估兼容性

检查关键应用和工具是否支持 cgroup v2:

  • 容器运行时: Docker 20.10+、containerd 1.4+、Podman 2.0+ 都支持 v2
  • 编排系统: Kubernetes 1.25+ 推荐使用 v2
  • 监控工具: 确认 Prometheus、cAdvisor 等工具版本兼容
  • 自定义脚本: 审查直接操作 cgroup 的脚本

检查系统兼容性:

除了应用兼容性,还需要确认系统组件版本满足要求。

最低内核版本要求:

# 检查内核版本
uname -r

# cgroup v2 要求:
# - 最低: Linux 4.15
# - 推荐: Linux 5.2+

如果内核版本低于 4.15,必须先升级操作系统。内核 5.2 以上版本包含了完整的 cgroup v2 freezer 支持,在生产环境中更稳定。

systemd 版本要求:

# 检查 systemd 版本
systemd --version

# 推荐: systemd 244+

systemd 是现代 Linux 发行版的核心组件,与 cgroup 紧密集成。版本 244 以下的 systemd 在 cpuset 控制器的委托功能上存在限制,可能影响容器的 CPU 亲和性配置。

2. 查阅容器运行时的迁移文档

对于 Docker:

Docker 20.10+ 原生支持 cgroup v2,在检测到系统使用 cgroup v2 时会自动切换到 systemd cgroup 驱动。需要确保配置文件 /etc/docker/daemon.json 中设置了正确的驱动。详细内容可参考 Docker 官方文档

对于 containerd:

containerd 1.4+ 支持 cgroup v2,需要在配置文件 /etc/containerd/config.toml 中显式启用 systemd cgroup 驱动。在 [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] 部分设置 SystemdCgroup = true。更多配置细节见 containerd cgroups v2 文档

对于 Kubernetes:

Kubernetes 1.25+ 正式支持 cgroup v2 (GA)。kubelet 在检测到 cgroup v2 系统时会自动适配,但需要确保 kubelet 和容器运行时都使用 systemd cgroup 驱动。节点迁移时需要逐个替换。完整迁移指南参考 Kubernetes cgroup v2 文档

迁移策略建议

在非生产环境先进行充分测试,验证应用行为和性能指标。对于生产环境,建议采用滚动升级策略,逐步迁移节点,并保持回滚能力。

总结

cgroup 作为容器技术的基础,正在经历从 v1 到 v2 的重要演进。虽然 Docker Engine v29.0.0 和 containerd 2.2.0 将 cgroup v1 的支持延续到 2029 年 5 月,但现在就是开始规划迁移的最佳时机。

参考

评论