别再无脑调大Request:K8s配额与成本优化手记
很多团队在 Kubernetes 上遇到性能问题,第一反应是把手里的 Request 调大:延迟高了加 CPU,OOM 了加内存,压测不过就翻倍。短期看像是“药到病除”,长期却把集群变成了一个昂贵的保险箱:节点越加越多,装箱率越来越低,配额越批越大,账单越来越难看。Request 不是许愿池里的硬币,它是调度器与成本系统之间的一份合约。本文结合 2026 年常见的多租户集群实践,聊聊如何用证据而不是直觉管理 Request、配额与成本。
一、问题不是“Request 太小”,而是“没有证据”
很多团队调大 Request 的动机可以理解:线上抖一下,先加 CPU;Pod 被 OOMKill,先把内存翻倍;压测没达标,先把配额批高。这样做在短时间内确实能降低故障概率,但它掩盖了一个更关键的问题——我们并没有说清楚资源到底被谁、在什么时间、以什么方式消耗掉了。没有指标支撑的调参,本质上是在用预算购买确定性。
Request 的本质是调度预留,不是实际使用量。调度器只看 Request 来决定 Pod 能不能放到某个节点上,节点上的实际 CPU 和内存使用率却可能远低于 Request。也就是说,Request 调大以后,即使业务负载没变,集群也会被迫预留更多容量,最终表现为节点数量增加、单节点装箱率下降、单位请求成本上升。你感觉“资源不够用”,可能只是“资源被预留得太散”。
更糟的是,Request 一旦普遍虚高,容量规划就会失真。扩容决策基于错误的基线,配额审批基于错误的用量,成本分摊也会把大量闲置容量算到业务头上。团队之间开始互相猜疑:平台说业务浪费,业务说平台不给资源。最后大家只能继续调大 Request,形成恶性循环。
正确的顺序不是先调大,而是先建立证据链:采集使用量、观察分位数、识别瓶颈类型、做小步变更、验证收益。Request 应该是被测量和校准出来的,而不是被焦虑推上去的。
二、把 Request 和 Limit 的账算清楚
Request 和 Limit 是两套完全不同的机制。Request 影响调度、QoS 和 HPA 的利用率分母;Limit 影响容器运行时的 cgroup 上限。CPU 是可压缩资源,超过 Limit 通常表现为限流和延迟上升;内存是不可压缩资源,超过 Limit 通常表现为 OOMKill。把两者混为一谈,就会得出“Request 等于 Limit 最安全”这种看似正确、实则昂贵的结论。
Kubernetes 的 QoS 分为 Guaranteed、Burstable 和 BestEffort。Guaranteed 要求所有容器的 CPU 和内存 Request 都等于 Limit,它适合延迟敏感、资源画像稳定的核心服务;Burstable 允许 Request 小于 Limit,适合大多数在线业务;BestEffort 不设置 Request 和 Limit,只适合可中断的批处理或测试负载。QoS 不是越高越好,Guaranteed 的代价是牺牲装箱弹性。
超卖也要分资源看。CPU 的 Limit 总和超过节点可分配量,通常是可以接受的,因为 CPU 可以按权重争抢;但内存 Limit 大幅超卖,就意味着节点随时可能触发系统级 OOM 或驱逐。一个常见的错误是:为了让 Pod 更容易调度,把内存 Request 压得很低,却把内存 Limit 设得很高。调度器以为节点还有空间,运行时却可能因为内存压力把整组 Pod 赶走。
可以用一个简单公式检查成本敏感度:节点成本约等于节点数量乘以单价乘以时间,而节点数量又由总 Request 和装箱率共同决定。假设一个 8 核 32GB 的节点,系统预留和 DaemonSet 占用 1 核 4GB,剩余 7 核 28GB。若每个 Pod Request 为 2 核 8GB,理论上只能放 3 个;若经过右 sizing 降到 1 核 6GB,则可能放 4 到 5 个。单 Pod 看似只降了一点,集群账单却可能下降三成。
三、配额不是“越大越安全”,而是预算合约
Namespace 级的 ResourceQuota 经常被当成“防事故的保险丝”,于是团队习惯性申请一个很大的配额,觉得这样不会阻塞发布。但配额本质上是平台与业务之间的预算合约:它既约束资源占用,也约束成本预期。配额过大,业务会无意识地囤积 Request;配额过小,Pod 会长期 Pending,发布流程被卡死。
配额设计要和业务等级挂钩。核心服务可以保留合理缓冲,但缓冲必须有依据,例如按过去 14 天 P95 用量的 1.2 倍设置;离线任务可以使用更紧的配额,并配合优先级和抢占;测试环境则应该显著收紧,避免长期空跑。ResourceQuota 可以限制 requests.cpu、requests.memory、limits.cpu、limits.memory,也可以限制 Pod 数量、Service 数量等对象规模。不要只限制 Limit 而放开 Request,否则调度压力仍然存在。
LimitRange 是配额体系里的另一个关键工具。它可以为命名空间设置默认 Request 和 Limit,防止用户提交“裸 Pod”;也可以设置最大最小边界,阻止明显不合理的资源声明。实践中,平台团队应该把 LimitRange 当作兜底,而不是替代右 sizing。默认值只能保证“不至于完全没有”,不能保证“刚好合适”。
多租户场景下,还要区分“配额”和“实际分配”。配额是上限,不是预留;但很多团队会把配额当成已经到手的资源,导致平台整体超卖。更健康的做法是:配额按预算审批,实际容量按集群池化调度,再通过成本分摊把浪费可视化。配额管理的目标不是让每个团队都拿到一个大数字,而是让资源申请与业务价值匹配。
四、右 sizing 的闭环:指标、分位数、灰度
右 sizing 不是一次性动作,而是一个闭环。第一步是采集足够的指标:CPU 使用率、内存 working set、CPU 限流次数、OOMKill 次数、延迟分位数、错误率、副本数变化。只看平均值几乎没有意义,因为平均值会掩盖尖峰;至少要看 P95 和 P99,内存还要看峰值和增长趋势。观察窗口建议覆盖一个完整的业务周期,例如 7 到 14 天,大促类业务要单独标注。
第二步是区分瓶颈类型。CPU 高但限流不严重,可能只是计算密集;CPU 限流严重且延迟敏感,才需要考虑提高 CPU Limit 或 Request;内存持续上涨并伴随 OOMKill,要先排查泄漏和缓存策略,而不是直接翻倍;内存使用平稳但 Request 虚高,则可以下调。对于 Java 类服务,还要关注堆外内存、JVM 堆上限和容器 Limit 的关系,避免“容器没满、JVM 先崩”。
第三步是使用推荐工具但不要盲信。VPA 的 recommend 模式可以提供 Request 建议,OpenCost、Kubecost 等工具可以提供成本和利用率视图。推荐值要结合业务 SLO 人工复核,尤其是延迟敏感服务。对内存来说,Request 应覆盖稳定工作集和合理峰值,而不是压到平均值;对 CPU 来说,Request 可以接近 P95,Limit 根据是否允许限流来设置。
第四步是灰度变更。先改非核心服务或单个副本,观察一到两个业务周期;再逐步扩大。变更时要记录基线,否则事后无法判断收益来自右 sizing、流量下降还是缓存命中。一个可执行的规则是:每次调整不超过原值的 30%,并设置回滚阈值,例如 P99 延迟上升超过 10% 或 OOMKill 增加,就自动回退。
五、HPA、VPA、Cluster Autoscaler 的配合顺序
HPA 根据指标扩缩副本,但它计算利用率时用的是 Request 作分母。Request 虚高会让 HPA 误以为利用率很低,从而不扩容;Request 过低又会让 HPA 过度敏感,频繁抖动。所以 HPA 的前提是 Request 基本靠谱,并且指标采集稳定。HPA 还要配置合理的 stabilizationWindowSeconds 和扩缩容策略,避免流量尖峰后立刻缩容造成二次抖动。
VPA 负责调整 Pod 的 Request 和 Limit,但它和 HPA 存在天然冲突:两者都基于 CPU 或内存指标做决策,如果同时自动修改同一维度,就会互相打架。常见的分工是:HPA 管副本数,VPA 只给内存做推荐或自动调整;CPU 维度由 HPA 负责,VPA 保持 recommend 模式。对于延迟敏感服务,VPA 全自动调整要非常谨慎,因为重启 Pod 和改变资源上限都可能带来抖动。
Cluster Autoscaler 或 Karpenter 负责节点层扩容。它们看到的是“有 Pod 因为资源不足而 Pending”,所以 Request 的准确性直接影响节点池效率。Request 普遍虚高时,Autoscaler 会过早加节点;Request 过低时,节点可能过度装箱,运行时争抢严重。Karpenter 这类新一代节点自动扩缩容工具更强调实例形态选择和整合,但仍然依赖准确的 Pod 资源声明。
推荐顺序是:先用监控和 VPA 推荐做右 sizing,让 Request 接近真实需求;再用 HPA 处理副本层弹性;最后让节点自动扩缩容处理容量层弹性。三层各司其职,不要用节点扩容去弥补 Request 虚高,也不要用 VPA 去解决流量突增。
六、提高装箱率:调度策略与节点池
装箱率可以粗略理解为节点上已分配 Request 占可分配资源的比例。提高装箱率不等于把节点塞满,而是减少碎片和无效预留。常见手段包括按负载形态划分节点池:延迟敏感型、通用型、批处理型、Spot 型。不同节点池使用不同实例规格和调度策略,避免“一个大 Pod 卡住整个节点”的碎片问题。
调度策略要克制使用。亲和性与反亲和性可以提高可用性,但过强的反亲和会让 Pod 分散到大量节点,降低装箱率;拓扑分布约束也要设置合理的 maxSkew,否则可能为了高可用牺牲太多密度。对于无状态服务,可以适当使用 Spot 或抢占式实例,并配合 PDB、优雅终止和多可用区分布,把中断成本控制在可接受范围。
还要把“隐藏占用”算进去。DaemonSet、系统组件、Sidecar、Init Container、Pod Overhead 都会占用 Request。很多团队只优化业务容器,却忽略了日志采集、服务网格 Sidecar 和监控 Agent。一个 Sidecar 多 100m CPU、100Mi 内存,乘以数千个 Pod 就是一笔不小的预留。右 sizing 应该覆盖整个 Pod,而不是只看主容器。
碎片也是成本。大 Request 的 Pod 可能让节点剩下很多无法利用的小空隙;过多小 Pod 又会增加调度和管理开销。解决办法不是一味调小,而是让 Request 分布更贴近节点规格,例如把 7 核节点留给 1 核、2 核的 Pod,把大内存 Pod 放到大规格节点池。定期查看 Pending Pod 的原因和节点分配率,比拍脑袋调参更有效。
七、成本可视化与组织机制
成本优化如果只停留在技术层,很容易反弹。必须把成本可视化到团队和应用。第一步是统一标签:team、app、env、cost-center、owner。没有标签的资源,最终都会变成“公共成本”,没人认领。第二步是使用 OpenCost、Kubecost 或云厂商成本工具做分摊,区分已分配成本、实际使用成本和闲置成本。
在 2026 年,越来越多平台团队开始关注单位经济性,而不是只看总账单。例如每千次请求成本、每个活跃用户成本、每笔订单成本。总账单受流量影响很大,单位成本才能反映效率。把 Request 利用率、装箱率、闲置容量、Spot 覆盖率纳入月度复盘,比单次降配更有持续价值。
组织机制上,建议把配额审批和成本预算绑定。新业务申请配额时,要求给出请求量级、资源画像和回收计划;季度复盘时,对长期低利用率的配额进行回收或缩容。平台团队不要做“资源警察”,而要做“成本教练”:提供推荐值、变更窗口、回滚工具和收益看板,让业务团队愿意配合。
还要警惕“省小钱花大钱”。为了降低 Request 导致频繁 OOM 或延迟超标,最终损失可能远高于节点费用。成本优化的目标是提升资源效率,不是把资源压到极限。稳定性、交付速度和成本之间需要明确优先级,核心链路应该保留合理冗余。
八、一个可落地的 30 天行动清单
第一周做盘点。导出所有 Namespace 的 ResourceQuota、LimitRange 和 Pod 资源声明,找出 Request 与 Limit 差异过大、长期低利用率、没有标签、没有 Owner 的工作负载。用 kubectl top pod 和监控系统交叉验证,先圈出前 20% 的资源消耗者。不要一上来全集群改,先找收益高、风险低的标的。
第二周建立基线。为候选服务采集 14 天的 CPU P95、内存峰值、限流次数、OOMKill 和延迟分位数,形成一张右 sizing 建议表。建议表至少包含当前 Request、建议 Request、当前 Limit、建议 Limit、预计节省、风险等级和回滚方案。没有基线就不要改,否则无法证明效果。
第三周做试点。选择非核心但流量稳定的服务,按不超过 30% 的幅度调整,先改一个副本或一个可用区。观察延迟、错误率、OOMKill 和 HPA 行为,确认稳定后再扩大。同步调整 LimitRange 默认值,防止新 Pod 又回到旧习惯。对内存类调整要更保守,因为内存问题往往在高峰才暴露。
第四周固化机制。把右 sizing 纳入发布检查单,把配额审批和成本看板纳入月度运营,把 VPA 推荐、HPA 策略和节点池规则写成平台默认配置。最后复盘一次:节省了多少节点、装箱率提升多少、有没有稳定性回退。只有形成闭环,下一次才不会又回到“无脑调大 Request”。
九、常见误区与收尾
第一个误区是“Request 等于 Limit 最安全”。Guaranteed QoS 确实能减少争抢,但代价是失去装箱弹性,尤其在大规模集群里成本很高。第二个误区是“CPU 可以随便超卖,内存也可以”。CPU 超卖通常表现为限流,内存超卖可能直接触发 OOM 和驱逐,两者风险完全不同。第三个误区是“VPA 全自动就能省钱”。没有 SLO 约束和灰度机制的自动调整,可能把稳定性调没。
第四个误区是“成本优化就是降配”。真正的优化是让 Request 贴近需求、让配额匹配预算、让调度减少碎片、让弹性覆盖峰谷。降配只是其中一种手段,而且往往不是收益最高的手段。第五个误区是“配额越大越不会出事”。配额过大只会把问题推迟到账单和容量规划阶段,并不会消失。
Kubernetes 的资源管理是一门关于证据的工程。Request 应该来自监控和业务画像,配额应该来自预算和 SLO,成本应该来自可视化和组织机制。别再用调大 Request 来掩盖不确定性;先把账算清楚,再把策略写进平台,最后让每一次变更都能被验证。这样省下来的不只是节点费用,还有团队对容量决策的信任。