Linux cgroup v2 资源控制实战:限制进程 CPU/内存/IO,systemd slice 管理

Linux cgroup v2 资源控制实战:限制进程 CPU/内存/IO,systemd slice 管理 Linux cgroup v2 资源控制实战限制进程 CPU/内存/IOsystemd slice 管理Linux cgroupControl Groups是内核提供的一种机制用于限制、记录和隔离进程组的资源使用。cgroup v2 是其第二代实现统一了层级结构简化了接口设计并与 systemd 深度集成。本文将带你从零开始掌握 cgroup v2 的核心用法包括 CPU、内存、IO 限制以及通过 systemd slice 进行服务资源管理。环境要求本教程在以下环境中测试通过操作系统Ubuntu 22.04 / Debian 12 / CentOS Stream 9内核版本5.10建议 6.xsystemd 版本245推荐使用雨云服务器 rainyun-com进行实验注册填优惠码2026off领 5 折优惠券。推荐机型2 核 4GB Linux 云服务器足以运行本文所有实验场景价格实惠按量计费适合学习测试。核心概念cgroup v1 vs cgroup v2cgroup v1 采用多层级结构每种资源cpu、memory、blkio 等有独立的层级树管理复杂容易出现资源竞争问题。cgroup v2 采用统一层级所有控制器挂载在同一棵树下接口更简洁解决了 v1 中的多个设计缺陷特性cgroup v1cgroup v2层级结构多层级统一层级接口路径/sys/fs/cgroup/controller//sys/fs/cgroup/资源控制粒度各控制器独立统一协调systemd 集成部分支持原生支持PSI 支持不支持支持主要控制器cpu限制 CPU 使用时间配额/周期memory限制内存和 swap 使用io限制块设备读写速率/IOPSpids限制进程数量cpuset绑定 CPU 核心和 NUMA 节点systemd slice 概念systemd 使用 slice、scope、service 三种单元类型管理 cgroupslice资源控制层级的容器单元如system.slice、user.slicescope由外部程序创建的进程组service由 systemd 管理的服务配置步骤第一步确认 cgroup v2 已启用# 检查挂载类型mount|grepcgroup# 应显示 cgroup2 类型# 或检查文件stat-fc%T /sys/fs/cgroup/# 输出 cgroup2fs 说明已启用 v2若系统使用混合模式可通过内核参数强制启用纯 v2# 编辑 GRUB 配置sudovim/etc/default/grub# 在 GRUB_CMDLINE_LINUX 中添加GRUB_CMDLINE_LINUXsystemd.unified_cgroup_hierarchy1sudoupdate-grubsudoreboot第二步手动创建 cgroup 并限制 CPU# 创建自定义 cgroupsudomkdir/sys/fs/cgroup/myapp# 启用 cpu 和 memory 控制器需在父级启用echocpu memory io|sudotee/sys/fs/cgroup/cgroup.subtree_control# 设置 CPU 限制每 100ms 周期内最多使用 50ms即 50% 单核echo50000 100000|sudotee/sys/fs/cgroup/myapp/cpu.max# 将进程加入 cgroup替换 PID 为实际进程号echoPID|sudotee/sys/fs/cgroup/myapp/cgroup.procs第三步限制内存使用# 设置内存上限为 512MBecho$((512*1024*1024))|sudotee/sys/fs/cgroup/myapp/memory.max# 设置内存软限制建议值echo$((400*1024*1024))|sudotee/sys/fs/cgroup/myapp/memory.high# 禁用 swap可选echo0|sudotee/sys/fs/cgroup/myapp/memory.swap.max# 查看当前内存使用cat/sys/fs/cgroup/myapp/memory.current第四步限制磁盘 IO# 查看块设备 major:minor 号ls-l/dev/sda# 例如 8:0# 限制读写速率最大读 50MB/s写 20MB/secho8:0 rbps52428800 wbps20971520|sudotee/sys/fs/cgroup/myapp/io.max# 限制 IOPS最大读 1000 IOPS写 500 IOPSecho8:0 riops1000 wiops500|sudotee/sys/fs/cgroup/myapp/io.max# 查看 IO 统计cat/sys/fs/cgroup/myapp/io.stat第五步使用 systemd slice 管理服务资源创建自定义 slice 单元文件sudovim/etc/systemd/system/myapp.slice[Unit] DescriptionMyApp Resource Slice Beforeslices.target [Slice] # CPU 限制总 CPU 的 30%相对权重 CPUQuota30% # 内存限制 MemoryMax1G MemoryHigh800M # IO 权重100 为默认值越小优先级越低 IOWeight50将服务绑定到该 slicesudovim/etc/systemd/system/myapp.service[Unit] DescriptionMyApp Service Afternetwork.target [Service] Slicemyapp.slice ExecStart/usr/bin/myapp Restartalways [Install] WantedBymulti-user.targetsudosystemctl daemon-reloadsudosystemctlenable--nowmyapp.service# 查看资源使用情况systemctl status myapp.service systemd-cgtop实战示例场景一限制 Python 爬虫的 CPU 占用# 启动爬虫后获取 PIDpython3 spider.pySPIDER_PID$!# 创建限制组CPU 不超过 25%sudomkdir/sys/fs/cgroup/spiderecho25000 100000|sudotee/sys/fs/cgroup/spider/cpu.maxecho$((256*1024*1024))|sudotee/sys/fs/cgroup/spider/memory.maxecho$SPIDER_PID|sudotee/sys/fs/cgroup/spider/cgroup.procs# 验证限制效果top-p$SPIDER_PID场景二使用 systemd-run 临时限制命令# 在限制资源的环境中运行命令无需手动创建 cgroupsudosystemd-run\--scope\--slicemyapp.slice\-pCPUQuota20%\-pMemoryMax256M\-- python3 heavy_task.py场景三查看 PSI压力指标cgroup v2 支持 PSIPressure Stall Information可监控资源压力# 查看 CPU 压力cat/sys/fs/cgroup/myapp/cpu.pressure# 查看内存压力cat/sys/fs/cgroup/myapp/memory.pressure# 查看 IO 压力cat/sys/fs/cgroup/myapp/io.pressure# 输出示例# some avg100.00 avg600.00 avg3000.00 total0# full avg100.00 avg600.00 avg3000.00 total0常见问题Q设置 cpu.max 后为何没有限制效果A检查父级 cgroup 是否已启用 cpu 控制器。执行cat /sys/fs/cgroup/cgroup.subtree_control确认包含cpu若没有则执行echo cpu | sudo tee /sys/fs/cgroup/cgroup.subtree_control。Qmemory.max 设置后进程被 OOM Kill 怎么办A可先设置较宽松的memory.high软限制系统会在达到该值时主动回收内存并触发 throttle而非直接 kill。只有超过memory.max时才会触发 OOM。Q如何让 cgroup 设置在重启后持久化A直接操作/sys/fs/cgroup/下的文件不会持久化。推荐通过 systemd slice/service 单元文件管理或使用cgconfig工具需安装libcgroup-tools配合/etc/cgconfig.conf。Qsystemd-cgtop 显示的资源与 top 有差异Asystemd-cgtop显示的是 cgroup 维度的聚合数据而top显示单进程数据。两者统计维度不同属正常现象。Q如何删除自定义 cgroupA先将所有进程移出移到父级 cgroup再使用rmdir删除目录# 将进程移到根 cgroupechoPID|sudotee/sys/fs/cgroup/cgroup.procs# 删除空目录sudormdir/sys/fs/cgroup/myapp