如何排查 Kubernetes 节点上容器进程导致的 CPU 节流问题?

文章导读
在 Kubernetes 生产环境中,容器 CPU 节流(Throttling)是导致应用延迟突增的常见原因。即使节点整体 CPU 空闲,单个容器触达 Limit 上限也会被内核强制暂停。排查的核心在于精准定位到具体容器的 cgroup 路径,确认节流计数,并安全调整资源配额。
📋 目录
  1. A 精准定位:从 Pod 到 Cgroup 路径
  2. B 安全调整:资源配额修改模板
  3. C 验证效果:对比监控指标
  4. D 常见坑与排查建议
A A

在 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 工具评估合理值。

如何排查 Kubernetes 节点上容器进程导致的 CPU 节流问题?

验证效果:对比监控指标

调整资源配置后,需再次登录节点验证 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 10050

2. 应用指标对比

  • 延迟(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 工具评估合理值。