这样做的核心逻辑在于改变了 Pod 的 QoS(服务质量)等级,从而从调度和内核两个层面优化资源抢占。以下是详细分析:
1. 提升 QoS 等级为 Guaranteed
在 K8s 中,Pod 根据 requests 和 limits 的配置分为三个 QoS 等级:
- BestEffort: 没设 requests 和 limits。
- Burstable: requests < limits(你目前的状态)。
- Guaranteed: requests == limits(你想要调整的状态)。
调整后的优势:
- 稳定性极高:Guaranteed 级别的 Pod 拥有最高优先级。当节点资源紧张时,K8s 会先驱逐 BestEffort 和 Burstable 的 Pod,最后才考虑 Guaranteed。
- 降低调度抖动:调度器(kube-scheduler)在放置 Pod 时只参考 requests。如果 requests 很小,调度器可能会在一个节点上堆叠太多 Pod,导致实际运行中发生严重的 CPU 争抢。对齐后,调度器会更加"保守",确保物理资源真实存在。
2. 优化 vCPU 资源抢占(内核层面)
K8s 底部使用 Linux 的 Cgroups 来管理 CPU:
- Requests 对应 cpu.shares:定义了在 CPU 繁忙时,进程能分到的权重。
- Limits 对应 cpu.cfs_quota_us:定义了硬上限。
对齐带来的改变:
- 确定的 CPU 权重:当 requests 调大后,该 Pod 在内核调度器中的 cpu.shares 权重会显著增加。在系统 CPU 繁忙、多个进程"打架"时,内核会分配给你的 Pod 更多的时间片。
- 减少 CPU Throttling(节流):虽然 limits 没变,但因为 requests 变大了,节点上不会超量挤入太多"邻居"。你的 Pod 更有可能实时拿到所需的 CPU 周期,从而减少因触发 CFS 配合限制而产生的延迟抖动(Tail Latency)。
3. 避免"喧闹邻居" (Noisy Neighbor) 效应
如果 requests 设得很小(例如 0.5 核),而 limits 设得很大(例如 4 核):
- 平时你的 Pod 可能会跑在 4 核上(因为邻居在睡觉)。
- 一旦邻居醒了开始抢资源,由于你的 requests 只有 0.5,内核会强制把你切回到 0.5 的水平。这种剧烈的性能跌落对核心业务(如石墨的实时协作)是致命的,会导致用户感知的卡顿。
- 对齐后:你从物理上锁定了这部分资源,邻居无法抢走你的"保底"份额。
4. 潜在风险与代价
- 资源利用率下降:这是最大的代价。由于 requests 占满了,即使你的服务在低峰期不怎么用 CPU,这部分资源也无法分给别的 Pod,导致集群整体的"装箱率"降低。
- 调度失败风险:如果你的 requests 调得太大,可能会出现节点剩余空间不足,导致 Pod 处于 Pending 状态无法启动。
建议操作:
- 分批调整:先调整最核心、对延迟最敏感的服务(如消息同步、实时编辑)。
- 监控 CPU Throttling:调整后,利用 Prometheus 观察 container_cpu_cfs_throttled_seconds_total 指标。如果这个值下降,说明优化有效。
- 配合 CPU Manager (可选):如果你的节点开启了 Static 策略的 CPU Manager,Guaranteed 级别的 Pod 还可以获得 独占 CPU 核心(Exclusive CPUs) 的能力,彻底消除上下文切换带来的损耗。
总结: 对于核心服务,"空间换时间" 是值得的。将 requests 对齐 limits 是解决 vCPU 抢占、降低请求延迟最直接且有效的手段。