linux学习笔记-cgroup(二)
cgroups (Control Groups) 是 Linux 内核功能,用于限制、记录和隔离进程组的资源使用(CPU、内存、磁盘I/O、网络等)。cgroup v2 是 cgroups 的第二代实现,提供了更统一和一致的接口。
一、cgroup v2 核心概念
- 层级结构(Hierarchy):v2 采用单一层级结构,所有控制器挂载在统一视图下
- 控制器(Controllers):资源控制模块(如 cpu、memory、io 等)
- cgroup 路径:每个 cgroup 在虚拟文件系统中有唯一路径
- 进程归属:进程可属于任意 cgroup,受该 cgroup 资源限制
二、基本操作步骤
1. 挂载 cgroup v2 文件系统
# 检查当前系统是否已启用 cgroup v2
mount | grep cgroup
# 若未启用,在 /etc/fstab 中添加
cgroup2 /sys/fs/cgroup cgroup2 rw,relatime,nsdelegate 0 0
# 临时挂载
mount -t cgroup2 cgroup2 /sys/fs/cgroup
2. 创建和删除 cgroup
# 进入 cgroup 根目录
cd /sys/fs/cgroup
# 创建新 cgroup(自动创建子目录)
mkdir myapp_group
# 删除 cgroup
rmdir myapp_group
3. 启用资源控制器
# 查看当前可用的控制器
cat cgroup.controllers
# 启用控制器(如 memory 和 cpu)
echo '+memory +cpu' > cgroup.subtree_control
# 验证已启用控制器
cat cgroup.subtree_control
三、资源控制示例
1. CPU 限制
示例:限制进程最多使用 1 个 CPU 核心(100ms/100ms)
# 创建 cgroup
mkdir cpu_limit_group
# 启用 CPU 控制器
echo '+cpu' > cgroup.subtree_control
# 设置 CPU 配额(周期 100ms,配额 100ms)
echo '100000' > cpu_limit_group/cpu.max
# 将进程 PID 添加到 cgroup
echo 1234 > cpu_limit_group/cgroup.procs
2. 内存限制
示例:限制内存使用不超过 1GB
# 创建 cgroup
mkdir mem_limit_group
# 启用 memory 控制器
echo '+memory' > cgroup.subtree_control
# 设置内存硬限制(1GB)
echo '1G' > mem_limit_group/memory.max
# 设置 OOM 优先级(可选)
echo '100' > mem_limit_group/memory.oom.group
# 添加进程
echo 5678 > mem_limit_group/cgroup.procs
3. 磁盘 I/O 限制
示例:限制磁盘读写带宽
# 创建 cgroup
mkdir io_limit_group
# 启用 io 控制器
echo '+io' > cgroup.subtree_control
# 查找磁盘设备号(如 /dev/sda)
lsblk -d -o NAME,MAJ:MIN
# 设置读带宽限制(10MB/s)
echo '254:0 rbps=10485760' > io_limit_group/io.max
# 设置写 IOPS 限制(1000 iops)
echo '254:0 wiops=1000' > io_limit_group/io.max
4. 混合资源限制
示例:为 Web 服务设置综合资源限制
# 创建 cgroup
mkdir web_service
# 启用所有可用控制器
echo '+cpu +memory +io +pids' > cgroup.subtree_control
# CPU 限制(50% 单核)
echo '50000 100000' > web_service/cpu.max
# 内存限制(2GB)
echo '2G' > web_service/memory.max
# 进程数限制(100 进程)
echo '100' > web_service/pids.max
# 启动服务并加入 cgroup
systemd-run --scope -p MemoryMax=2G -p CPUQuota=50% /opt/webapp/start.sh
四、高级功能示例
1. 资源统计监控
# 查看内存使用统计
cat memory.current
cat memory.stat
# 查看 CPU 使用统计
cat cpu.stat
# 查看 IO 统计
cat io.stat
2. OOM 控制
# 禁用某 cgroup 的 OOM 杀手(当内存超限时直接报错而非 kill 进程)
echo '1' > memory.oom.group
# 查看 OOM 事件
cat memory.oom.group
3. 嵌套 cgroup 结构
# 创建父 cgroup
mkdir parent_group
echo '+cpu +memory' > parent_group/cgroup.subtree_control
# 创建子 cgroup
mkdir parent_group/child1
echo '50000 100000' > parent_group/child1/cpu.max
mkdir parent_group/child2
echo '25000 100000' > parent_group/child2/cpu.max
# 父 cgroup 设置总限制
echo '75000 100000' > parent_group/cpu.max
五、Docker 中的 cgroup v2
Docker 从 20.10 版本开始支持 cgroup v2。使用示例如:
# 运行容器时指定资源限制(自动创建 cgroup)
docker run -d \
--cpus=1.5 \
--memory=512m \
--blkio-weight=300 \
--name mycontainer \
nginx:alpine
# 查看容器对应的 cgroup
systemd-cgls | grep docker
六、注意事项
- 修改
cgroup.subtree_control
会影响所有子 cgroup - 资源限制值必须满足父 cgroup 的约束
- 某些控制器(如
cpuset
)需要额外配置 - 系统重启后 cgroup 配置不会持久化,需通过 systemd 或脚本实现持久化
- 使用
nsdelegate
挂载选项时,命名空间内的 cgroup 操作会被委派给容器
通过以上方法,可以有效地利用 cgroup v2 对系统资源进行精细化管理,确保关键应用的服务质量(QoS),同时防止资源滥用导致的系统不稳定。