目录
cgroup 详解
cgroup(Control Groups)是 Linux 内核提供的资源隔离与限制机制,用于对进程组(process groups)的 CPU、内存、IO、网络等系统资源进行精细化控制。它是容器技术(如 Docker、Kubernetes)、虚拟化、资源管理工具(如 systemd)的核心底层依赖,核心目标是:将进程分组管理,为每组分配可控的资源配额,避免单个进程/组过度占用资源影响系统稳定性。
一、核心概念
理解 cgroup 需先掌握 4 个核心术语:
| 术语 | 作用 |
|---|---|
| 任务(Task) | 即 Linux 进程(PID 对应的实体),是 cgroup 资源控制的最小单位,一个任务可加入多个 cgroup(不同子系统)。 |
| 控制组(cgroup) | 一组被统一资源控制的任务集合,可包含子 cgroup(形成层级结构,资源可继承/限制)。 |
| 子系统(Subsystem) | 即资源控制器(Resource Controller),对应一种具体资源的控制能力(如 CPU 子系统控制 CPU 使用率)。 |
| 层级(Hierarchy) | 由多个 cgroup 组成的树状结构(与文件系统目录树类似),一个层级绑定一个或多个子系统,任务通过挂载层级的目录加入 cgroup。 |
关键关系(核心规则)
- 一个层级可绑定 多个子系统(共同控制该层级下 cgroup 的资源);
- 一个子系统只能绑定 一个层级(避免资源控制冲突);
- 一个任务可加入 多个层级 的 cgroup(每个层级对应不同子系统,实现多资源控制);
- 同一层级中,一个任务 只能属于一个 cgroup(层级是树状结构,任务需明确归属某一分支)。
二、主要子系统(资源控制器)
Linux 内核支持的核心子系统(不同内核版本可能略有差异,lssubsys -a 可查看当前系统支持的子系统):
| 子系统名称 | 功能描述 |
|---|---|
cpu | 限制 cgroup 中任务的 CPU 使用率(如限制最多使用 50% CPU)。 |
cpuacct | 统计 cgroup 中任务的 CPU 使用情况(如用户态/内核态 CPU 耗时、总使用率)。 |
memory | 限制 cgroup 的内存使用上限(物理内存+交换空间),并统计内存使用量。 |
blkio | 限制块设备 IO 带宽(如硬盘、SSD),控制读写速度、IO 优先级。 |
devices | 控制 cgroup 中任务对设备的访问权限(允许/禁止读写/创建某类设备,如 /dev/sda)。 |
net_cls | 为 cgroup 中的网络数据包打上类标识(classid),配合 tc 工具做网络限流。 |
net_prio | 控制 cgroup 中任务的网络流量优先级。 |
pid | 限制 cgroup 中允许创建的最大进程数(PID 数量)。 |
freezer | 暂停/恢复 cgroup 中的所有任务(类似 kill -STOP/CONT,用于容器暂停)。 |
cpuset | 绑定 cgroup 中任务到指定 CPU 核心和 NUMA 节点(如仅允许使用 CPU0/CPU1)。 |
hugetlb | 限制 cgroup 对大页内存(HugeTLB)的使用。 |
rdma | 限制 cgroup 对 RDMA(远程直接内存访问)资源的使用。 |
三、cgroup 的两种版本:v1 vs v2
cgroup 有两个主要版本,v2 是内核 4.5+ 引入的新一代架构,解决了 v1 的设计缺陷(如子系统分散、层级冲突),目前已成为 Docker、Kubernetes 的默认推荐版本。
核心差异对比
| 特性 | cgroup v1 | cgroup v2 |
|---|---|---|
| 子系统管理 | 每个子系统独立层级,分散挂载(如 /sys/fs/cgroup/cpu) | 所有子系统统一到一个层级,挂载点 /sys/fs/cgroup/unified(或直接 /sys/fs/cgroup) |
| 资源继承 | 子 cgroup 需单独配置,无统一默认 | 子 cgroup 自动继承父 cgroup 资源限制,配置更简洁 |
| 内存控制 | 物理内存、交换空间分开限制(memory.limit_in_bytes) | 统一限制(memory.max),支持 OOM 优先级 |
| CPU 控制 | 依赖 cpu.shares(相对权重)、cpu.cfs_quota_us(绝对限制) | 简化为 cpu.max(绝对限制)、cpu.weight(相对权重),支持 CPU 带宽控制 |
| 进程管理 | 任务可属于多个层级的 cgroup | 任务仅属于一个 cgroup(统一层级),避免冲突 |
| 兼容性 | 支持所有老工具(如 docker run --cpus 早期版本) | 需工具适配(Docker 19.03+、K8s 1.19+ 完全支持) |
查看当前系统使用的版本
# 方法1:查看挂载点
mount | grep cgroup
# 若输出包含 /sys/fs/cgroup/unified 或 /sys/fs/cgroup 且无单独子系统挂载,即为 v2
# 若输出多个 /sys/fs/cgroup/cpu、/sys/fs/cgroup/memory 等,即为 v1
# 方法2:通过 /proc/cgroups 判断
cat /proc/cgroups
# v2 中所有子系统的 hierarchy 列值相同(统一层级),v1 中不同子系统值不同
四、cgroup 实操(v2 示例)
cgroup 基于文件系统实现,所有配置均通过操作 /sys/fs/cgroup 下的文件完成(需 root 权限)。以下以 “限制进程 CPU 使用率、内存上限” 为例,演示手动配置流程。
前提:确保系统启用 cgroup v2
若当前为 v1,可通过以下方式临时切换(重启失效):
# 卸载所有 v1 子系统
for m in $(mount | grep cgroup | grep -v unified | awk '{print $3}'); do umount $m; done
# 挂载 v2 统一层级
mount -t cgroup2 none /sys/fs/cgroup
步骤1:创建 cgroup 控制组
在 /sys/fs/cgroup 下创建目录(即创建一个 cgroup,内核会自动生成默认配置文件):
# 创建名为 "my-cgroup" 的控制组
mkdir /sys/fs/cgroup/my-cgroup
cd /sys/fs/cgroup/my-cgroup
# 查看自动生成的配置文件(包含所有子系统的控制参数)
ls
# 输出示例:cgroup.controllers cgroup.max.depth memory.max cpu.max ...
步骤2:配置资源限制
(1)限制 CPU 使用率(最多使用 1 个 CPU 核心)
cgroup v2 用 cpu.max 控制 CPU 绝对限制,格式为 配额/周期(单位:微秒,1 秒=1e6 微秒):
# 配置:周期 100ms(100000 微秒),配额 100ms(即 100% 占用 1 个核心)
echo "100000 100000" > cpu.max
# 若要限制为 50% CPU(0.5 个核心),配额设为 50ms:
# echo "50000 100000" > cpu.max
# 查看配置
cat cpu.max
(2)限制内存上限(最多使用 512MB 物理内存)
用 memory.max 控制内存上限(支持 K/M/G 单位):
# 限制物理内存最大 512MB(交换空间默认无限制,可通过 memory.swap.max 限制)
echo "512M" > memory.max
# 查看配置
cat memory.max
步骤3:将进程加入 cgroup
通过 cgroup.procs 文件写入进程 PID,即可将进程纳入该 cgroup 的资源控制:
# 假设要控制的进程 PID 为 1234
echo 1234 > cgroup.procs
# 验证进程是否在该 cgroup 中(查看 cgroup.procs 文件)
cat cgroup.procs
步骤4:监控 cgroup 资源使用
通过统计类文件查看资源使用情况:
# 查看 CPU 使用统计(单位:微秒)
cat cpu.stat
# 查看内存使用统计(已用内存、峰值等)
cat memory.stat
步骤5:删除 cgroup
先确保 cgroup 中无进程(cgroup.procs 为空),再删除目录:
# 清空进程(可选,若进程已退出则无需操作)
echo > cgroup.procs
# 删除 cgroup
rmdir /sys/fs/cgroup/my-cgroup
五、cgroup 的典型应用场景
- 容器技术:Docker、Kubernetes 利用 cgroup 实现容器的资源隔离(如
docker run --cpus 1 --memory 1G本质是配置 cgroup); - 系统资源管理:systemd 集成 cgroup,通过
service或slice控制服务的资源(如systemctl set-property nginx.service CPUQuota=50%); - 多租户隔离:云服务器(如阿里云 ECS)利用 cgroup 隔离不同租户的资源,避免单个租户占用过多资源;
- 测试环境限流:压测时限制测试进程的 CPU/内存使用,避免影响生产环境。
六、常见问题与注意事项
- 权限问题:
/sys/fs/cgroup目录默认仅 root 可操作,普通用户需通过sudo或文件系统权限配置; - 内存限制不生效:需确保内核启用
CONFIG_MEMCG编译选项(主流发行版默认启用),且未禁用 memory 子系统; - CPU 限制与核心数:
cpu.max的配额不能超过周期(如周期 100ms 时,配额最大 100ms,对应 1 个核心),多核心需调整周期或配额; - v1 与 v2 兼容性:老工具(如早期
docker版本)可能不支持 v2,需切换回 v1 或升级工具; - 子 cgroup 资源限制:子 cgroup 的资源上限不能超过父 cgroup(如父 cgroup 限制 1G 内存,子 cgroup 最多只能设 1G)。
总结
cgroup 是 Linux 内核的核心资源管理机制,通过“任务-控制组-子系统-层级”的架构,实现了对进程组的多维度资源控制。v2 版本简化了配置、解决了 v1 的设计缺陷,已成为主流场景的首选。无论是容器、虚拟化还是系统资源管理,cgroup 都是实现“资源可控”的关键技术,理解其原理和实操方法,能帮助更好地排查资源相关问题(如容器 OOM、CPU 占用过高)。
49

被折叠的 条评论
为什么被折叠?



