Kubernetes 自动伸缩与成本优化实战:我踩过的坑和最终方案
结论:自动伸缩不是万能药,组合使用 HPA、VPA 和 Cluster Autoscaler 并配合成本监控,才能真正省钱又省心。
1. 为什么自动伸缩反而让成本飙升?

我接手过一个项目,团队已经配置了 HPA(水平 Pod 自动伸缩),但月底账单出来时,成本比预期高了 40%。分析后发现:
- HPA 基于 CPU 使用率触发,但业务高峰只是短暂的,伸缩后 Pod 数量一直维持在高位
- 没有设置最小/最大 Pod 限制,导致无限制扩容
- 节点数没有自动缩减,Cluster Autoscaler 配置不当
核心教训:自动伸缩不是“自动省钱”,而是“自动调整资源”。省钱需要额外的策略。
2. 实战配置:HPA + VPA + Cluster Autoscaler 三件套
2.1 水平自动伸缩(HPA)—— 最基础也最容易出问题
我的典型配置:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web-app
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 70
behavior:
scaleDown:
stabilizationWindowSeconds: 300 # 5分钟稳定窗口
policies:
- type: Percent
value: 50
periodSeconds: 60
scaleUp:
stabilizationWindowSeconds: 60
踩坑点:
- 只配 CPU 指标:内存突增时不会扩容,导致 OOM
- 稳定窗口太短:频繁扩缩容,Pod 重建开销大
- 缩容策略太激进:突然缩掉大量 Pod,影响用户体验
注意:behavior 字段是 v2 API 的关键,务必配置稳定窗口,避免“震荡”。
2.2 垂直自动伸缩(VPA)—— 小心重启
VPA 用于调整 Pod 的 CPU/内存请求和限制。我踩过的坑:
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: web-app-vpa
spec:
targetRef:
apiVersion: "apps/v1"
kind: Deployment
name: web-app
updatePolicy:
updateMode: "Auto" # 自动模式会导致 Pod 重启
resourcePolicy:
containerPolicies:
- containerName: '*'
minAllowed:
cpu: 100m

memory: 100Mi
maxAllowed:
cpu: 2
memory: 2Gi
controlledResources: ["cpu", "memory"]
血泪教训:
- updateMode: "Auto" 会重启 Pod 来应用新资源限制,导致服务中断
- 对于无状态服务,使用 Initial 模式,只在 Pod 创建时调整
- 必须设置 minAllowed 和 maxAllowed,否则 VPA 可能给 Pod 分配过大资源
我的建议:VPA 主要用于“推荐”而非“自动调整”。先用 Off 模式收集建议,再手动调整。
2.3 Cluster Autoscaler —— 节点层面的省钱关键
这是最容易被忽视的部分。配置:
# 安装 Cluster Autoscaler(AWS EKS 示例)
helm install cluster-autoscaler autoscaler/cluster-autoscaler \
--namespace kube-system \
--set autoDiscovery.clusterName=my-cluster \
--set awsRegion=us-west-2 \
--set rbac.create=true \
--set podPriorityThreshold=-10
关键参数:
- --scale-down-enabled=true:默认开启
- --scale-down-delay-after-add=10m:节点添加后等待 10 分钟再考虑缩容
- --scale-down-unneeded-time=10m:节点空闲 10 分钟后缩容
- --max-node-provision-time=15m:节点启动超时时间
踩坑:
- 节点组配置了 spot 实例,但没设置 nodeSelector,导致关键服务被调度到 spot 节点,被回收时中断
- 没有配置 podDisruptionBudget,缩容时 Pod 被强制删除
3. 成本优化实战策略
3.1 预留实例 + Spot 混合
我的节点组配置:
# 节点组 A:预留实例,运行关键服务
nodeGroups:
- name: on-demand-group
instanceType: t3.medium
minSize: 2
maxSize: 10
labels:
workload-type: critical
# 节点组 B:Spot 实例,运行批处理任务
- name: spot-group
instanceType: t3.medium
spotInstancePools: 4
spotAllocationStrategy: "capacity-optimized"
minSize: 0
maxSize: 20
labels:
workload-type: batch
taints:
- key: "spot"
value: "true"
effect: "NoSchedule"
部署时使用 nodeSelector 和 tolerations:
apiVersion: apps/v1
kind: Deployment
metadata:
name: batch-processor
spec:
template:
spec:
tolerations:
- key: "spot"
operator: "Exists"
effect: "NoSchedule"
nodeSelector:
workload-type: batch
3.2 成本监控:用 Kubecost 看清每一分钱
安装 Kubecost:
helm install kubecost kubecost/cost-analyzer \
--namespace kubecost \
--set kubecostToken="your-token" \
--set prometheus.nodeExporter.enabled=false
关键指标:
- 集群成本:按命名空间、Deployment、Pod 查看
- 闲置资源:查看未被使用的 CPU/内存
- Spot 使用率:检查 spot 节点利用率
我从 Kubecost 发现的典型问题:
- 某个命名空间占用了 60% 的集群资源,但实际流量只有 5%
- 开发环境有 30 个 Pod 处于 Running 但无流量状态
- 某个 Deployment 的 requests 设置过高(2 CPU 但实际只用 0.1)
3.3 成本优化三板斧
第一板斧:设置资源配额
apiVersion: v1
kind: ResourceQuota
metadata:
name: dev-quota
namespace: dev
spec:
hard:
requests.cpu: "10"
requests.memory: 20Gi
limits.cpu: "20"
limits.memory: 40Gi
count/pods: 50
第二板斧:使用 LimitRange 强制限制
apiVersion: v1
kind: LimitRange
metadata:
name: default-limits
namespace: dev
spec:
limits:
- max:
cpu: "2"
memory: 2Gi
min:
cpu: "0.1"
memory: 100Mi
default:
cpu: "0.5"
memory: 512Mi
defaultRequest:
cpu: "0.2"
memory: 256Mi
type: Container
第三板斧:定期清理闲置资源
我的脚本(每周运行):
#!/bin/bash
# 查找 7 天内没有流量的 Pod
kubectl get pods --all-namespaces -o json | jq -r '
.items[] | select(.metadata.creationTimestamp < (now - 7*86400)) |
.metadata.namespace + "/" + .metadata.name
' | while read line; do
echo "检查闲置 Pod: $line"
# 这里可以检查日志或监控指标
done
4. 最终效果
实施上述方案后,我的集群成本变化:
- 节点数:从 15 个降到 8 个(节省 46%)
- Pod 密度:从平均 3 Pod/节点提升到 6 Pod/节点
- Spot 使用率:从 0% 提升到 35%
- 月度成本:降低约 40%
5. 延伸思考
- GPU 场景:对于 ML 训练任务,HPA 不适用,考虑 KEDA 基于队列长度伸缩
- 无服务器方案:考虑 Karpenter(比 Cluster Autoscaler 更智能的节点自动伸缩)
- 成本模型:不只是看云厂商账单,还要考虑运维成本(Pod 重建、服务中断)
最后一句:自动伸缩是工具,成本优化是目标。别让工具控制你,而是要驾驭工具。

评论已关闭!