4. CPU资源配额基础:Kubernetes CPU Request与Limit机制、CFS配额与CPU Throttling
在服务网格场景下,Envoy Sidecar 与业务容器共享同一套 CPU 资源配额。理解 Kubernetes 的 CPU 资源模型以及底层 CFS(Completely Fair Scheduler)配额机制,是诊断因 CPU 节流(Throttling)导致 API 延迟飙升的前提。
4.1 CPU Request 与 Limit:资源保证与硬边界
Kubernetes 通过 Request 和 Limit 两个参数定义容器的 CPU 资源约束:
| 参数 | 含义 | 调度依据 | 运行时行为 |
|---|---|---|---|
| Request | 容器保证能获得的 CPU 时间下限 | 节点调度决策(总和 ≤ 节点可分配) | CFS 为该容器分配对应的权重(Shares) |
| Limit | 容器最多能使用的 CPU 时间上限 | 不参与调度 | CFS 通过配额周期(CFS Quota)强制执行硬限制 |
关键认知: Request 决定“你能用多少”,Limit 决定“你最多能用多少”。当 Limit > Request 时,容器在空闲时可突发(Burst)使用额外 CPU;当 CPU 争用时,容器只能获得 Request 对应的份额。
4.2 CFS 配额与 CPU Throttling 原理
Kubernetes 的 CPU Limit 底层由 Linux CFS 的 cpu.cfs_quota_us 和 cpu.cfs_period_us 实现。默认周期为 100ms(即 100000μs)。
- CFS Period:一个固定的时间窗口,默认 100ms。
- CFS Quota:在该周期内,容器允许使用的 CPU 时间总量。
- Throttling:当容器在周期内消耗完 Quota,剩余时间将被强制休眠,直到下一个周期重置。
例如,设置 limits.cpu: 2,则 CFS Quota = 2 × 100000μs = 200000μs。容器每 100ms 最多运行 200ms(即 2 个核满负载)。
Throttling 计算公式:
Throttled Time = 容器在周期内实际运行时间 - CFS Quota(当实际运行时间 > Quota 时)
节流率 = Throttled Time / (CFS Period × 周期数)
Throttled Time = 容器在周期内实际运行时间 - CFS Quota(当实际运行时间 > Quota 时)
节流率 = Throttled Time / (CFS Period × 周期数)
4.3 CPU Throttling 对服务网格延迟的影响
Envoy 作为 Sidecar 处理所有入站和出站流量。当 Envoy 容器被 CPU Throttling 时,其事件循环(Event Loop)无法及时处理网络 I/O,直接导致:
- 请求排队:Worker 线程被暂停,新请求在连接池或缓冲区堆积。
- 延迟抖动:P99 延迟出现周期性尖峰,与 CFS 周期(100ms)对齐。
- 连接超时:上游连接建立或 TLS 握手因调度延迟而失败。
常见误区: 仅监控容器 CPU 使用率(如 80%)无法发现 Throttling。Throttling 发生在微秒级的时间片内,必须通过
container_cpu_cfs_throttled_seconds_total 指标或 /sys/fs/cgroup/cpu.stat 中的 nr_throttled 来观测。
4.4 CFS 配额与 CPU Throttling 工作流程
下图展示了从 Pod 创建到 CFS 执行 Throttling 的完整链路:
4.5 关键监控指标与诊断方法
在服务网格延迟诊断中,以下指标直接关联 CPU Throttling:
| 指标名称(Prometheus) | 类型 | 诊断意义 |
|---|---|---|
container_cpu_cfs_throttled_seconds_total |
Counter | 累计 Throttled 时间,增量反映节流严重程度 |
container_cpu_cfs_throttled_periods_total |
Counter | 发生 Throttling 的周期数,与总周期数对比得节流率 |
container_cpu_cfs_periods_total |
Counter | CFS 总周期数,用于计算节流比例 |
envoy_server_live + 延迟直方图 |
Gauge/Histogram | 关联 Throttling 事件与 P99 延迟尖峰 |
诊断命令示例(在节点上直接查看 cgroup):
# 查看 Envoy 容器的 CFS 状态
cat /sys/fs/cgroup/cpu/kubepods/besteffort/pod<pod-uid>/<container-id>/cpu.stat
# 输出示例
nr_periods 12345
nr_throttled 678
throttled_time 34567890 # 单位:纳秒
# 节流率计算
throttle_ratio = nr_throttled / nr_periods # 0.055 = 5.5%
4.6 优化策略:避免 Envoy 被 Throttling
基于上述机制,针对服务网格的 CPU 资源配额优化应遵循以下原则:
- 设置合理的 Request:基于 Envoy 的稳态 CPU 使用率(P99 或 P95)设置 Request,确保调度器为其预留足够份额。
- Limit 不宜过紧:避免将 Limit 设置为与 Request 相同(即无突发能力)。建议 Limit = Request × 1.5~2.0,允许流量突发时 Envoy 能短暂使用更多 CPU。
- 监控 Throttling 而非 CPU 使用率:将
container_cpu_cfs_throttled_seconds_total加入告警规则,阈值设为 > 1% 节流率。 - 考虑禁用 CPU Limit(仅限特定场景):在独占节点或 QoS 保证的 Pod 中,可移除 Limit 以避免 Throttling,但需配合节点资源预留。
避坑提示: 不要盲目提高 Envoy 的 CPU Request。过高的 Request 会导致节点资源碎片化,降低调度密度。应结合 Envoy 的实际资源画像(通过 Prometheus 历史数据)进行精确配置。
4.7 知识结构总结
下表梳理了 CPU 资源配额的核心概念及其在服务网格延迟诊断中的角色:
| 概念 | 层级 | 对延迟的影响 | 优化方向 |
|---|---|---|---|
| CPU Request | 调度保证 | 低 Request 导致调度不足,竞争加剧 | 基于 P99 使用率设置 |
| CPU Limit | 运行时硬限制 | 过紧 Limit 导致 Throttling,延迟抖动 | 保留突发余量 |
| CFS Quota | 内核实现 | Quota 耗尽直接触发线程休眠 | 监控 nr_throttled |
| CFS Period | 内核时间窗口 | 固定 100ms,影响 Throttling 粒度 | 不可调(内核参数) |