Linux cgroup v2作为内核资源控制框架的统一版本,提供CPU、内存、IO、设备的层级化管理能力。服务器运维场景下,通过cgroup v2可对容器化服务、批处理任务、用户会话实施精细化资源限制,防止单一进程耗尽整机资源引发雪崩。cgroup v2采用统一层级结构(unified hierarchy),相比v1的多控制器独立层级,资源控制粒度更精确,配置方式更简洁。
cgroup v2与v1架构差异对比
cgroup v1时代,CPU、memory、blkio等控制器各自维护独立层级,进程可同时挂载到不同层级的cgroup中。这种设计导致资源统计碎片化——一个进程的CPU使用在cpuacct层级统计、内存使用在memory层级统计,运维人员需要跨多个路径拼凑资源画像。
cgroup v2将所有控制器统一到单一层级(/sys/fs/cgroup/),进程只能挂载到一个cgroup节点,该节点同时管理CPU、内存、IO等所有资源。子节点的资源限制不能超过父节点,形成自然的资源分配树。v2还新增了PSI(Pressure Stall Information)压力监控机制,量化资源竞争对任务延迟的影响。
检查系统是否已启用cgroup v2:
# 检查cgroup版本
mount | grep cgroup
# cgroup2 on /sys/fs/cgroup type cgroup2 (rw,relatime,nsdelegate)
# 查看已挂载的控制器
cat /sys/fs/cgroup/cgroup.controllers
# cpuset cpu io memory hugetlb pids rdma misc
# 查看某个进程的cgroup归属
cat /proc/$PID/cgroup
# 0::/user.slice/user-1000.slice/session-1.scope
cgroup v2 CPU资源限制与权重分配
cgroup v2的CPU控制通过cpu控制器实现,提供三种限制方式:cpu.weight(权重分配,类似nice值)、cpu.max(绝对上限)、cpu.uclamp(利用率钳位)。
cpu.weight取值范围1~10000,默认100。权重不设硬上限,按比例分配空闲CPU时间。两个cgroup权重分别为100和200时,按1:2分配CPU。适合弹性负载场景——CPU空闲时高权重任务可获得更多算力。
cpu.max设置绝对限速,格式为”$MAX $PERIOD”,默认周期100000微秒(100ms)。cpu.max 50000 100000表示每100ms周期内最多使用50ms CPU时间,即限制为50%单核。
# 创建cgroup并启用cpu控制器
sudo mkdir /sys/fs/cgroup/myapp
# 启用子cgroup的控制器(在父cgroup中配置)
echo "+cpu +memory +io" | sudo tee /sys/fs/cgroup/cgroup.subtree_control
# 设置CPU权重(权重分配模式)
echo 200 | sudo tee /sys/fs/cgroup/myapp/cpu.weight
# 设置CPU绝对上限(限制为单核30%)
echo "30000 100000" | sudo tee /sys/fs/cgroup/myapp/cpu.max
# 将进程加入cgroup
echo $PID | sudo tee /sys/fs/cgroup/myapp/cgroup.procs
# 验证CPU限制效果
# 在myapp cgroup内运行CPU密集任务,用top观察CPU使用率
cgroup v2内存限制与OOM控制策略
v2内存控制通过memory.max(硬限制)和memory.high(软限制)实现。memory.high超过后内核加大回收力度但不杀进程,memory.max超过后触发OOM Killer。memory.swap.max控制交换分区使用上限,设为0可禁用swap。
内存OOM行为可通过memory.oom.group控制。设为1时,cgroup内任何进程触发OOM将杀死该cgroup内所有进程(适合容器场景),设为0仅杀死导致OOM的单个进程。
# 内存限制配置
echo "2G" | sudo tee /sys/fs/cgroup/myapp/memory.max # 硬限制2GB
echo "1.5G" | sudo tee /sys/fs/cgroup/myapp/memory.high # 软限制1.5GB
echo "0" | sudo tee /sys/fs/cgroup/myapp/memory.swap.max # 禁止swap
# 容器场景:cgroup内任何进程OOM则杀全组
echo 1 | sudo tee /sys/fs/cgroup/myapp/memory.oom.group
# 查看当前内存使用
cat /sys/fs/cgroup/myapp/memory.current
cat /sys/fs/cgroup/myapp/memory.peak
# 查看内存压力
cat /sys/fs/cgroup/myapp/memory.pressure
# some avg10=0.00 avg60=0.00 avg300=0.00 total=0
# full avg10=0.00 avg60=0.00 avg300=0.00 total=0
PSI指标解释:some表示部分任务因资源不足等待的时间占比,full表示所有任务都在等待的时间占比。avg10/avg60/avg300分别是10秒/60秒/300秒滑动平均。当memory.pressure的full avg10持续偏高时,说明内存已严重不足,需要扩容或释放。
cgroup v2 IO带宽限制与设备控制
IO控制器通过io.max限制读写带宽和IOPS。格式为”$MACTYPE:$BANDWIDTH $IOPS”,支持rbps(读字节/秒)、wbps(写字节/秒)、riops(读IOPS)、wiops(写IOPS)。
# 获取设备号
lsblk -o NAME,MAJ:MIN
# sda 8:0
# 限制sda读写带宽各100MB/s
echo "8:0 rbps=104857600 wbps=104857600" | sudo tee /sys/fs/cgroup/myapp/io.max
# 限制IOPS(适合SSD场景)
echo "8:0 riops=1000 wiops=500" | sudo tee /sys/fs/cgroup/myapp/io.max
# 查看IO统计
cat /sys/fs/cgroup/myapp/io.stat
# 8:0 rbytes=1234567 wbytes=2345678 rios=123 wios=456
结合systemd使用cgroup v2的实践
现代Linux发行版已将systemd与cgroup v2深度集成,推荐通过systemd slice/unit配置资源限制而非手动操作cgroup文件。每个systemd service自动创建对应cgroup。
# /etc/systemd/system/myapp.service
[Unit]
Description=My Application
[Service]
ExecStart=/usr/bin/myapp
# CPU限制:最多使用2个核心
CPUQuota=200%
# 内存限制:最大2GB
MemoryMax=2G
MemoryHigh=1500M
# 禁止swap
MemorySwapMax=0
# IO限制
IOReadBandwidthMax=/dev/sda 100M
IOWriteBandwidthMax=/dev/sda 50M
# 进程数限制
TasksMax=100
[Install]
WantedBy=multi-user.target
# 重载并重启
sudo systemctl daemon-reload
sudo systemctl restart myapp
# 查看资源使用
systemctl status myapp
systemd-cgtop
systemd-cgtop命令实时展示各cgroup的CPU、内存、IO使用情况,是排查资源争抢问题的利器。当某服务memory.current接近memory.max时需提前扩容,避免OOM杀进程导致服务中断。
cgroup v2常见问题排查
控制器不可用:检查内核编译选项CONFIG_CGROUPS、CONFIG_CGROUP_V2。某些控制器需要在内核启动参数中添加cgroup_no_v1=all强制禁用v1。云服务器内核通常已启用v2,自编译内核需确认配置。
子cgroup无法设置权重:cpu.weight只在父cgroup启用了cpu控制器(cgroup.subtree_control中包含+cpu)时生效。cgroup v2的控制器是向下继承的,必须在每一级父节点显式启用。
memory.limit显示no limit:确认写入的值格式正确。memory.max接受字节数或带K/M/G后缀的值。读取时返回字节数,0表示无限制。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/linuxcgroupv2-zi-yuan-xian-zhi-pei-zhi-yu-jin-cheng-ge-li/