文件是什么
cgroup v2 的 cpu.stat 记录某个控制组消耗的 CPU 时间计数,以及受 CPU 限额约束的统计数据,是判断「容器是不是被限额卡住」的一手证据。它包含 usage_usec(累计 CPU 时间)、user_usec/system_usec(用户态与内核态拆分)、nr_periods、nr_throttled、throttled_usec;后三个字段只在设置了 cpu.max 之后才有意义,nr_throttled 与 throttled_usec 增长说明任务反复撞上限额并被强制等待。
基本信息
| 路径 | /sys/fs/cgroup/<组路径>/cpu.stat(cgroup v2 unified) |
|---|---|
| 单位 | 微秒(usec);计数为累计值 |
| 限额接口 | cpu.max,格式「quota period」,如 200000 100000 表示 2 核 |
| systemd 对应 | CPUQuota=(限额)、CPUWeight=(权重) |
| cgroup v1 差异 | 位于 /sys/fs/cgroup/cpu/<组>/,限额用 cpu.cfs_quota_us / cpu.cfs_period_us |
| 权限 | 读取一般可读;修改需 root 或委派写权限 |
典型使用场景
- 容器出现周期性延迟尖刺:throttled_usec 持续增长即为节流导致,需放宽 CPUQuota
- 上线前压测:对比设置限额与不设限额时的吞吐,量化节流代价
- 混部环境排查「谁在拖慢谁」:逐个 slice 看 nr_throttled 占比
- 确认限额是否过大闲置:usage_usec 长期远低于配额说明配额虚高
- 与 cpu.pressure(PSI)联合使用,区分限额节流与宿主侧排队
查看与调整
查看与调整
cat /sys/fs/cgroup/myapp.slice/cpu.max # 查看限额:如 200000 100000 表示 2 核
cat /sys/fs/cgroup/myapp.slice/cpu.stat # 读取全部计数器
awk '$1=="throttled_usec"{print $2}' /sys/fs/cgroup/myapp.slice/cpu.stat # 只看累计节流时间
sleep 60 # 等一分钟后再读一次,两次相减才是当前每秒的节流增量
systemctl set-property myapp.service CPUQuota=200% # 临时放宽到 2 核,立即生效
systemctl show myapp.service -p CPUQuotaPerSecUSec # 核对系统最终生效的限额值字段逐项读法
| 字段 | 含义 | 判读要点 |
|---|---|---|
| usage_usec | 该组累计消耗的 CPU 时间 | 除以墙钟时间可换算成平均核数 |
| user_usec / system_usec | 用户态与内核态时间拆分 | system 占比高要查系统调用或内核处理 |
| nr_periods | 限额周期总数 | 分母,用于算节流比例 |
| nr_throttled | 被节流的周期数 | 与 nr_periods 的比值接近 1 表示长期贴限额 |
| throttled_usec | 被强制等待的累计时间 | 要看增量,绝对值不代表当前状态 |
nr_throttled 与 throttled_usec 都是累计值,单次读取的绝对值说明不了「现在是否还在被节流」。标准做法是间隔采样两次求差值;服务重启后计数归零,跨重启比较需要外部指标系统。
宿主 vCPU 超卖、NUMA 争抢或邻居占用导致的排队不会记入本组的 throttled_usec。这类场景要看宿主机 steal time、cpu.pressure 或宿主侧调度指标,避免把超卖问题误判为容器限额问题。