Kubernetes容器资源优化通过调整CPU/内存请求,降低成本,提高效率。VPA或托管工具(如nOps)可实现。通过调度策略(非高峰优化、工作时间冻结、高峰回滚),平衡优化与可靠性,实现可控的持续资源调整。
译自:From Guesswork to Guardrails: Kubernetes Container Rightsizing
作者:Shouri Thallam
在 Kubernetes 集群中,CPU 和内存请求既是成本拨盘,也是可靠性拨盘。它们是您告诉调度器 Pod“需要”什么的方式,也是节点自动扩缩器和水平 Pod 自动扩缩器 (HPA) 在决定是否增加容量或副本时所依据的反应。
问题在于请求会漂移。它们可能在早期开发或过去流量模式下设置,然后工作负载演变,而这些数字却没有变化。没有人希望永远手动调整请求,但在错误时间重写资源的成本工具可能会更糟。因此,资源优化显然很有价值,但在没有防护措施的混合生产集群中持续运行却很困难。
什么是容器资源优化及其回报
容器资源优化是指调整 CPU 和内存请求(以及在适当情况下,限制)的做法,使其与实际使用情况匹配,而非历史猜测。当请求被夸大时,Kubernetes 会预留从未使用过的容量。您会失去 Pod 密度,调度器比预期更快地耗尽“空间”,并且集群会根据声明的需求而非实际负载进行扩容。
这转化为更多的节点和通常更大的实例类型,因为较小的节点无法适应您请求的形状。在更大的环境中,少数几个过大的“鲸鱼”容器甚至可能推动上游基础设施变更——额外的节点池、更大的子网、更多的 VPC/IP 预留空间——却只是为了托管闲置容量。资源优化将该基准拉回现实,从而提高打包效率,减缓节点增长,并使自动扩缩器根据清晰的信号而非资源规模欠债运行。
从何开始:自定义方法与托管路径
如果您想使用原生工具来完成此操作,通常的入门是垂直 Pod 自动扩缩器 (VPA)。在推荐模式下,VPA 根据观察到的 CPU 和内存历史记录为您提供每个容器的请求建议。一些团队会定期审查这些数字并通过 GitOps 差异应用它们;另一些团队则将 VPA 与生成拉取请求 (PR) 或 YAML 补丁的开源资源优化工具结合使用。更 DIY 的路线是从 Prometheus 抓取指标,在脚本中计算新的请求,然后通过 cron 应用它们,通常会有人工参与循环来批准敏感命名空间的更改。这些方法是获得初步节省的合法途径,并且通常足以满足低风险服务或可预测的批处理工作负载。
差距在规模化时出现。VPA 和大多数开源工具侧重于 改变什么,但它们不处理 何时 应用更新、哪些 工作负载可以安全地自动触及或 如何 避免与发布和自动扩缩器发生冲突。
像 nOps 这样开箱即用的生产级调度工具基于与 VPA 相同的底层思想(基于使用情况的推荐),但叠加了调度和防护措施,使更新仅在批准的窗口内进行。这些工具还将回滚和操作历史记录附加到每次调整大小,这是团队一旦尝试在生产中广泛运行资源优化后,否则最终需要自行连接的部分。
工作负载和容器资源优化模式
只有当您了解要调整大小的工作负载类型时,调度才有意义,因为不同的工作负载需要不同的请求基准和不同的应用更改时机。下表是一个快速模式映射,用于在深入调度策略机制之前确定这些差异。
| 模式 | 特点 | 优化方法 |
|---|---|---|
| 稳定工作负载 | CPU/内存使用情况一致 | 请求使用 P90 或 P95 使用率。限制保持接近。 |
| 突发性服务(API、前端) | 大部分时间空闲,突然出现高峰 | 请求使用 P50/P70 + HPA 用于突发。更高的 CPU 限制。 |
| 渐进增长(CRON、工作器、流处理) | 内存随时间逐渐增加(泄漏/状态) | 使用峰值内存 → 请求 = 峰值 + 10-20%。对持续增长添加警报。 |
| 空闲守护进程/Sidecar | 持续低使用率但预留资源大 | 积极进行资源优化或合并/移除 Sidecar。 |
| 短生命周期作业/批处理 | CPU 突发,内存启动时可预测 | 基于容器最大使用率进行优化。考虑资源 QoS:BestEffort/Burstable。 |
| 未知新工作负载 | 无基准 | 从高开始 → 测量 → 迭代式向下调整。 |
基于工作负载的资源优化
跨这些模式进行资源优化显然很有用,但它也暴露出真实的犹豫和摩擦,即在运行中的集群中不断更改请求,以及它们如何与他们已经信任的发布、值班和其他控制措施保持一致。
一旦推荐存在,执行时机与优化本身一样重要。调度允许您定义资源优化可以执行的时间和范围,之外的一切都保持只观察模式。这归结为三个实际选择:何时应用更改、何时阻止更改以及高峰期与非高峰期是否运行不同的配置。以下策略是常见的生产默认设置。
1. 仅在周末/非高峰时段进行资源优化
工作负载在周二下午 2 点与周六凌晨 3 点的行为不同,因此一个常见的安全默认设置是仅在低流量时段应用资源优化。这会将 Pod 重启和任何自动扩缩器副作用推迟到影响范围最小的时期,并留出时间在高峰负载返回之前验证稳定性。
例如,团队可以从周末时段(例如当地时间周六 00:00 至周日 06:00)或集群测量的最低流量时段开始。
有几种标准方法可以强制执行非高峰期门控:
- Argo CD/Flux 计划的 GitOps 同步: 资源优化建议成为常规的 YAML/overlay 更新,但 Argo/Flux 设置为仅在该窗口期间同步这些差异,以便更改保持可审查,并且 Git 仍然是事实来源。
- Kubernetes CronJob + Kustomize/Helm 补丁: CronJob 仅在该窗口内运行,拉取最新的建议并直接修补请求——这是一种轻量级的集群原生批处理机制,无需 GitOps 门控。
- 计划的资源优化自动化: 资源优化器持续计算建议,但在内部强制执行应用窗口,在同一系统中处理目标定位和回滚,而不是自行连接该控制层。
2. 工作时间冻结资源优化
这种方法与非高峰期批处理的逆向操作:继续生成建议,但在高峰时段阻止任何请求/限制写入。目的是避免在用户流量和发布活动最高时,由于调整大小导致的重启或自动扩缩器比例变化。
一个常见的起始规则是工作日拒绝窗口(例如,当地集群时间周一至周五,上午 8 点至下午 6 点),通常仅应用于对延迟敏感的命名空间。
| 工作时间风险 | 为何重要 |
|---|---|
| 流量和负载更高 | 任何重启或重新调度都会立即对用户产生影响。 |
| 错误检测更困难 | 高峰期的可变性使得资源调整回退更难快速发现。 |
| SRE/基础设施可用性较低 | 更长的回滚周期增加了错误更改的成本。 |
实际不变式很简单:在允许的窗口之外,资源优化可以观察和推荐,但它不会应用。
3. 高峰时段自动回滚
此策略假设您不想要一个“永久”的请求基准。相反,您在非高峰期运行一个优化的基准,然后在高峰期回滚到已知的保守基准。这是持续调整和完全冻结之间的中间地带。您仍然定期获得节省,但避免在一天中最繁忙的时段使用新的、可能过于激进的请求,这对于具有不可预测高峰行为的服务最为重要。
实际上,调度很简单:在晚上或周末应用最新的建议,然后在流量增加之前恢复先前的“安全”配置。
这最适合那些具有可靠空闲时段但高峰期突发或难以预测的工作负载,您希望在非高峰期获得成本优势,而无需将高峰期的可靠性押注在新计算的请求上。机械上,回滚只是一个计划的配置文件切换,通常通过在“优化”和“基准”GitOps overlay 之间切换来完成,或者是在窗口关闭时恢复基准请求的 CronJob,或者是一个支持计划回滚的资源优化器。
结果和验证
一旦调度和防护措施到位,最后一步是证明资源优化使系统变得更好。结果通常涵盖三个维度:成本、可靠性和运维。
| 维度 | 示例指标 | 目的 |
|---|---|---|
| 成本 | 优化百分比,每服务每天美元成本,利用率变化 | 量化效率提升,区分持续节省和短期噪音。 |
| 可靠性 | SLO 燃烧率,延迟 p95/p99,OOMKill 频率,自动扩缩器抖动 | 确认优化没有造成退化或触发扩缩波动。 |
| 运维 | 恢复时间,部署差异持续时间,自动化成功率 | 衡量资源优化在计划窗口内执行和恢复的一致性。 |
为了准确解释结果,比较相同的工作负载周期——相同的周几和小时——以消除自然的流量差异。当可逆性是自动的,并且回退会触发即时回滚时,资源优化就变成了一个可审计的控制循环,通常每 30 到 60 天重新运行一次。
nOps 中的调度:它如何映射到上述模式
我将计划的资源优化描述为推荐引擎之上的控制层:选择合格的目标,定义窗口,并决定“窗口外”行为应该是什么。
我的公司 nOps 在其容器和工作负载资源优化功能中直接实现了该模型。调度层不会改变建议的计算方式;它限制了它们何时可以应用以及在窗口外发生什么。建议继续根据观察到的使用情况更新,但调度会控制何时将这些更新写回请求/限制。
范围:您可以调度什么
nOps 中的调度可以在不同的范围应用,具体取决于您的集群是如何组织的:
工作负载资源优化调度 针对类似作业或计算密集型工作负载(批处理、ETL、分析、Spark 风格的管道)。预期是可预测的运行/空闲周期,因此调度通常与这些阶段保持一致。
容器资源优化调度 针对长时间运行的服务和部署,其中时机很重要,因为调整大小会重启 Pod 并影响自动扩缩器比例。
在这两种情况下,调度都附加到显式目标(集群、命名空间、部署或容器组),而不是默认在整个集群范围内运行。这与前面描述的“定位正确的工作负载”方法相匹配。
窗口和执行行为
调度定义了一个或多个允许资源优化执行的时间窗口。在窗口内,资源优化可以根据当前建议应用新的请求/限制。在窗口外,nOps 支持两种行为,它们对应本文中的执行模式:
- 保持模式: 在窗口外,配置保持固定。建议可能继续计算,但在下一个计划运行之前不会推送任何更新。
- 回滚模式: 当窗口关闭时,nOps 恢复上次已知的基准配置。这适用于您希望在低流量期间进行临时优化,但需要一个可预测的峰值前基准的情况。
重要的机制点在于调度控制的是更改的应用,而不仅仅是建议的生成。
与扩缩和发布的协调
由于资源优化会更新请求,它可能会改变水平 Pod 自动扩缩器 (HPA) 使用的利用率比率,并可能触发节点自动扩缩器响应的重新调度。调度是 nOps 用来减少这些重叠的机制:您在避免发布活动和自动扩缩器稳定期的窗口内运行调整大小,并在流量高时保持关键服务的稳定。这与“性能和冲突处理”部分描述的相同顺序防护措施。
采用路径
实际的推广路径看起来像前面概述的分阶段方法:
- 从狭窄的目标开始(一个命名空间或一个低风险的部署类别)。
- 设置一个保守的非高峰期窗口。
- 观察对重启、延迟和自动扩缩器行为的影响。
- 一旦结果稳定,扩展目标或窗口。
nOps 保留已应用的资源优化操作的历史记录,因此团队可以追踪调度何时执行以及它们更改了什么,这有助于在推广范围扩大时进行验证和回滚决策。
总结
计划的资源优化是一种使资源调优行为与您的其他生产控制保持一致的方法:有范围、有时间限制且可逆。您不再需要将 CPU 和内存基准视为仅在成本飙升或发生事故时才重新审视的东西,调度允许您以与每个服务运行方式相匹配的节奏,使其与工作负载的实际情况保持一致。最终结果是,您获得了资源优化的效率优势,而无需要求每个工作负载都承受相同水平的自动化风险。在持续调优安全的情况下,让它运行;在稳定性更重要的情况下,保守地进行调度;在两者都不适用的情况下,让工作负载保持原样。