CPU 带宽限额
cgroup v2 用 cpu.max 限制一个控制组的 CPU 带宽,格式是「配额 周期」,单位微秒。写 50000 100000 表示每 100ms 周期最多用 50ms CPU,约等于 0.5 核;只写 max 表示不限额。它是容器与 systemd 服务限核的现行接口,替代了 cgroup v1 的 cpu.cfs_quota_us 与 cpu.cfs_period_us。组内任务用满配额后会被节流,等下一个周期再放行。
基本信息
| 接口路径 | /sys/fs/cgroup/<组>/cpu.max |
|---|---|
| 格式 | 配额 周期(微秒),或单写 max |
| 换算示例 | 50000 100000 约 0.5 核;200000 100000 即 2 核 |
| systemd 对应 | CPUQuota=50% |
| 节流观测 | cpu.stat 中的 nr_throttled 与 throttled_usec |
典型使用场景
- 容器 CPU 限额:docker 的 --cpus、Kubernetes 的 limits.cpu
- systemd 服务限核,防止单个服务打满整机
- 排查「配额没跑满却延迟很高」的节流问题
- 多租户隔离,按业务分配 CPU 预算
- 与 cpu.weight 的分工选择:要上限用配额,要竞争份额用权重
查看与设置
查看与设置
cat /sys/fs/cgroup/<组>/cpu.max # 查看当前配额与周期
echo '50000 100000' > /sys/fs/cgroup/<组>/cpu.max # 限制到约 0.5 核
cat /sys/fs/cgroup/<组>/cpu.stat # nr_throttled 与 throttled_usec
systemctl set-property myservice.service CPUQuota=50%
systemctl show myservice.service -p CPUQuotaPerSecUSec
systemd-cgtop -m # 各组实时资源占用cpu.max 与 cpu.stat 读法
| 字段 | 含义 | 注意 |
|---|---|---|
| 配额 | 周期内允许使用的微秒数 | 除以周期才是核数 |
| 周期 | 调度周期,默认 100000 微秒 | 周期越长突发能力越强、粒度越粗 |
| max | 表示不限额 | 默认状态通常就是 max 100000 |
| nr_throttled | 被节流的累计次数 | 持续增长说明配额偏紧 |
| throttled_usec | 累计被节流的时长 | 与周期一起判断节流严重程度 |
cpu.max 限制的是带宽而不是绑定核心:被限的组仍可在任意核上运行,需要独占核请改用 cpuset。
配额过紧会让延迟敏感服务被反复节流,表现为 P99 明显变差而平均 CPU 用量看起来并不高,必须结合 cpu.stat 判断。
设置渠道与生效范围
- 容器运行时:docker run --cpus=1.5 会换算成对应配额写入容器控制组
- Kubernetes:Pod 的 limits.cpu 由容器运行时落到 cpu.max
- systemd:systemctl set-property 写入 CPUQuota,默认生成 drop-in 持久化
- 直接写 /sys/fs/cgroup:适合临时调试,重新部署或重启后可能被上层配置覆盖
与相邻参数的边界
- cpu.weight 管组间竞争份额,不设上限;cpu.max 管绝对上限,不表达组间比例
- cpu.max.burst 允许在配额内累积突发额度,适合有脉冲峰值的服务
- cpuset 负责把任务绑到指定核,与带宽限制属于两个维度,可以叠加使用