在 Kubernetes 生产环境中,容器 CPU 节流(Throttling)是导致应用延迟突增的常见原因。即使节点整体 CPU 空闲,单个容器触达 Limit 上限也会被内核强制暂停。排查的核心在于精准定位到具体容器的 cgroup 路径,确认节流计数,并安全调整资源配额。
先说结论:CPU 节流通常是因为容器设置的 CPU Limit 过低,导致进程被 Linux CFS 调度器强制暂停。优先通过 cgroup 指标确认节流次数,再按倍数调高资源限制,谨慎移除 Limit。
- 先确认:通过容器 PID 查找 cgroup 路径,确认 nr_throttled 是否持续增长
- 先处理:优先按 1.5~2 倍调高 CPU Limit,仅在紧急且节点资源充足时考虑移除限制
- 再验证:观察 nr_throttled 停止增长且应用延迟回落
精准定位:从 Pod 到 Cgroup 路径
直接使用通配符查找 cgroup 文件在生产环境往往无法定位到具体容器。建议通过 Pod UID 或容器 PID 精准锁定路径。
第一步:获取 Pod UID 和节点信息
# 获取 Pod UID 和所在节点
kubectl get pod <pod-name> -n <namespace> -o jsonpath='{.metadata.uid} {.spec.nodeName}'
# 输出示例:a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8 node-192-168-1-10第二步:登录节点查找容器 PID
SSH 登录到上述节点,根据容器运行时(containerd 或 docker)查找容器 ID 和 PID。
# 如果使用 containerd (crictl)
crictl ps | grep <pod-name>
# 获取容器 ID 后查看详细信息获取 PID
crictl inspect <container-id> | grep pid
# 如果使用 docker
docker ps | grep <pod-name>
docker inspect <container-id> | grep Pid第三步:确认 cgroup 路径与节流指标
拿到 PID 后(假设 PID 为 12345),查看该进程所属的 cgroup 路径。
# 查看 cgroup 路径
cat /proc/12345/cgroup
# 根据返回路径拼接统计文件
# 如果是 cgroup v2 (常见于新系统)
cat /sys/fs/cgroup/<上面查到的相对路径>/cpu.stat | grep nr_throttled
# 如果是 cgroup v1 (常见于旧系统)
cat /sys/fs/cgroup/cpu/<上面查到的相对路径>/cpu.cfs_throttled_us重点关注 nr_throttled 字段。连续执行两次该命令,如果数值明显增加(例如从 100 变为 500),说明存在严重节流。
安全调整:资源配额修改模板
确认节流后,不要盲目移除 CPU Limit。建议优先按当前值的 1.5 倍至 2 倍调高,避免“吵闹的邻居”效应影响同一节点的其他服务。
Deployment 资源调整示例:
spec:
containers:
- name: app
resources:
requests:
cpu: "500m"
limits:
cpu: "1000m" # 原为 500m,建议先调整为 1000m 观察应用更改:
kubectl apply -f deployment.yaml
kubectl rollout restart deployment/<deployment-name> -n <namespace>风险提示:仅在节点整体 CPU 使用率低于 50% 且业务紧急恢复时,才考虑暂时移除 limits.cpu 字段,并尽快通过 VPA 工具评估合理值。
验证效果:对比监控指标
调整资源配置后,需再次登录节点验证 cgroup 指标,并结合应用监控确认效果。
1. cgroup 指标对比
调整前(节流中):
$ cat /sys/fs/cgroup/.../cpu.stat
nr_throttled 5200
nr_periods 10000调整后(节流缓解):
$ cat /sys/fs/cgroup/.../cpu.stat
nr_throttled 5210 # 数值基本不再增长
nr_periods 100502. 应用指标对比
- 延迟(Latency):P99 延迟应从波动状态回归平稳。
- CPU 使用率:
kubectl top pod显示的数值可能会上升,这是因为容器不再被强制暂停,能更充分地利用时间片,属于正常现象。
常见坑与排查建议
1. 仅看 kubectl top 数据
kubectl top 基于 Metrics Server,展示的是平均使用率,无法反映瞬间的节流情况。一个容器可能平均使用率很低,但峰值触达限制导致严重节流。
2. 忽略 cgroup 版本差异
不同 Linux 发行版和 Kubernetes 版本使用的 cgroup 版本不同(v1 或 v2)。
- v2 特征:统计文件为
cpu.stat,包含nr_throttled。 - v1 特征:统计文件为
cpu.cfs_throttled_us,需结合cpu.cfs_quota_us分析。
如果找不到 cpu.stat,请检查 /sys/fs/cgroup 挂载情况。
3. 盲目移除所有限制
在生产环境中,完全移除 CPU Limit 可能导致节点资源争抢。如果节点资源已紧张,无限制容器可能耗尽 CPU,导致同一节点上的其他核心服务变慢。建议结合 Vertical Pod Autoscaler 工具评估合理值。