Kubernetes 成本优化完全指南:削减 30-60% 账单的实战手册
Kubernetes 已经成为现代云原生平台的事实标准,但伴随它的是难以察觉的资源浪费。FinOps 基金会 2025 年的调查显示,平均 K8s 集群有 32% 到 65% 的 CPU 与内存处于已分配但未使用状态,这些钱安静地流入云厂商的账户。换句话说每跑一千万元的 K8s 账单,至少有三百万到六百万元是可以省下的。本文从 request 与 limit 设置、Horizontal Pod Autoscaler(HPA)、Vertical Pod Autoscaler(VPA)、Cluster Autoscaler 与 Karpenter、Spot 实例、Namespace 配额与 LimitRange、Kubecost 与 OpenCost 监控、治理与 FinOps 流程八个维度系统讲解 K8s 成本优化的工程方法,并附几个真实削减 30% 到 60% 账单的案例。无论你的集群在 AWS、阿里云、腾讯云还是自建机房,原则都通用。
资源请求与限制:浪费的源头
每个 Pod 都需要声明 resources.requests 与 resources.limits。requests 是调度器分配资源的依据,limit 是实际能用的上限。许多团队直接把 requests 设得很大以"保险起见",这等于让调度器看到的可用资源大幅缩水,节点利用率压根上不去。最常见的反模式是 requests 与 limit 设成同一个高值(QoS Guaranteed),结果 Pod 永远占着没用的资源。
合理做法是根据真实历史数据设置 requests。Prometheus 已记录至少两周数据的服务,用 P95 或 P99 内存与 CPU 真实使用值乘以 1.1 到 1.3 作为 requests,limit 适度放大到 1.5 到 2 倍以容纳突发。CPU 通常不设 limit 或设较高,因为 CPU 限流(throttling)对延迟极敏感;内存必须设 limit 否则会拖垮整个节点。VPA 的推荐模式(updateMode: Off)能定期给出建议值,运维只需要每月校准一次。
要注意的是 JVM、Go、Node.js 等运行时对容器内存语义有不同处理。JVM 早期不感知 cgroup 内存,需要 -XX:+UseContainerSupport 与 -XX:MaxRAMPercentage;Node.js 需要 --max-old-space-size;Python 没有限制,OOMKill 后 K8s 直接重启。把内存留出 10% 到 15% 给运行时本身的非堆区域,是减少 OOMKill 同时不浪费的关键经验。
HPA 与 VPA:弹性伸缩的两大武器
Horizontal Pod Autoscaler 根据指标自动调整副本数,是最被广泛采用的弹性手段。最简单的版本基于 CPU 平均利用率,比如目标 70% 时高于这个值就扩容。Custom Metrics 让 HPA 用业务指标驱动,例如每秒请求数、Kafka 消费延迟、SQS 队列长度。KEDA 把外部数据源作为伸缩依据,是事件驱动场景的事实标准。
Vertical Pod Autoscaler 在 Pod 维度调整 requests 与 limits。它有三种模式:Off 仅给推荐值、Initial 在 Pod 创建时设置、Auto 自动重启 Pod 应用新值。Auto 模式风险较大,业内更多在 Off 模式下读取推荐值,再人工或 GitOps 应用,避免半夜全量重启。最近社区开始流行"VPA 提建议、HPA 做执行"的组合策略,两者各管一边。
HPA 与 VPA 不能基于同一指标共存,会出现互相打架。常见实践是 HPA 用 CPU 或业务指标横向扩,VPA 仅用于内存的优化。对于无状态服务,HPA 优先;对于有状态或大模型推理服务,VPA 更合适。无论用哪种伸缩,都要避免"伸缩抖动":HPA 默认 stabilizationWindow 已经是 5 分钟,仍可能因瞬时流量波动反复扩缩,需要根据应用特性调整。
Cluster Autoscaler 与 Karpenter
集群级伸缩负责动态增减节点。传统方案 Cluster Autoscaler 监听 Pending Pod,从预先定义好的 Node Group 中扩容;缺点是只能从已有 InstanceType 中选,扩容速度也较慢,往往需要 1 到 3 分钟。Karpenter 是 AWS 推出后被 CNCF 接管的下一代方案,不依赖 Node Group,直接根据 Pod requests 智能选择最便宜实例,扩容速度可降到 30 到 60 秒。
Karpenter 的核心优势是 bin packing 与实例多样性。它会把多种实例类型放进 Provisioner 池,按总价排序,并自动 consolidate 把碎片化负载合并到更少节点。一个真实案例:某出海电商团队从 Cluster Autoscaler 切换到 Karpenter,节点数从平均 220 降到 130,月账单减少 38%。
阿里云 ACK、腾讯云 TKE 也都有自家版本的弹性伸缩组件,原理类似但 API 与实例类型本地化。无论用哪种方案,都要把节点选择策略与 Pod 的拓扑分布约束(topologySpreadConstraints)结合,避免所有副本被打到同一区。否则节省了成本却牺牲了高可用,得不偿失。
Spot 实例:最大化折扣的双刃剑
Spot Instance(GCP 称 Spot VM、阿里云抢占式实例)以远低于按需价格提供算力,AWS 平均能省 70%、阿里云 60% 到 90% 不等。代价是云厂商可在两分钟通知后回收实例。Kubernetes 的天然容错让它非常适合驱动 Spot:节点被回收时 Pod 重新调度,整体业务不感知。
实施 Spot 的最佳实践包括:用 Karpenter 或 Spot Termination Handler 监听回收事件并优雅迁移;用多个 InstanceType 与多 AZ 分散回收风险;为 Spot 节点打标签,并用 nodeSelector 把无状态服务调度上去;保留 20% 到 30% 按需节点作为 baseline,承载关键 Pod。批处理、CI/CD、机器学习训练、缓存副本是 Spot 的甜区,数据库主节点与单点状态服务要避开。
实际收益看比例。某游戏团队把 60% 的玩法验证服务迁到 Spot,整体月计算成本从 18 万元降到 9.6 万元,降幅 47%。最早期会有几天的"调教阵痛"——回收时间、AZ 分布、PDB(PodDisruptionBudget)参数都需要打磨——但稳定后维护成本几乎为零。
Namespace Quota 与 LimitRange:组织级护栏
ResourceQuota 限制 Namespace 内 CPU、内存、Pod 数、PVC 大小的总量;LimitRange 设置单个 Pod/Container 的默认值与最大最小边界。这两个对象最容易被忽视,但它们是大组织成本治理的护栏:没有 Quota,每个团队都能无限申请,账单自然失控。
实战中可以用三层结构:平台层定义 ClusterRole 与 LimitRange 默认值,业务部门维护 Namespace 级 ResourceQuota,团队在自己的 Namespace 内自由调度。配合 Kyverno、OPA Gatekeeper 等策略引擎,可以做到"未声明 requests 的 Pod 直接拒绝",强制好习惯。结合 GitOps 把 Quota 放进 Git,每次扩容都走 PR 评审,自然就不会出现"一夜打到上限"的事故。
Quota 不是简单卡死,而是配合监控让浪费可见。当某 Namespace Quota 长期使用率不足 30%,就该缩减;高于 80% 就该加额。把这些指标接到 Grafana 看板,每月做一次"Quota Review",优化成本立竿见影。
Kubecost 与 OpenCost:让浪费可见
看不见就管不住。Kubecost 与 OpenCost 是 K8s 成本归因的事实标准。OpenCost 是 CNCF 沙箱开源版,提供 Pod、Container、Namespace、Workload、Label 等多维度的成本拆分。Kubecost 是商业增强版,加入了网络成本、跨集群聚合、长期数据存储、Savings Insights 自动建议、Allocations Reports、API 与多租户。
部署 Kubecost 通常用 Helm Chart,10 分钟可以跑起来。它会从云厂商 Pricing API 拉单价、从 Prometheus 拉资源使用、从 Kubernetes API 拉 Workload 元数据,然后做成本分摊。你能看到"App A 上周花了 1234 元,其中 65% 是 CPU、20% 是内存、15% 是 PV"。这种可见性是后续所有优化决策的基础。
云厂商现在也都自带集成。AWS Cost and Usage Report 可以按 Tag 拆分,EKS 已支持 Cost Insights;GKE 内置 Cost Allocation;AKS 提供 Cost Analysis 视图;阿里云、腾讯云也支持工作负载级成本归因。开放标准如 FOCUS(FinOps Cost and Usage Specification)让多云账单整合越来越容易。建议从一开始就给所有 Workload 打统一的标签:team、service、env、cost-center,方便后续按业务维度归因。
真实案例:30% 到 60% 削减背后的事
案例一:某电商中台团队,月 K8s 账单 80 万元。第一阶段排查 requests 设置不合理,结合 VPA 推荐与 P95 真实数据,调整 60% 服务的 requests/limits,节点数从 180 降到 120。第二阶段引入 Karpenter 替换 Cluster Autoscaler,并把无状态服务迁到 Spot 实例。两个月后月账单降到 32 万元,降幅 60%。
案例二:某 SaaS 公司面向欧美客户,K8s 在 AWS 上跑,月账单 50 万人民币。引入 Kubecost 后发现两个零流量但仍在跑的开发集群每月花费 8 万元,立即关闭。然后把 30% 批处理任务迁到 Spot,加上 PV 从 gp2 升级到 gp3 节省存储费。三个月后月账单降到 35 万元,降幅 30%。
案例三:某 AI 推理平台,GPU 节点占整体 70% 成本。优化重点是 GPU 共享与时间复用:用 NVIDIA MIG 把 A100 切成多份,结合 KEDA 按队列长度伸缩。再把开发与训练任务调度到 Spot GPU,生产推理保留按需。半年内月账单从 240 万元降到 110 万元,降幅 54%。这些案例的共同点:监控先行、迭代调优、把成本目标写进团队 OKR。
从优化到治理:FinOps 流程落地
技术手段只能解决一时浪费,长期看必须建立 FinOps 流程:周会评审 Top 浪费 Workload;月度 Quota Review;季度容量规划;年度 Reserved Instance 与 Savings Plan 决策。把这些写进运营手册,并指定专门的 FinOps Owner,跨研发、SRE、财务三方协作。
Showback 与 Chargeback 是治理的高级阶段。Showback 把成本以可视化报表分发给业务团队,让他们看到自己造成的开销;Chargeback 直接把成本计入业务部门预算,一旦花钱有真实痛感,浪费会大幅减少。许多互联网大厂在内部建立了"工程经济学"实践,把每个 Service 的单位经济(Cost per Request、Cost per User)量化到 OKR。
结语:Kubernetes 成本优化没有银弹,靠的是把 8 个维度逐一打磨。先建立可见性,再针对最大浪费下手,配合自动化工具与组织流程,30% 到 60% 的削减在大多数团队都能复现。最后提醒一句:不要为了优化而优化。永远把可用性与开发体验放在第一位,确认 SLO 不被牺牲后再砍成本。
常见问题
request 和 limit 应该怎么设置才合理?
常见做法是先用 VPA 推荐值或 P95 真实使用量乘以 1.2 倍作为 request,limit 设置为 request 的 1.5 到 2 倍以容纳突发,避免设置过紧导致 OOMKill。CPU 一般不设 limit 或设为较高值,因为 CPU 限流(throttling)对响应时间影响极大;内存必须设 limit。新服务上线前用压测得出基线,运行两周后再用真实数据校准,避免凭直觉设大值导致大量浪费。
HPA、VPA、Cluster Autoscaler 三者怎么配合?
HPA 横向扩缩 Pod 数量,最常用,基于 CPU、内存或自定义指标;VPA 纵向调整单 Pod 的 request/limit,适合无法横向扩展的服务;Cluster Autoscaler 在节点层根据 Pending Pod 增减节点。三者不能盲目叠加,HPA 与 VPA 同时作用同一指标会冲突,业内通常 HPA 走 CPU、VPA 走内存,或者只用 VPA 推荐模式辅助 HPA。Karpenter 比 Cluster Autoscaler 更智能,能直接挑选最便宜实例类型。
Spot 实例什么场景能用?
适合无状态、可重入、能在两分钟内优雅退出的工作负载:批处理任务、CI/CD 跑机、AI 训练、数据流水线、缓存层副本。不适合数据库主节点、单点服务、Stateful 长事务。生产中的稳健做法是 70% 工作负载跑 Spot、30% 跑按需作为底线,再用 Karpenter 或 Cluster Autoscaler 自动在 Spot 被回收时切换实例类型,最高可省 70% 计算费。
Kubecost 和 OpenCost 有什么区别?
OpenCost 是 CNCF 沙箱项目,由 Kubecost 团队开源,提供 Pod、Namespace、Workload 级的成本归因,免费但功能基础。Kubecost 是商业版,建立在 OpenCost 之上提供网络成本、跨集群聚合、报表、SLO 与告警、Savings Insights、长期数据保留与多租户管理。预算紧的团队从 OpenCost 起步,规模化后再升级 Kubecost;许多云厂商也基于 OpenCost 提供原生集成,例如 EKS、GKE、AKS 都能开箱看到工作负载级账单。
为什么实施了优化但账单没降?
常见原因有三:一是只优化了 CPU 与内存,但出口流量、负载均衡、PV 存储、跨可用区流量这些"非计算"占了一半以上账单;二是优化只覆盖了一个集群或一个 Namespace,整体浪费没动;三是优化收益被新业务增长抵消了。建议把成本归因到 Team/Service 层级,每周开成本评审会,把优化目标写进 OKR,账单才会真正下降。技术只是工具,治理流程才是关键。