Linux中的Cgroup

cgroup(Control Groups) 是 Linux 内核中的一项重要功能,用于管理和限制系统资源的使用。它允许用户按照需求对 CPU、内存、I/O 等资源进行精细化的控制,从而为容器化技术(如 Docker 和 Kubernetes)提供了基础支持。

Linux 的 cgroup 有两个版本:cgroup v1cgroup v2。随着 Linux 内核的发展,cgroup v2 在功能和设计上对 v1 做了很多改进。本文将详细探讨 cgroup v1 和 v2 的区别,并提供技术细节和实际应用示例。


什么是 cgroup?

cgroup 是 Linux 内核的一项功能,用于:

  1. 资源限制:限制某些进程可以使用的资源量(如 CPU、内存等)。
  2. 资源优先级:为不同的进程分配不同的资源优先级。
  3. 资源计费:跟踪进程使用的资源量。
  4. 进程管理:将一组进程组织为一个组,并对其统一管理。

它的主要应用场景包括:

  • 容器技术(如 Docker、Kubernetes)。
  • 虚拟化技术。
  • 系统性能调优。

cgroup v1 和 v2 的区别

1.文件结构对比

cgroup v1 的文件结构

在 cgroup v1 中,每种资源(如 CPU、内存、I/O)都有独立的子系统,每个子系统都有自己的目录和控制文件。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/sys/fs/cgroup/
├── cpu/
│ ├── cpu.cfs_quota_us
│ ├── cpu.cfs_period_us
│ ├── tasks
│ └── ...
├── memory/
│ ├── memory.limit_in_bytes
│ ├── memory.usage_in_bytes
│ ├── tasks
│ └── ...
└── blkio/
├── blkio.throttle.read_bps_device
├── blkio.throttle.write_bps_device
├── tasks
└── ...
  • 每个子系统(如 cpumemory)管理自己的资源。
  • 配置文件分散在不同的目录中,容易导致配置冲突。

cgroup v2 的文件结构

在 cgroup v2 中,所有控制器共享一个统一的层次结构和文件系统:

1
2
3
4
5
6
7
8
/sys/fs/cgroup/
├── cgroup.controllers
├── cgroup.procs
├── cgroup.subtree_control
├── cpu.max
├── memory.max
├── io.max
└── ...
  • 统一的文件结构,所有资源控制参数(如 CPU、内存、I/O)都在同一目录下。
  • 减少了配置冲突,更加简洁和高效。

2. 资源控制参数对比

以下是 cgroup v1 和 v2 在资源控制方面的主要参数对比:

CPU 控制参数

功能 cgroup v1 参数 cgroup v2 参数
设置 CPU 时间配额 cpu.cfs_quota_us cpu.max
设置 CPU 时间周期 cpu.cfs_period_us cpu.max
设置 CPU 权重(优先级) cpu.shares cpu.weight
  • 在 cgroup v2 中,cpu.max 替代了 cpu.cfs_quota_uscpu.cfs_period_us,格式为 <quota> <period>
  • cpu.weight 替代了 cpu.shares,用于设置 CPU 权重。

内存控制参数

功能 cgroup v1 参数 cgroup v2 参数
设置内存上限 memory.limit_in_bytes memory.max
设置内存软限制 memory.soft_limit_in_bytes 不支持
内存使用量 memory.usage_in_bytes memory.current
  • cgroup v2 简化了内存控制,废弃了一些复杂的参数(如软限制)。

I/O 控制参数

功能 cgroup v1 参数 cgroup v2 参数
限制读写带宽 blkio.throttle.read_bps_device io.max
限制 IOPS blkio.throttle.write_iops_device io.max
  • cgroup v2 使用 io.max 统一配置 I/O 带宽和 IOPS 限制。

控制 CPU 使用率示例:

运行以下 Go 程序,会吃掉两个 CPU:

1
2
3
4
5
6
7
8
9
func main() {
go func() {
for {
}
}()
for {

}
}
1
go build -o busyloop
1
./busyloop

此时运行top命令,会显示 200%CPU 占用。

1
2
   PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                
426388 cadmin 20 0 702356 1024 640 R 210.0 0.0 0:18.75 busyloop

他的 PID 号是426388,我们可以mkdir /sys/fs/cgroup/cpudemo,然后将它添加到cpu.procs中。

1
2
echo ps -ef|grep busyloop|grep -v grep|awk '{print $2}' > cgroup.procs
echo "100000 1000000" > cpu.max

此时限制 100000/1000000 就是使用 10% 的 CPU 了。


如何检查系统使用的是 cgroup v1 还是 v2?

运行以下命令:

1
mount | grep cgroup
  • 如果输出中包含 cgroup2,说明系统使用的是 cgroup v2。
  • 如果输出中包含多个子系统(如 cpumemory 等),说明使用的是 cgroup v1。

可视化对比

以下是 cgroup v1 和 v2 的结构对比:



Linux中的Cgroup
https://mfzzf.github.io/2025/03/13/Linux中的Cgroup/
作者
Mzzf
发布于
2025年3月13日
许可协议