深色模式
弹性伸缩排障与容量规划
摘要:本文是 K8s 弹性伸缩分类的收口篇,面向生产 SRE / 平台工程师。它把 HPA、VPA、Cluster Autoscaler、KEDA 四层弹性放在一张图上,给出选型决策树、HPA/VPA 冲突矩阵、排障决策树、容量规划公式与成本权衡,并指出指标链路(metrics-server 与各类 adapter)这一共同前置依赖。适用 Kubernetes v1.28+。
适用版本与前提
- Kubernetes:v1.28+
- 已阅读本分类 hpa.md / vpa.md / ca.md / keda.md
- 前提:metrics-server(Resource 指标)与对应 adapter(自定义/外部/KEDA)已就绪
四层弹性的职责边界
| 层 | 伸缩对象 | 驱动信号 | 是否需要节点层 |
|---|---|---|---|
| HPA | Pod 副本 | 资源/自定义/外部指标 | 间接(靠 CA) |
| VPA | 单 Pod 规格 | 历史用量 | 否(但改 requests 影响调度) |
| CA | 节点数 | Pending Pod(调度压力) | 自身即节点层 |
| KEDA | Pod 副本 | 事件源 | 间接(靠 CA)+ 自带 HPA |
决策树:该用哪个
HPA 与 VPA 冲突矩阵
这是生产最常踩的坑。二者对同一资源的"双控"会导致系统不收敛。
| HPA 信号 | VPA 模式 | 同资源? | 结论 |
|---|---|---|---|
| CPU | Off | — | 安全:VPA 仅出推荐 |
| CPU | Auto/Recreate | CPU | 冲突:互殴,禁止 |
| CPU | Auto + controlledResources:[memory] | 内存 | 安全:HPA 管 CPU、VPA 管内存 |
| 自定义/外部指标 | Auto | 否 | 安全 |
| 内存 | Auto | 内存 | 冲突:建议 VPA 改 Off 或 HPA 换信号 |
经验法则
能共存的安全组合只有两类:(1) VPA 设 Off,把推荐值交给人工/CI 治理;(2) HPA 与 VPA 管不同资源(HPA=CPU、VPA=内存)。其余同资源组合都应避免。详见 hpa.md、vpa.md。
排障决策树
容量规划公式(经验模型)
以下为规划用的近似公式,实际需结合压测与历史数据;[未实测],请用你的真实负载验证。
1. 副本数(来自 HPA 资源指标)
期望副本 ≈ ceil( 总目标 QPS / 单副本可承载 QPS )
≈ ceil( 平均 CPU 用量 / (requests.cpu × 目标利用率) )1
2
2
2. 单节点可调度 Pod 上限
节点 Pod 容量 = floor( 节点可分配资源 / 单 Pod requests ) # 受 CPU/内存各自约束, 取最小
节点组可承载副本上限 = 单节点容量 × 节点数(max)1
2
2
3. HPA max 与节点组上限对齐
HPA maxReplicas ≤ 节点组可承载副本上限
否则达到上限后多余副本永久 Pending, 需 CA 协同扩容节点组1
2
2
4. 成本近似
周期成本 ≈ 节点数 × 单节点单价 × 时长 + 副本波动带来的节点增量1
治理顺序建议
- 先给所有工作负载设准确 requests(否则 HPA 失效、CA 扩容模拟失准)。
- 用 VPA Off 跑 1~2 周,回收过度申请的资源(常可回收 40%~60%,
[未实测])。 - 上 HPA(资源或外部指标)吸收波动。
- 事件/队列负载用 KEDA 做 scale-to-zero。
- 最后用 Cluster Autoscaler 让节点数跟随 Pod 总数。
指标链路:共同前置依赖
四层弹性都依赖指标可用,故障往往出在链路而非控制器本身:
| 指标类型 | 提供方 | 故障表现 |
|---|---|---|
| Resource(CPU/内存) | metrics-server(metrics.k8s.io) | kubectl top 空 → HPA/VPA 全失效 |
| 自定义(Pods/Object) | Prometheus Adapter 等(custom.metrics.k8s.io) | HPA ScalingActive=False |
| 外部(队列/云) | KEDA / 自定义 adapter(external.metrics.k8s.io) | HPA/KEDA 取不到指标 |
生产危险
metrics-server 不可用会让 HPA 与 VPA 同时失明。请将 kubectl top 失败、metrics-server Pod 异常纳入告警,且为自定义/外部指标配置 fallback(KEDA)或静态兜底,避免"指标断了→缩到 0→彻底不处理"的最坏路径。
常见失败模式汇总
| 失败模式 | 根因 | 缓解 |
|---|---|---|
| 抖动(flapping) | 稳定窗口过短 | 加大 scaleDown.stabilizationWindowSeconds |
| 扩容跟不上尖峰 | 15s 同步 + 冷启动 + CA 实例供应慢 | 预热副本 / KEDA 事件驱动 / Karpenter [厂商特定] |
| HPA 与 VPA 互殴 | 同资源双控 | 拆资源或 VPA Off |
| 节点不缩容 | PDB/本地存储/注解 | 放宽 PDB、加 safe-to-evict、调整注解 |
| 永久 Pending | HPA max > 节点组容量 | 对齐 max 与节点组上限 |
| 冷启动超时 | scale-to-zero 唤醒慢 | minReplicaCount:1 或 idleReplicaCount 预热 |
安全与合规
- 任何自动伸缩都应有
maxReplicas/ 节点组 max 作为成本与爆炸半径上限;缺失上限是生产事故常见源。 - CA 删节点、VPA
Auto重启 Pod、KEDA scale-to-zero 都属于"自动改变运行态"的操作,务必配 PDB 与就绪/存活探针,并在非高峰先灰度验证。 - 高权限组件(VPA admission webhook、CA、KEDA)应限制作用范围,避免影响控制面。
性能、容量与成本权衡
- 快上慢下:扩容立即、缩容带稳定窗口,是抗丢请求与抗抖动的通用策略。
- scale-to-zero 省成本但有冷启动代价:延迟敏感路径慎用,或保留
idleReplicaCount。 - 过度细分节点组增加管理复杂度;单节点组过大降低缩容精度。按硬件/可用区/团队分池即可。
InPlaceOrRecreate等原地resize能力仍在演进[版本相关],不要假设 VPA 改动是"无感"的。
可观测性清单
bash
kubectl get hpa -A # 看 ScalingActive/Limited
kubectl top pods -n <ns> # 验证 metrics-server
kubectl get events -n kube-system | grep -i scale # CA 扩容/缩容事件
kubectl get scaledobject -A # KEDA 激活状态
kubectl describe vpa <name> # VPA 推荐值1
2
3
4
5
2
3
4
5
关键监控项:Pending Pod 持续时间、HPA ScalingActive=False 次数、CA TriggeredScaleUp/ScaleDownFailed、KEDA ScaledObject Active 比例、节点 unneeded 时长。
替代方案与权衡
| 方案 | 适用 | 不适用 |
|---|---|---|
| 本文四层组合 | 通用生产集群 | 极简/单负载 |
| Karpenter | AWS,按需灵活供应 | 非 AWS/需固定节点组 |
| 定时伸缩(cron HPA) | 可预测波峰 | 不可预测负载 |
FAQ
Q:能不能 HPA + VPA + CA 全开? A:可以,但 HPA 与 VPA 必须管不同资源(或 VPA Off)。CA 是节点层,与前两者天然互补。
Q:指标源挂了会怎样? A:HPA 进入 ScalingActive=False 不再缩放(保留当前副本);KEDA 可用 fallback 兜底;VPA 推荐停滞。务必监控指标链路。
未决/待验证项
InPlaceOrRecreate模式的默认行为与可用性随版本变化 ——TODO(verify):在 v1.28+ 实测确认。- VPA 资源回收比例(40%~60%)为社区经验值 ——
[未实测],需结合你的负载压测。 - Karpenter 与 CA 的取舍边界随云厂商与版本演进 ——
[厂商特定],以厂商文档为准。
参考资料
- Kubernetes 官方文档 - Horizontal Pod Autoscale,访问日期:2026-10-08。
- Kubernetes Autoscaler - VPA README,访问日期:2026-10-08。
- Kubernetes Autoscaler - Cluster Autoscaler FAQ,访问日期:2026-10-08。
- KEDA 官方文档,访问日期:2026-10-08。