很多团队把 Kubernetes 集群的成本问题归结为「节点买多了」,但真正造成浪费的往往是另一类现象:资源申请值拍脑袋填、HPA 阈值形同虚设、长期没人看的测试工作负载一直在跑。Kubernetes 的成本治理本质上是把“看不见的浪费”变成“看得见的账”。

一、第一步:把成本拆到团队和业务
集群总账单没法指导任何决策。真正有用的粒度是“每个命名空间 / 每个团队 / 每个应用每月花了多少”。实现路径通常是:按节点价格把单节点成本算出时价,再根据各工作负载的 requests 占比做加权分摊。
这里有个常见的错位:分摊应该按 requests 而非实际用量。因为调度器是按 requests 分配资源的,requests 才是真正占用集群容量的东西。只按实际 CPU 用量分摊,会让申请了 4 核、实际只用 0.2 核的服务看起来“很便宜”。
二、第二步:把 requests 从玄学变成数据
大部分集群的资源利用率偏低,根源是 requests 设置过大。三个具体做法:
- 用历史监控数据反推:取过去 14 天的 P95 用量作为 requests 初值,而不是凭经验填。
- 区分 requests 与 limits:requests 决定调度,limits 决定上限。CPU 的 limits 设置过高意义不大(可压缩资源),但内存的 limits 必须设,否则节点级 OOM 会连带影响其他 Pod。
- 引入 VPA 的 recommend 模式:只让它给出建议值、不自动改,观察一段时间再逐步收紧,风险可控。
三、第三步:弹性伸缩要分层看
Kubernetes 的弹性有三层,很多团队只做了中间一层,自然效果有限:
| 层级 | 机制 | 解决什么 |
|---|---|---|
| Pod 级 | HPA | 业务负载波动,按 CPU/QPS/自定义指标扩副本 |
| 节点级 | Cluster Autoscaler / 节点池 | Pod 没地方调度时自动加机器,忙完后缩回 |
| 容量级 | 定时伸缩 / 预留实例 | 应对可预测的周期性峰值,如大促、日终批处理 |
实践中最容易漏掉的是最后一层。如果业务有明显早高峰,仅靠 HPA 响应会滞后 1–3 分钟,且频繁扩缩本身也有成本。用 CronHPA 提前把副本数拉高,反而比 HPA 更稳定、更省钱。
另一个细节:HPA 的缩容冷却时间不要设得太短。指标刚回落就立刻缩容,会紧接着因为流量回升再扩容,形成抖动。一般建议扩容冷却 1 分钟、缩容冷却 5 分钟。
四、第四步:处理那些“不值钱但很贵”的工作负载
以下几类资源几乎在每个集群里都存在,清理收益立竿见影:
- 长期无人访问的测试环境:可以设为夜间自动缩容到 0,工作时间再拉起。
- 未挂载的 PVC:块存储按容量计费,没人用的卷一直在花钱。
- 过大的镜像与副本数:无状态服务动辄 10 个副本、每个 requests 2 核,先确认峰值 QPS 是否真的需要。
- 游离的 LoadBalancer 类型 Service:每个都会产生一笔固定费用。
五、把治理变成机制,而不是运动
一次性优化能省 20%–30%,但半年后往往又涨回去。可持续的做法是建立三条机制:成本看板向团队公开、新服务上线时 requests 必须附监控依据、每月一次资源利用率异常review。
成本治理的终点不是“花得最少”,而是“每一分钱都能解释清楚”。当团队能回答“这个服务为什么需要 8 核”时,治理就真正落地了。
