Kubernetes Tips:扩缩容不抖(HPA + VPA + Cluster Autoscaler)
把 requests 写对、HPA 行为调稳、VPA 做推荐、CA 能补容量,让扩缩容可预测而不是“抽风”。
扩缩容是一套“系统的系统”。如果你觉得它不稳,往往不是 HPA 这个功能不好,而是:
- requests 不准(分母错)
- 多个控制器在打架(HPA/VPA/发布/surge 同时发生)
- 集群容量层(Cluster Autoscaler/节点池)跟不上
这篇 tips 给一个可落地的稳定扩缩容思路。
三层扩缩容:先搞清楚谁负责什么
- HPA(Horizontal Pod Autoscaler):改副本数(replicas)
- VPA(Vertical Pod Autoscaler):改/推荐 requests(有些模式也能自动改)
- Cluster Autoscaler:改节点数(加/减节点)
想要稳定,需要三层对齐:指标、requests、容量与启动时间。
Step 0:requests 是地基(不写或写错,一切都不准)
很多扩缩容逻辑都以 requests 为基础:
- HPA 的 CPU utilization 常用:
当前 CPU / requests.cpu - 调度器靠 requests 放置 Pod
- Cluster Autoscaler 看到 Pod Pending 才会补节点(Pending 常由 requests 触发)
因此第一步永远是:所有容器都要有合理 requests。
HPA 基础例子(CPU 利用率)
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api
namespace: app
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api
minReplicas: 3
maxReplicas: 30
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
含义:
- 平均 CPU 接近 requests 的 60% 时保持稳定
- 高于 60% 倾向扩容,低于 60% 倾向缩容
但注意:如果 requests 不准,这个“60%”没有意义。
防止抖动:stabilization window 与 scaling policy
HPA v2 支持行为配置,用来避免“上上下下”:
behavior:
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Percent
value: 100
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 20
periodSeconds: 60
思路是:
- 扩容尽量快(应对突发)
- 缩容慢一点(避免流量小波动导致频繁缩容)
指标选择:CPU 不是万能
CPU 利用率适合:
- 典型无状态 Web/API
但对这些类型往往不准:
- 队列 worker(更适合 backlog/lag)
- 内存型服务(CPU 低但内存持续升)
- I/O 型服务(瓶颈不在 CPU)
更靠谱的做法是选择贴近业务负载的指标:
- 队列深度、消费滞后
- RPS/并发连接数
- 关键路径延迟(谨慎,避免反馈环)
结论:
用“能代表负载”的指标扩容,而不是只看资源消耗。
冷启动与 readiness:扩了也不一定立刻有用
扩容增 Pod,但 Pod 变成可用需要时间:
- 拉镜像
- 启动(JVM warmup、迁移、缓存)
- readiness 通过
如果启动慢,HPA 扩容再快也救不了峰值。
你可能需要:
- 提高
minReplicas - 提前预热镜像(节点缓存)
- 对启动慢服务加
startupProbe - 合理的 scaleUp policy
Cluster Autoscaler:容量层的关键
HPA 扩容后,如果节点不够,Pod 会 Pending。Cluster Autoscaler 需要能识别并补节点。
如果 CA 不工作,常见原因:
- affinity/nodeSelector 让 Pod 只能去不存在的节点池
- requests 太大,没有任何节点规格能容纳
- 节点池 max size/配额到顶
- PDB/约束导致缩容逻辑受限(与 scale-down 相关)
排查 Pending:
kubectl get pod -n <ns> | rg -n "Pending"
kubectl describe pod -n <ns> <pod> | rg -n "FailedScheduling|Insufficient"
VPA:即使只做推荐也很有价值
VPA 模式(按你们平台而定)通常有:
- Off:只推荐
- Initial:只在创建 Pod 时设置 requests
- Auto:自动调整 requests(可能带来重建/波动,需谨慎)
建议路径:
- 先 Off(观察推荐,校正 requests)
- 再 Initial(更安全的自动化)
- 最后再评估 Auto(按业务风险分层)
HPA + VPA 一起用:避免打架
如果 HPA 以 CPU utilization 扩容,而 VPA 频繁改 CPU requests:
- 分母变了,HPA 会突然改变判断
- 容易产生“看起来负载没变,但副本数在变”的现象
实践上常见组合:
- HPA 用 CPU 或业务指标控制副本数
- VPA 用来推荐/调整 内存 requests(或以 Initial 模式周期性更新)
内存扩缩容要谨慎
HPA 也能按内存指标扩缩,但内存通常是滞后指标:
- 缓存增长导致内存上升,但扩容并不一定能立刻缓解
- 缩容后缓存重建反而变慢
更常见的稳妥方式:
- HPA 按 CPU/RPS 扩容
- VPA 优化内存 requests
- 缩容保守(长 stabilization window)
一个现实的落地计划(不容易翻车)
- 所有容器补齐 requests(先做到“可预测调度”)
- 上 HPA:target 保守、scaleDown 慢
- 做一次压测或观察一次真实峰值(看扩容时间线)
- 确认 CA 能补节点且节点池有余量/配额
- 上 VPA 推荐,逐步把 requests 校正到更合理
排障:HPA/指标为什么不工作
看 HPA 状态:
kubectl get hpa -n <ns>
kubectl describe hpa -n <ns> <hpa>
常见提示:
- 无法获取指标(metrics pipeline 问题)
- 缺 requests(HPA 无法计算 utilization)
- 频繁 scale events(需要 behavior 调整或指标换更贴近负载)
Checklist
- requests 对齐真实负载(别拍脑袋)
- HPA 缩容保守,避免抖动
- 指标链路可靠(metrics-server/adapter)
- Cluster Autoscaler 能满足调度约束并有容量余量
- 用 VPA 推荐持续修正 requests
参考链接
FAQ
Q: HPA 和 VPA 怎么选? A: HPA 负责副本数,VPA 负责 requests/limits 的自动校准。同一工作负载不要让两者同时生效,可用 VPA recommendation 模式配合 HPA。
Q: 为什么 HPA 会抖动? A: 指标延迟和激进策略会导致反复伸缩。加 stabilization window、放慢 scale down,并调准目标值。
Q: 一定要装 metrics-server 吗? A: CPU/内存的 HPA 需要 metrics-server;自定义指标需要指标管道(如 Prometheus + adapter)。