【背景】
做了三年 K8s 运维,踩得最多、也最容易被忽略的一个坑,就是 CPU limit 带来的 CFS throttling。
具体现象:一个 Java 在线服务(Spring Boot,4C8G Pod),CPU request=1、limit=1,稳态 CPU 使用率只有 25%(看起来「离 limit 远着呢」),但 P99 从 18ms 涨到了 52ms。
打开 cgroup 一看:
# cgroup v1
cat /sys/fs/cgroup/cpu/kubepods/podXXX/cpu.stat
nr_periods 4820311
nr_throttled 283417
throttled_time 1987654321
throttling ratio ≈ 5.9%——每 17 个调度周期就有 1 个被卡住。Java 的 GC STW、线程池 burst、JIT 编译这些瞬间峰值操作,恰好撞在 CFS quota 的窗口边界上,被 throttle 了。
关键问题在于:平均 CPU 使用率 25% 完全不能说明 throttling 不严重,因为 CFS quota 是按每个调度周期(默认 100ms)的窗口来限的,不是按"总平均"来的。
【常见分歧 / 几种做法】
我见过三种典型立场:
派系 A:CPU limit = CPU request(设死) 理由:公平、可预测、容量规划简单。"一个 Pod 就给你这么多 CPU,别想多拿。" 代价:burst 能力被完全砍掉,对延迟敏感服务 P99 直接翻倍。
派系 B:只设 request,不设 CPU limit 理由:K8s 调度用 request 保证"最少能拿到多少",limit 不设意味着"上限不封顶",burst 能力保留,P99 友好。 代价:极端情况下(比如 GC 风暴、流量突增),一个 Pod 可能吃满整个节点的 CPU,把同节点邻居全拖下去。
派系 C:limit = 2x request 或 4x request(折中) 理由:既保留一定的 burst 空间,又不至于失控。 代价:这个倍数到底取多少?2x 够吗?4x 会不会还是不够?本质上是"凭感觉调参"。
【我的倾向与理由】
分场景,不"一刀切":
-
在线延迟敏感服务(API、搜索、风控)
- CPU request 按 P95 用量设(保证调度不超卖)
- CPU limit 不设或设成节点总 CPU(等于不限流)
- 防止"吃满节点"靠的不是 limit,而是 HPA + 副本数 + 节点资源预留
- 关键监控:
container_cpu_cfs_throttled_periods_total / container_cpu_cfs_periods_total,ratio > 3% 就该告警,> 5% 就该调
-
Batch / 离线任务(ETL、报表、ML 训练)
- CPU limit = CPU request(设死)
- 理由:这类任务对 P99 不敏感,公平性更重要
- 配合
priorityClassName=low+preemptionPolicy=PreemptLowerPriority,确保在线 Pod 随时能抢占
-
GPU 节点上的 CPU 侧
- GPU 本身有硬隔离(MIG / vGPU),但 CPU 侧的 limit 仍然影响 kernel 线程、数据搬运
- 建议:GPU Pod 的 CPU limit 至少 2x request,给 CUDA kernel launch 留 burst 空间
核心理由:CFS quota 的 throttle 是"硬卡",不是"软限"。一旦触发,线程直接被挂起,不像 I/O 的 io.max 还有 burst 窗口。对延迟敏感服务,这个"硬卡"的代价远大于"不设限"带来的邻居风险——后者可以用调度策略、资源预留、priority 来兜底。
【想听大家怎么选】
几个具体问题想征集经验:
- 你们线上 K8s 集群(什么版本、cgroup v1 还是 v2)里,在线服务的 CPU limit 到底怎么定的?有没有"不设 limit"的先例?
- cgroup v2 的
cpu.max和 v1 的 CFS quota 行为一样吗?v2 有没有 burst 参数(cpu.max.burst)能缓解 throttling?你们用上了吗? - 不设 CPU limit 之后,你们怎么防"一个 Pod 吃满节点"?HPA 够不够?有没有用过 LimitRange 做兜底?
- 你们监控 throttling 的告警阈值设的多少?有没有被 throttling 坑过 P99 但一开始完全没往这个方向想的?
- 有没有用 coscheduling(Kueue / Volcano)来替代 limit 做资源隔离的?效果如何?
欢迎拍砖,尤其是"我踩过这个坑然后怎么解的"的真实案例。