登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  linux

Linux cgroups v2 CPU 配额和权重怎么区分

来源:17golang原创

时间:2026-09-08 04:29:26 380浏览 收藏

Linux cgroups v2 里,cpu.weightcpu.max 不是两种写法的同一个参数:前者解决“多个活跃子组如何分 CPU”,后者解决“这个组在一个周期内最多能用多少 CPU 时间”。如果只想让后台任务在竞争时少拿一些资源,用权重;如果必须把计算量压在明确上限内,用配额,必要时两者叠加。

要点速览
  • cpu.weight 默认值为 100,范围是 1–10000,含义是同级活跃子 cgroup 的相对份额,不是百分比。
  • cpu.max 使用 $MAX $PERIOD,例如 50000 100000 表示每 100000 微秒最多使用 50000 微秒。
  • memory.max 是硬限制,memory.high 更像回收压力与节流边界;委派子树始终不能突破父级限制。

先把 cpu.weight 和 cpu.max 放回两种模型

可以把同一父级下的两个活跃子 cgroup 想成共同争用一块 CPU 资源。cpu.weight=200 的组和 cpu.weight=100 的组,在都需要 CPU 时大致按 2:1 分配;其中一组空闲时,另一组可以利用空出来的时间,所以权重是“有竞争时的倾向”,不会自动切出固定百分比。

cpu.max 则给出带宽上限。格式是 $MAX $PERIOD,例如下面的设置把一个工作组限制在半个周期:

# 创建实验组;实际环境应确认 /sys/fs/cgroup 已挂载为 cgroup v2
sudo mkdir -p /sys/fs/cgroup/demo-worker

# 让父级负责向子组分配 CPU 与内存控制器
echo "+cpu +memory" | sudo tee /sys/fs/cgroup/subtree_control

# 每 100000 微秒最多使用 50000 微秒 CPU 时间
echo "50000 100000" | sudo tee /sys/fs/cgroup/demo-worker/cpu.max

# 只有发生 CPU 竞争时才体现相对优先级
echo 200 | sudo tee /sys/fs/cgroup/demo-worker/cpu.weight
Linux cgroups v2 中 cpu.weight 与 cpu.max 的静态关系框图
图1:用同一父级下的活跃子 cgroup 对照 cpu.weight 的比例分配和 cpu.max 的周期带宽边界。

因此,“给低优先级任务设置 20% CPU”并不严谨:若要表达硬上限,应使用 cpu.max;若只是希望它在和别的任务竞争时少分一些,应使用 cpu.weight。配额触发后,cpu.stat 中的 nr_throttledthrottled_usec 才能说明确实发生了限流。

用一个 worker.slice 组合配额、权重和内存

把进程写入 cgroup.procs 后,CPU 和内存规则才会作用到它。下面的片段展示最小组合;生产环境不要直接改系统服务所在的层级,最好为业务预留独立的父级。

# 设置 512 MiB 硬内存上限;超出且无法回收时可能触发该组内的 OOM 处理
echo "512M" | sudo tee /sys/fs/cgroup/demo-worker/memory.max

# 观察到高水位后施加回收压力,但它不是 memory.max 那样的硬上限
echo "384M" | sudo tee /sys/fs/cgroup/demo-worker/memory.high

# 将目标进程 PID 放入 cgroup;PID 应替换成实际业务进程号
echo "${PID}" | sudo tee /sys/fs/cgroup/demo-worker/cgroup.procs

这个组合表达的是:CPU 方面先受 cpu.max 的绝对上限约束,再在同级竞争中参考 cpu.weight;内存方面优先用 memory.high 观察回收压力,确有硬边界需求时再设置 memory.max。不要把 CPU 配额的百分比直接套到内存上,两个控制器的单位和失效方式不同。

cgroups v2 的内存与委派边界

memory.max 是主要硬限制,无法继续回收时会在该 cgroup 范围内触发 OOM 处理;memory.high 是节流和回收压力边界,超过它不等于立即杀进程。排查内存问题时,先读 memory.currentmemory.events,再决定是回收压力过高还是硬上限确实过小。

委派也有一个容易忽略的边界:低权限用户可以在被委派的子树里创建子 cgroup、组织自己的进程,但不能修改控制父级资源分配的文件,更不能通过子树逃出上层的 CPU 或内存限制。cgroup.procscgroup.subtree_control 是组织子树的重要入口,权限应单独授予,不要把整个目录粗暴地改成可写。

Linux cgroups v2 内存限制与委派子树的静态边界框图
图2:查看 memory.max、memory.high 与 delegated child 的层级关系,理解低权限委派不能突破父级限制。

发现配置了却不生效时怎么判断

先确认控制器是否在正确层级启用,再确认进程位置,最后看统计项,不要只看写入命令是否返回成功:

# 查看当前层级可用的控制器和已经启用的子树控制器
cat /sys/fs/cgroup/cgroup.controllers
cat /sys/fs/cgroup/cgroup.subtree_control

# 确认进程确实属于目标组
cat /sys/fs/cgroup/demo-worker/cgroup.procs

# 观察 CPU 是否真的被限流,以及内存是否触发事件
cat /sys/fs/cgroup/demo-worker/cpu.stat
cat /sys/fs/cgroup/demo-worker/memory.events

常见误区有三个:把 cpu.weight 当成固定百分比;只设置了父级文件却没有把进程放入子组;把 memory.high 当成绝对内存上限。最后可以用下面的速查表做选择。

目标优先设置判断信号
竞争时让某组多分或少分 CPUcpu.weight同级活跃组的相对份额
限制每个周期的 CPU 用量cpu.maxnr_throttledthrottled_usec
设置内存硬边界memory.maxmemory.events 与 OOM 事件
提前施加回收压力memory.high回收、节流和业务延迟变化

相关问题

cpu.weight=100 是否就是 100% CPU?

不是。100 是默认权重值,只在同一父级下与其他活跃子组比较。需要固定上限时使用 cpu.max

为什么写入 cpu.max 后进程仍能短时间突发?

配额按周期统计,短时观察可能跨越周期边界;应结合 cpu.stat 的限流计数和持续时间判断,而不是用一次瞬时 CPU 百分比下结论。

更完整的接口语义和委派规则可参考 Linux 内核 Control Group v2 文档。在生产环境调整前,先确认发行版的 systemd 或容器运行时是否也在管理同一层级。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>