排查CPU资源争抢需确认是否真实竞争:查容器cgroup配额(cpu.max或cpu.shares)、用PSI指标看CPU等待压力、结合docker stats与top -H定位高负载容器及线程,并验证K8s limits或cpu-quota配置是否合理。

排查容器化环境中的 CPU 资源争抢,不能只看“CPU 使用率高”,而要确认是不是真的在争——即多个容器/进程在竞争有限的 CPU 时间片。关键在于区分“用得多”和“抢不到”。
看清楚容器实际能用多少 CPU
宿主机上 lscpu 显示 16 核,不代表每个容器都能用满 16 核。Docker 或 Kubernetes 通过 cgroups 限制 CPU 资源,必须查容器视角的真实配额:
- 进容器执行 cat /sys/fs/cgroup/cpu.max(cgroup v2):返回类似 500000 100000,表示该容器每 100ms 最多运行 50ms(即 0.5 核)
- 查 cpu.shares(cgroup v1):cat /sys/fs/cgroup/cpu/cpu.shares,值为 1024 是默认权重,512 就是默认的一半——但注意:它只在资源争抢时起作用,空闲时不生效
- 对比宿主机 nproc 和容器内 nproc:若两者一致,不代表能用满,只是 cgroup 未隐藏逻辑核数;真正限制在 cpu.max 或 cpu.cfs_quota_us
识别是否真存在 CPU 争抢
使用 PSI(Pressure Stall Information)指标,这是 Linux 内核专为回答“任务是否因等 CPU 而卡住”设计的机制:
Linux AI 服务器 — 将 Linux 服务器转换为本地 AI 推理集群。使用 systemd、NVIDIA CUDA 实现无头 Linux AI,零 GUI 开销。
- 查当前 CPU 压力:cat /proc/pressure/cpu,关注 some 行的 10s/60s/300s 平均值。若 10s 值持续 >10%,说明已有明显等待
- 对比 top 的 %CPU 和 pidstat -u 1 中的 %usr + %system:如果进程显示 CPU 高,但 PSI 的 some 值也高,大概率是调度延迟大、上下文切换多,而非纯计算瓶颈
- 特别注意:容器中看到的 load average 会包含所有被限制在该 cgroup 内的可运行任务,所以即使单个容器 CPU 使用率仅 60%,其内部 load 可能已超 10——这就是争抢信号
定位争抢源头是哪个容器或线程
先缩小范围,再深入线程级:
- 查本节点所有容器的 CPU 使用(需 docker 或 crictl):docker stats --no-stream 或 crictl stats --no-stream,重点关注 CPUPerc 和 PIDs 列;PIDs 数量突增常伴随调度压力
- 进高负载容器,用 top -H 看线程级占用,配合 ps -eo pid,ppid,tid,pcpu,comm --sort=-pcpu | head -10 找出最耗 CPU 的线程
- 若怀疑是 GC 或锁竞争导致伪 CPU 高(如 Java 应用),用 jstack PID | grep 'java.lang.Thread.State' | sort | uniq -c | sort -nr 统计线程状态分布;大量线程卡在 BLOCKED 或 WAITING,说明不是 CPU 算力不足,而是同步阻塞
验证配置是否合理
很多“CPU 跑满”问题,根源在资源配置策略错配:
- K8s 中检查 Pod 的 resources.limits.cpu 是否设为 1000m(即 1 核),但实际业务需要 2 核以上——这时即使没超限,也会因调度器分配不均造成争抢
- 避免混用 cpu-shares 和 cpu-quota:前者是相对权重,后者是硬上限;同时设置易引发不可预期行为,生产环境建议统一用 cpu.quota/cpu.period 或 K8s 的 limits
- 检查节点是否启用了 static CPU manager policy(K8s):若未开启,关键容器可能被调度到同一物理核,加剧争抢

















