HPA 是 Kubernetes Horizontal Pod Autoscaler,中文通常称为:
Horizontal Pod Autoscaler
水平 Pod 自动扩缩容器它根据监控指标,自动调整工作负载的 Pod 副本数。
基本逻辑:
指标升高 -> 增加 Pod 副本
指标降低 -> 减少 Pod 副本HPA 主要管理:
典型结构:
例如:
minReplicas: 3
maxReplicas: 20
targetCPU: 70%表示:
最少运行 3 个 Pod
最多运行 20 个 Pod
平均 CPU 利用率超过目标时扩容
低于目标时缩容需要先区分两个概念:
| 概念 | 作用 |
|---|---|
| Pod QoS | 根据 requests/limits 对 Pod 分类 |
| HPA | 根据指标自动调整 Pod 副本数 |
HPA 不是:
HPA 解决的是:
当前副本数是否足够承载当前负载VPA 解决的是:
单个 Pod 的 CPU、内存规格是否合理Cluster Autoscaler 解决的是:
集群节点数量是否足够三者可以这样理解:
HPA:横向扩容,增加或减少 Pod 数量
VPA:纵向调整,增加或减少单 Pod 资源
CA:节点扩容,增加或减少 Node 数量假设一个 API 服务平时运行 3 个 Pod:
Pod 1
Pod 2
Pod 3白天流量增加后:
CPU 升高
请求延迟增加
队列积压如果仍然保持 3 个 Pod,可能出现:
HPA 可以自动调整为:
3 个 Pod -> 6 个 Pod -> 10 个 Pod当流量下降后,再逐步缩回:
10 个 Pod -> 6 个 Pod -> 3 个 Pod早期 HPA API:
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler主要支持:
示例:
生产环境一般更推荐:
autoscaling/v2autoscaling/v2 支持:
生产环境通常使用:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler最常见的资源指标:
cpu
memory示例:
内存:
依赖:
metrics-server查看:
kubectl top pods -n production
kubectl top nodes例如:
resources:
requests:
cpu: "250m"容器实际使用:
500m利用率大致为:
500m / 250m = 200%如果 HPA 目标为 70%,就会倾向扩容。
因此:
HPA 的 CPU 利用率不是相对于节点总 CPU,
而通常是相对于 Pod 的 CPU request。这也是为什么 HPA 工作负载必须合理配置 requests。
也可以不使用百分比,而使用绝对值:
含义:
所有 Pod 的平均 CPU 使用量目标为 500m区别:
| 类型 | 含义 |
|---|---|
Utilization | 实际使用量 / request |
AverageValue | 每个 Pod 的平均绝对使用量 |
对于不同 Pod request 不一致的场景,AverageValue 有时更直观。
在 HPA 中常见:
AverageValue
Value用于多个 Pod 的平均值:
target:
type: AverageValue
averageValue: "100"用于整体指标值:
target:
type: Value
value: "1000"例如:
CPU 和内存:
依赖:
metrics.k8s.io
metrics-serverPods 指标是每个 Pod 都有一个指标,HPA 根据平均值计算。
例如每个 Pod 的活跃任务数:
适合:
这通常需要 Custom Metrics Adapter。
Object 指标关联 Kubernetes 中的某个对象。
例如根据 Ingress 请求速率:
适合:
External 指标来自 Kubernetes 集群外部。
例如:
示意:
通常需要:
Prometheus Adapter
或其他 External Metrics AdapterContainerResource 允许基于 Pod 中某个指定容器的资源利用率扩缩。
示例:
适合:
业务容器 + Service Mesh Sidecar
业务容器 + 日志 Sidecar可以避免 Sidecar 的 CPU 使用影响 HPA。
需要确认:
HPA 的简化计算公式:
期望副本数 =
当前副本数 × 当前指标值 / 目标指标值例如:
当前副本数:3
当前 CPU 利用率:140%
目标 CPU 利用率:70%计算:
3 × 140 / 70 = 6因此期望副本数约为:
6另一个例子:
当前副本数:10
当前 CPU 利用率:35%
目标 CPU 利用率:70%计算:
10 × 35 / 70 = 5可能缩容到:
5实际结果还会受到:
minReplicasmaxReplicas影响。
如果 HPA 同时配置:
CPU
内存
请求数
队列长度Kubernetes 会分别计算期望副本数,然后通常取其中最大值。
例如:
CPU 计算结果:4
内存计算结果:6
队列长度计算结果:10最终期望副本数:
10这样可以避免某个指标显示正常,但另一个指标已经严重过载。
前提是 Deployment 配置了 CPU request:
resources:
requests:
cpu: "250m"注意:
CPU 或内存任一指标要求扩容时,HPA 都可能扩容。假设每个 Pod 暴露自定义指标:
http_requests_per_second示例:
含义:
每个 Pod 平均处理 100 RPS
超过后逐步扩容相比单纯 CPU,更接近业务负载,但需要:
示意:
含义:
每个消费者 Pod 平均允许约 1000 条积压
积压增加时扩容生产中需要考虑:
默认 HPA 可能在指标抖动时频繁扩缩。生产环境通常需要配置 behavior。
含义:
每 60 秒最多扩大到原来的 2 倍,
或最多增加 4 个 Pod,
取允许扩容更多的策略。scaleUp 通常希望:
含义:
缩容前观察 5 分钟
每 60 秒最多缩容 25%缩容通常应该比扩容慢,原因是:
HPA 会考虑 Pod 是否已经 Ready,但实际行为还会受到指标采集和控制器状态影响。
新 Pod 启动期间可能存在:
Pod 已创建
Pod 尚未 Ready
指标尚未稳定如果 HPA 立即把这些 Pod 的低使用量算入平均值,可能造成错误缩容。
因此生产环境需要:
HPA 解决的是副本数量,不会替你判断应用是否真的已经具备承载能力。
如果使用:
target:
type: Utilization那么对应容器应该配置:
resources:
requests:
cpu: "250m"否则 HPA 可能无法计算:
missing request for cpu查看:
kubectl describe hpa api -n production关注:
AbleToScale
ScalingActive
ScalingLimited
Conditions
Eventsrequests:
cpu: "50m"实际使用:
200mCPU 利用率:
400%HPA 可能很快扩容。
requests:
cpu: "2"实际使用:
300m利用率:
15%即使业务请求已经变慢,HPA 也可能认为负载很低。
因此 request 必须反映合理的单 Pod 容量,而不是随意填写。
HPA 不是基于 limit 计算 CPU 利用率,而通常基于 request。
例如:
requests:
实际使用:
500mHPA 利用率大致为:
500m / 250m = 200%不是:
500m / 1 = 50%因此调大 CPU limit 不一定改变 HPA 的 CPU 利用率;调大 CPU request 才会明显改变该基准。
最常见:
适合:
也可以扩缩 StatefulSet:
但有状态服务不能简单按照 CPU 扩容。
需要额外考虑:
HPA 对 StatefulSet 只负责修改副本数,不负责完成数据库集群扩容逻辑。
HPA 扩容过程:
注意:
HPA 扩容完成
不等于新 Pod 已经可以接收流量如果新 Pod 启动慢,可能出现:
副本数增加了
但实际可用后端没有同步增加因此要监控:
HPA 只增加 Pod,不负责增加节点。
可能出现:
如果没有 Cluster Autoscaler 或节点容量不足:
HPA desiredReplicas 增加
但实际 Running Pod 不增加排查:
生产环境要同时设置:
HPA maxReplicas
Cluster Autoscaler 最大节点数
节点池容量
ResourceQuota
发布额外容量否则可能发生:
HPA 想扩到 20 个 Pod
但集群只放得下 8 个HPA 和 VPA 可以配合,但需要设计边界。
常见分工:
HPA:根据负载调整 Pod 数量
VPA:根据历史使用调整单 Pod request/limit但如果 HPA 和 VPA 都基于 CPU 利用率,就可能互相影响:
VPA 增大 request
-> CPU 利用率下降
-> HPA 不扩容
VPA 减小 request
-> CPU 利用率升高
HPA 扩容和 Deployment 滚动更新可能同时发生。
例如:
期望副本数:10
滚动更新 maxSurge:25%更新期间可能创建:
最多 13 个 Pod如果 HPA 同时把期望副本数从 10 调到 20,发布过程可能暂时需要:
20 + maxSurge这会影响:
生产环境需要协调:
strategy:
以及:
minReplicas
maxReplicas
ResourceQuota适合:
优点:
缺点:
适合:
风险:
内存 HPA 要特别配置缩容稳定窗口。
适合:
例如:
每个 Pod 处理 100 RPS优点:
风险:
适合:
队列型服务通常比 CPU HPA 更适合使用:
消息积压
消费延迟
待处理任务数但需要结合:
例如:
每个租户请求数
支付订单数
实时连接数
会议房间数
AI 推理请求数这种方式最贴近业务,但需要:
一个好的 HPA 指标应该满足:
指标升高意味着 Pod 更接近容量上限
增加 Pod 后指标会下降
指标变化相对及时
指标不会因为副本数增加而失真例如:
每 Pod 活跃请求数
每 Pod 队列长度
每 Pod 消费延迟通常比:
随机日志数量
总请求数但没有除以副本数更适合作为扩缩指标。
minReplicas: 3最小副本数要考虑:
不要把核心服务的 minReplicas 设置为 1,除非明确接受单实例风险。
maxReplicas: 50最大副本数应受到以下约束:
HPA 最大副本数不是越大越好。如果下游数据库最多支持 1000 个连接,而每个 Pod 创建 50 个连接,那么副本数上限就需要纳入数据库容量。
推荐:
scaleDown:
stabilizationWindowSeconds: 300对有明显周期性流量的业务,可以设置更长:
300 秒
600 秒扩容通常需要更快,缩容通常需要更慢。
如果 Pod 启动需要 2 分钟,HPA 扩容触发后,短时间内仍然没有可用容量。
需要考虑:
minReplicasHPA 不是瞬时扩容,完整链路包括:
查看:
kubectl describe hpa api -n production重点看:
Metrics
Current Metrics
Desired Replicas
Conditions
Events常见原因:
检查:
常见原因:
需要关联分析:
HPA 指标
Pod Ready 数
请求量
错误率
典型表现:
3 -> 8 -> 4 -> 10 -> 3常见原因:
治理方法:
behavior:
scaleDown:
stabilizationWindowSeconds: 300并调整:
可能是:
maxReplicas 已达到上限查看:
kubectl describe hpa api -n production如果看到:
ScalingLimited=True说明扩缩容受到边界限制。
也可能是:
HPA 已经把 desiredReplicas 调高,
但新 Pod 因资源不足处于 Pending查看:
这通常说明问题不一定是副本数不足,可能是:
HPA 只是增加 Pod,不会自动消除系统中的其他瓶颈。
Deployment:
HPA:
适合:
适合:
不适合:
设计含义:
每个 Pod 目标处理 100 RPS如果总请求量为:
1000 RPS理想副本数大约为:
1000 / 100 = 10前提是:
含义:
每个 Worker 平均处理约 500 条积压消息需要确保:
适合:
业务容器 CPU 代表真实业务压力,
Sidecar CPU 不应触发业务扩容。但如果 Sidecar 本身也会成为瓶颈,例如代理处理加密或大量连接,那么只看业务容器可能又不够,需要使用多指标或单独监控 Sidecar。
HPA 可以提高资源利用率,但也可能增加成本。
需要控制:
常见成本问题:
maxReplicas 过大生产环境应建立告警:
HPA 长时间达到 maxReplicas
HPA 长时间无法达到 desiredReplicas
HPA 频繁扩缩
HPA 指标缺失
集群节点成本突然升高HPA 是 Kubernetes 中根据指标自动调整 Pod 副本数的控制器。
它主要支持:
核心计算逻辑可以简化为:
期望副本数 =
当前副本数 × 当前指标 / 目标指标生产环境的推荐组合是:
最重要的几个结论:
成熟的生产 HPA 设计,不是简单地配置:
averageUtilization: 70而是要回答:
只有这些问题都经过验证,HPA 才能真正改善生产系统的弹性和稳定性。 有。前面已经覆盖了 HPA 的主体,下面补充一些更深入的机制和生产中非常容易踩坑的点。
HPA 不会因为指标略微超过目标就立即扩缩容,而是存在一定的变化容忍区间,避免频繁抖动。
假设目标 CPU 利用率为:
averageUtilization: 70当前利用率是:
72%通常不会立刻扩容,因为变化幅度太小。
简化理解:
当前指标 / 目标指标只有当这个比例明显偏离 1 时,HPA 才会调整副本数。
该容忍度由 HPA Controller 参数控制,常见默认值约为:
0.1,也就是 10%不同集群可能通过 Controller Manager 参数调整:
--horizontal-pod-autoscaler-tolerance生产环境一般不建议随意修改全局容忍度,因为它会影响整个集群的所有 HPA。
简化公式:
期望副本数 =
当前副本数 × 当前指标 / 目标指标例如:
当前副本数:3
当前 CPU:95%
目标 CPU:70%计算结果:
3 × 95 / 70 = 4.07最终副本数需要取整,并受到:
minReplicas
maxReplicas
behavior
容忍区间限制。
因此不要期待:
当前 CPU 71% -> 精确扩容到某个小数副本副本数始终是整数。
即使指标突然暴涨,HPA 也可能受到以下因素限制:
完整链路可能是:
所以 HPA 不是瞬时弹性机制。
对于突发流量,需要结合:
minReplicasHPA 的目标对象必须支持 Kubernetes 的 Scale 子资源。
常见支持对象:
Deployment
ReplicaSet
StatefulSetHPA 通过类似以下接口修改目标对象:
/apis/apps/v1/namespaces/<namespace>/deployments/<name>/scale排查 HPA 目标是否支持:
如果目标对象不支持 Scale,HPA 无法正常工作。
错误示例:
HPA-A -> Deployment/api
HPA-B -> Deployment/api两个 HPA 都会修改:
spec.replicas结果可能是:
HPA-A 设置为 10
HPA-B 设置为 4
HPA-A 再设置为 8
HPA-B 再设置为 5造成:
生产环境应保证:
一个可扩缩工作负载,通常只绑定一个 HPA如果需要多个指标,应写在同一个 HPA 的 metrics 中。
常见冲突:
Deployment YAML:
replicas: 3
HPA:
期望副本数:10如果 GitOps 工具持续把 Deployment 的 spec.replicas 强制同步为 3,就可能出现:
HPA 扩容到 10
GitOps 又改回 3
HPA 再扩到 10生产环境需要明确副本数的管理方式:
Git 中不持续强制固定 spec.replicas,或者配置忽略规则。
后续由 HPA 管理。
避免两个控制器同时写同一字段。
如果部分 Pod 没有指标,HPA 不一定把它们当作使用量为 0。
指标缺失可能导致:
常见原因:
排查:
不要看到 HPA 没有扩容就直接提高 maxReplicas,先确认指标链路是否完整。
新 Pod 在启动期间可能:
Pod 已创建
但还没有 Ready
指标尚未稳定如果 HPA 过早使用这些 Pod 的指标,可能出现错误判断。
这也是为什么生产环境应正确配置:
startupProbe
readinessProbe并关注:
Pod 启动时间
Readiness 成功时间
metrics-server 采集时间
HPA 同步周期如果应用启动需要 90 秒,但 HPA 每 15 秒计算一次,扩容过程中的指标会有明显滞后。
指标通常不是瞬时值,而是经过一段时间聚合的结果。
例如 CPU 使用率可能受到:
采集周期
Prometheus 查询窗口
metrics-server 缓存
HPA 同步周期影响。
窗口过短:
对尖峰敏感
但容易抖动窗口过长:
更稳定
但响应变慢自定义指标尤其需要明确:
指标是瞬时值、平均值还是速率?
统计窗口是多少?
是否已经在 Adapter 或 Prometheus 中聚合?如果 Prometheus 指标已经是 5 分钟平均值,HPA 再基于它扩缩容,可能会明显滞后。
例如总请求数:
http_requests_total它是一个单调递增计数器,不能直接作为 HPA 指标。
通常需要转换成速率:
sum(rate(http_requests_total[2m]))如果需要每 Pod 请求数:
sum by (pod) (
rate(http_requests_total[2m])
)常见错误:
直接使用 Counter 当前累计值结果可能是:
指标不断增长
HPA 永久扩容生产使用 Prometheus 指标时,需要确认:
危险指标示例:
http_requests{user_id="..."}
http_requests{request_id="..."}
http_requests{url="完整动态路径"}这类标签可能产生大量时间序列,导致:
生产自定义指标应尽量使用低基数标签:
service
namespace
deployment
pod
method
status_class避免把以下信息作为指标标签:
用户 ID
订单 ID
请求 ID
完整 URL 参数
随机 TokenHPA 使用自定义或外部指标时,通常需要访问:
custom.metrics.k8s.io
external.metrics.k8s.io需要确认:
检查:
生产环境不要允许任意团队提交任意 External Metric 查询,平台应统一管理指标白名单和查询范围。
假设 Kafka Topic 有:
8 个分区消费者最多有效并行度通常受分区数限制。
如果 HPA 配置:
maxReplicas: 50可能出现:
50 个 Pod
只有 8 个 Pod 实际消费
其余 Pod 空闲这会造成:
队列型 HPA 的 maxReplicas 应结合:
分区数
任务并行度
每 Pod Consumer 数
下游处理能力
数据库连接池仅把积压降下来还不够,还要关注 backlog 是否能在业务要求内清空。
可以估算:
所需处理能力 =
当前积压量 / 目标清理时间例如:
积压:100 万条
目标:10 分钟清理需要的平均处理速度:
1000000 / 600 ≈ 1667 条/秒如果单个 Pod 只能处理:
100 条/秒至少需要约:
17 个有效消费者HPA 的目标值应基于业务清理时间,而不是随意设置一个 backlog 数字。
如果应用存在全局瓶颈,扩容 Pod 可能没有效果。
例如:
表现为:
HPA 副本数增加
但吞吐不增加
延迟仍然很高此时要优化的是:
而不是继续提高 maxReplicas。
假设:
每个 Pod 最大数据库连接数:50
maxReplicas:20数据库理论上可能承受:
50 × 20 = 1000 个连接如果数据库连接上限只有 500,HPA 扩容可能导致:
数据库连接耗尽
请求失败
应用重试
负载进一步增加生产环境应根据最大副本数反推:
数据库连接池
缓存连接数
下游 RPC 连接数
文件句柄
线程数
外部 API 配额HPA 的最大副本数不能只看 Kubernetes 集群容量。
扩容有延迟,突发流量可能先于新 Pod 到达。
推荐链路:
如果没有限流,可能出现:
流量暴增
-> Pod 过载
-> HPA 触发
因此生产系统需要:
缩容会减少 Pod 数量,导致:
因此有本地缓存的服务通常应:
behavior:
scaleDown:
stabilizationWindowSeconds: 600或者使用:
不能只根据 CPU 降低就立刻缩容。
对于以下服务要谨慎缩容:
缩容时应确保:
停止接收新连接
等待已有连接结束
迁移或重新建立连接
确认客户端有重连机制需要配合:
Readiness
SIGTERM
PreStop
terminationGracePeriodSeconds
PDB
客户端重连不适合直接使用 HPA 的场景包括:
这些场景可能需要:
VPA
StatefulSet 专用扩容流程
分片扩容
垂直扩容
专用 Operator
人工容量管理kubectl get hpa -n production
kubectl top pods -n production
kubectl top nodeskubectl get deployment api -n production -wkubectl get events -n production \
--sort-by=.lastTimestamp使用压测工具制造负载:
hey -z 5m -c 100 http://api.example.com/观察:
压测完成后,还要观察缩容:
流量下降
-> 指标下降
-> 稳定窗口
-> 副本逐步减少对应 Deployment 至少需要:
还需要:
metrics-server
Readiness Probe
合理的 maxReplicas
足够的节点容量
数据库连接规划
发布期间容量余量HPA 的本质是:
根据指标调整工作负载的副本数。但一个可靠的生产 HPA 还必须满足:
最容易忽略的三点是:
1. HPA 扩容的是副本,不是单 Pod 资源。
2. HPA 扩容成功,不等于新 Pod 已经 Ready。
3. HPA 能否改善性能,取决于系统是否真正具备横向扩展能力。因此,生产环境的完整弹性链路通常是:
HPA 只是这条链路中的副本调节器,不能单独承担整个系统的弹性、高可用和性能治理。 还可以补充最后一组:HPA 与 KEDA、预测扩容、冷启动、缩容保护、指标设计和多集群生产治理。这些属于实际落地时更高级的内容。
原生 HPA 更适合基于:
CPU
内存
Prometheus 指标
自定义指标
External MetricsKEDA 更适合事件驱动扩缩容:
Kafka lag
RabbitMQ queue length
Redis list length
典型架构:
KEDA ScaledObject
|
v
示例:
KEDA 的价值在于:
minReplicaCount: 0但生产需要考虑:
minReplicas: 0 要谨慎普通 HPA 通常至少保留一个或几个副本:
minReplicas: 2如果使用事件驱动组件或特定版本能力,也可能缩容到 0:
0 Pod -> 有事件 -> 创建 Pod适合:
不适合:
缩容到 0 之前,必须明确:
没有 Pod 时,谁负责产生和读取指标?这也是 KEDA 常用于事件驱动场景的原因。
HPA 触发扩容后,Pod 还要经历:
如果整个过程需要 2 分钟,而流量 30 秒内就暴涨,HPA 即使计算正确也来不及保护服务。
可采取:
minReplicasHPA 是反应式扩容,不是预测式扩容。
原生 HPA 主要根据当前或近期指标做反应式扩容。对于有明显规律的流量,例如:
每天 9 点流量上涨
每周一任务量增加
固定时间批处理启动可以结合:
minReplicas例如通过 KEDA 在工作时间提高最小副本数:
生产中常见组合:
定时预测扩容 + CPU/业务指标兜底这样可以在流量到来之前完成一部分扩容。
比较合理的业务指标通常是:
每 Pod RPS
每 Pod 活跃请求数
每 Pod 并发连接数
每 Pod 队列长度
每 Pod 消费延迟
每 Pod 活跃任务数不太理想的指标包括:
全局累计请求数
没有时间窗口的 Counter
无法按 Pod 归属的总量
与负载没有直接关系的日志数量
被重试流量放大的请求数理想指标应满足:
副本增加后,单 Pod 指标会下降例如总请求量本身可能随着副本增加而不变,甚至继续增长;而每 Pod 请求量更容易直接表达单 Pod 压力。
自定义指标可能出现:
NaN
负数
突然归零
突然暴涨
指标暂时不存在
生产指标链路应设计:
不要让一次指标系统故障触发大量无意义扩容。
例如同时配置:
CPU:目标 70%
内存:目标 75%
请求数:每 Pod 100 RPS
队列长度:每 Pod 1000HPA 通常会取需要最大副本数的指标,这有利于避免过载,但也可能导致:
请求数指标要求 5 副本
内存指标异常要求 30 副本最终扩容到 30。
生产环境应该:
HPA 缩容时,PDB 通常不是主要限制机制,但节点维护、滚动发布和主动驱逐会受 PDB 影响。
例如:
minAvailable: 80%如果 HPA 低峰期将副本数缩小到 2,那么 PDB 可能要求至少保留 2 个 Pod,导致:
使用百分比时尤其要注意副本数变化后的实际结果。
生产环境需要同时验证:
minReplicas
当前副本数
PDB minAvailable
maxUnavailable
节点 drain
滚动更新如果 HPA 扩容出来的新 Pod 都被调度到单一区域,可能出现:
副本数量增加了
但故障域集中关键服务需要配合:
还要考虑:
多集群环境中,每个集群的 HPA 独立工作,可能造成:
集群 A 扩容
集群 B 不扩容如果流量由全局 DNS 或全局负载均衡分配,还要考虑:
minReplicas/maxReplicas比较成熟的结构是:
全局流量调度
|
v
各集群本地 HPA
全局流量系统和集群内 HPA 需要分别治理。
发布期间 CPU、请求数和内存会产生短暂波动,可能触发 HPA。
例如:
新版本启动预热
-> CPU 突增
-> HPA 判断需要扩容
-> 发布和扩容同时发生这可能造成资源峰值。
建议:
maxSurge建议统一展示:
真正需要回答的是:
HPA 为什么扩容?
扩容后新 Pod 是否 Ready?
扩容是否带来吞吐提升?
只监控 currentReplicas 不够。
通常不使用长期 HPA更适合:
CronJob
KEDA Cron Trigger
Job 并发控制不建议直接使用普通 HPA 根据 CPU 扩副本更适合:
数据库 Operator
StatefulSet 专用扩容逻辑
分片或副本管理在生产环境启用 HPA 前,先回答:
HPA 的核心职责是:
根据指标自动调整工作负载的 Pod 副本数。更完整地说:
生产环境最常见的可靠组合是:
最后要记住:
HPA 能做的是增加或减少 Pod;
HPA 不能保证新 Pod 立即可用;
HPA 不能消除数据库、网络或锁等瓶颈;
HPA 不能替代限流、熔断、队列和应用容灾。当指标选择正确、资源 request 合理、Pod 启动足够快、节点和下游容量都经过验证时,HPA 才能真正成为生产环境中的弹性能力。 有。前面的内容已经覆盖 HPA 的主要知识,下面补充最后一组更偏实现、状态判断和平台治理的内容。
查看 HPA:
kubectl get hpa api -n production -o yaml重点关注:
常见 Condition:
| Condition | 含义 |
|---|---|
AbleToScale | HPA 是否能正常读取并计算扩缩容 |
ScalingActive | 指标是否有效且扩缩容逻辑已启用 |
ScalingLimited | 是否达到 minReplicas 或 |
例如:
ScalingLimited=True不一定表示 HPA 故障,也可能是:
当前指标仍然要求继续扩容,但已经达到 maxReplicas排查 HPA 时不要只看当前副本数:
kubectl describe hpa api -n production关注 Events:
SuccessfulRescale
FailedGetResourceMetric
FailedComputeMetricsReplicas
FailedGetExternalMetric
FailedGetPodsMetric常见含义:
| 事件 | 可能原因 |
|---|---|
SuccessfulRescale | HPA 成功修改副本数 |
FailedGetResourceMetric | metrics-server 无法提供 CPU/内存 |
FailedGetExternalMetric | 外部指标 Adapter 异常 |
FailedComputeMetricsReplicas | 指标计算失败 |
|
metrics-server 主要为:
kubectl top
Resource Metrics API提供近实时资源指标。
它不适合替代:
Prometheus
长期历史监控
复杂业务指标
审计分析
容量趋势分析依赖关系大致是:
不同 HPA 指标类型需要确认对应的指标服务是否存在。
查看 APIService:
kubectl get apiservice | grep metrics查看资源指标 API:
kubectl get --raw \
/apis/metrics.k8s.io/v1beta1/nodes查看某个 Namespace 的 Pod 指标:
kubectl get --raw \
/apis/metrics.k8s.io/v1beta1/namespaces/production/pods如果 kubectl top 不工作,CPU/内存 HPA 通常也无法正常工作。
HPA 读取目标工作负载下 Pod 的指标。如果目标对象、Pod 标签或控制器关系异常,HPA 可能无法正确计算。
检查:
确认:
Deployment selector
ReplicaSet selector
Pod template labels没有发生错误匹配。
尤其在手工修改标签、蓝绿发布、灰度发布时,要确认 HPA 管理的 Deployment 与实际 Pod 集合一致。
如果同一个 Deployment 正在滚动发布,短时间内可能同时存在:
旧版本 Pod
新版本 PodHPA 通常针对整个目标 Deployment 的副本数,而不是单独针对某个 ReplicaSet。
因此发布期间需要关注:
如果使用:
type: ContainerResource则所有相关 Pod 中的容器名称最好保持一致,否则部分 Pod 可能无法被正确统计。
HPA 负责:
一个目标工作负载的副本数量金丝雀发布负责:
不同版本之间的流量比例如果蓝绿或金丝雀使用两个 Deployment:
api-stable
api-canary通常应明确:
是否给两个 Deployment 分别配置 HPA
是否分别设置 min/max
流量比例变化后两个版本的负载如何变化不要只扩容稳定版本,却把大部分流量切给了 Canary 版本。
Service Mesh 可能产生:
客户端重试
代理重试
超时重试
跨服务重试如果 HPA 使用代理层请求数,指标可能包含重试流量:
一次业务请求
-> 原始请求
-> 代理重试两次
-> 指标记录三次结果可能是:
HPA 感知到的请求量高于真实业务请求量生产指标应明确:
统计入口请求还是代理请求?
统计重试前还是重试后?
统计成功请求还是所有尝试?
是否包含健康检查?即使副本数增加,流量也不一定均匀分布。
可能的原因:
如果新 Pod 长时间没有流量:
副本数增加
但旧 Pod 仍然过载应检查:
每 Pod 请求数
每 Pod 连接数
EndpointSlice
客户端连接行为
Service Mesh 负载策略如果单个 Pod 压测到:
1000 RPS但在 1000 RPS 时已经出现:
P99 延迟明显上升
CPU throttling
GC 增加
错误率上升就不应把 HPA 目标设置成 1000 RPS。
应该使用安全容量,例如:
600 RPS 或 700 RPSHPA 的目标应该满足:
业务指标达到目标时,Pod 仍有可接受的延迟和错误率假设:
数据库最大连接数:1000
每个 Pod 最大连接数:40理论最大副本数不能超过:
1000 / 40 = 25还要给:
预留空间。
因此实际 maxReplicas 可能设置为:
maxReplicas: 20而不是直接设置为 50。
常见生产策略:
扩容:快速
缩容:缓慢示例:
含义:
扩容可以快速响应
缩容至少观察 10 分钟
每分钟最多减少 10%具体值要结合:
如果业务负载有固定时间规律:
每天 9 点流量上升
每天 18 点流量下降仅依赖 HPA 可能反应偏慢。
更适合组合:
定时预扩容
+ HPA 实时兜底例如在高峰前提高:
minReplicas: 10高峰结束后恢复为:
minReplicas: 3也可以使用:
指标系统异常时,不能让生产服务完全失去弹性保护。
可以准备:
minReplicasmaxReplicasHPA 是自动控制器,也必须有人工兜底流程。
一个成熟的 HPA 系统通常包含:
最终生产检查:
最终结论:
HPA 不是简单的“CPU 超过 70% 就加 Pod”。
它是一套由指标、控制器、工作负载、调度器、节点自动扩容、
Service 和下游容量共同组成的闭环系统。真正可靠的 HPA 必须同时解决:
到这里,HPA 的 API、指标类型、计算逻辑、扩缩容策略、资源依赖、KEDA、VPA、Cluster Autoscaler、队列场景、发布、监控、故障排查和生产治理边界已经基本覆盖完整。
指标系统
|
v
HPA
|
v
Deployment / StatefulSet
|
v
Pod 副本数apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: web
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web
minReplicas: 2
maxReplicas: 10
targetCPUUtilizationPercentage: 70metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70metrics:
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 75metrics:
- type: Resource
resource:
name: cpu
target:
type: AverageValue
averageValue: "500m"metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70metrics:
- type: Pods
pods:
metric:
name: active_requests
target:
type: AverageValue
averageValue: "100"metrics:
- type: Object
object:
describedObject:
apiVersion: networking.k8s.io/v1
kind: Ingress
name: api-ingress
metric:
name: requests_per_second
target:
type: Value
value: "1000"metrics:
- type: External
external:
metric:
name: kafka_consumer_lag
selector:
matchLabels:
topic: orders
consumer_group: order-worker
target:
type: AverageValue
averageValue: "1000"metrics:
- type: ContainerResource
containerResource:
name: cpu
container: app
target:
type: Utilization
averageUtilization: 70apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api
namespace: production
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api
namespace: production
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 75apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api
namespace: production
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api
minReplicas: 3
maxReplicas: 30
metrics:
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: "100"apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: order-consumer
namespace: production
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: order-consumer
minReplicas: 2
maxReplicas: 20
metrics:
- type: External
external:
metric:
name: kafka_consumer_lag
selector:
matchLabels:
topic: orders
consumer_group: order-consumer
target:
type: AverageValue
averageValue: "1000"behavior:
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Percent
value: 100
periodSeconds: 60
- type: Pods
value: 4
periodSeconds: 60
selectPolicy: Maxbehavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 25
periodSeconds: 60
selectPolicy: MinapiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api
namespace: production
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api
minReplicas: 3
maxReplicas: 30
behavior:
scaleUp:
stabilizationWindowSeconds: 0
selectPolicy: Max
policies:
- type: Percent
value: 100
periodSeconds: 60
- type: Pods
value: 5
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300
selectPolicy: Min
policies:
- type: Percent
value: 20
periodSeconds: 60
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70HPA 增加副本数
|
v
Deployment 创建新 Pod
|
v
Pod 通过 Readiness Probe
|
v
Pod 加入 EndpointSlice
|
v
Service 开始转发流量HPA 扩容 Pod
|
v
新 Pod Pending
|
v
Cluster Autoscaler 增加节点
|
v
Pod 最终调度kubectl get pods -n production
kubectl describe pod <pending-pod> -n production
kubectl describe hpa api -n production
kubectl get nodes指标采集
-> HPA 计算
-> 创建 Pod
-> 调度
-> 拉镜像
-> 启动容器
-> 通过 Readiness
-> 加入 Servicekubectl get --raw /apis/metrics.k8s.io/v1beta1/nodes
kubectl top pods -n production
kubectl get hpa -n productionkubectl get pods -n production
kubectl describe pod <pending-pod> -n productionapiVersion: apps/v1
kind: Deployment
metadata:
name: api
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
image: registry.example.com/api:v1.2.0
ports:
- name: http
containerPort: 8080
resources:
requests:
cpu: "250m"
memory: "512Mi"
limits:
cpu: "1"
memory: "1Gi"
readinessProbe:
httpGet:
path: /ready
port: http
periodSeconds: 5apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api
namespace: production
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api
minReplicas: 3
maxReplicas: 20
behavior:
scaleUp:
policies:
- type: Percent
value: 100
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 25
periodSeconds: 60
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: cache-api
namespace: production
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: cache-api
minReplicas: 3
maxReplicas: 15
behavior:
scaleDown:
stabilizationWindowSeconds: 600
metrics:
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 75apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web
namespace: production
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web
minReplicas: 3
maxReplicas: 30
metrics:
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: "100"apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: worker
namespace: production
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: worker
minReplicas: 2
maxReplicas: 20
behavior:
scaleUp:
stabilizationWindowSeconds: 0
scaleDown:
stabilizationWindowSeconds: 600
metrics:
- type: External
external:
metric:
name: queue_backlog
selector:
matchLabels:
queue: orders
target:
type: AverageValue
averageValue: "500"apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api
namespace: production
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api
minReplicas: 3
maxReplicas: 20
metrics:
- type: ContainerResource
containerResource:
name: cpu
container: api
target:
type: Utilization
averageUtilization: 70[ ] HPA 使用 autoscaling/v2
[ ] scaleTargetRef 指向正确工作负载
[ ] minReplicas 合理
[ ] maxReplicas 合理
[ ] Pod 配置了对应 requests
[ ] metrics-server 或自定义指标 Adapter 正常
[ ] 指标与业务容量相关
[ ] 指标采集延迟已评估
[ ] Readiness Probe 正确
[ ] 新 Pod 启动时间已评估
[ ] 配置 scaleUp 行为
[ ] 配置 scaleDown 稳定窗口
[ ] 评估 Sidecar 是否影响指标
[ ] 评估数据库和下游连接上限
[ ] 评估消息分区和并发限制
[ ] 评估 ResourceQuota
[ ] 评估 Cluster Autoscaler
[ ] 评估滚动发布额外容量
[ ] 监控 desired/current/ready replicas
[ ] 监控 HPA Conditions 和 Events
[ ] 监控错误率、延迟和业务积压
[ ] 对 HPA 进行压力测试Resource:
CPU、内存
Pods:
每个 Pod 的自定义指标
Object:
某个 Kubernetes 对象的指标
External:
集群外部指标,例如队列积压
ContainerResource:
指定容器的资源指标Deployment/StatefulSet
+ 合理 resources.requests
+ HPA autoscaling/v2
+ Readiness/Startup Probe
+ metrics-server 或 Custom Metrics Adapter
+ scaleUp/scaleDown behavior
+ ResourceQuota
+ Cluster Autoscaler
+ 业务指标监控
+ 压测和灰度验证1. HPA 扩的是 Pod 数量,不是单个 Pod 的资源。
2. CPU 利用率通常以 request 为基准。
3. HPA 不负责扩容节点,节点不足需要 Cluster Autoscaler。
4. CPU 指标不一定代表真实业务压力,队列和请求数可能更合适。
5. minReplicas 和 maxReplicas 必须结合业务、节点、下游和成本确定。
6. 缩容通常应该比扩容更慢,避免抖动。
7. HPA 扩容完成不等于新 Pod 已经 Ready。
8. HPA 不能替代应用限流、熔断、缓存和下游容量治理。什么指标真正代表负载?
单个 Pod 能稳定承载多少请求?
Pod 启动需要多久?
扩容后流量是否均匀?
下游是否能承受更多副本?
最大副本数是多少?
节点能否及时扩容?
缩容是否会中断请求或任务?scaleUp policies
maxReplicas
控制器同步周期
指标采集延迟
Pod 创建速度
调度速度
节点扩容速度
Readiness 速度业务流量增加
-> 指标系统采集
-> HPA 获取指标
-> 计算期望副本
-> 修改 Deployment replicas
-> ReplicaSet 创建 Pod
-> Scheduler 调度
-> Kubelet 拉镜像
-> 容器启动
-> Readiness 成功
-> Service 加入后端kubectl describe hpa api -n production
kubectl top pods -n production
kubectl get --raw /apis/metrics.k8s.io/v1beta1/namespaces/production/podsIngress/Gateway
|
v
限流、排队、熔断
|
v
HPA 扩容
|
v
新 Pod Readykubectl get deployment api -n production
kubectl get pods -n production -l app=apiHPA current metrics
desiredReplicas
Deployment replicas
readyReplicas
Endpoint 数量
延迟
错误率
节点容量apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api
namespace: production
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api
minReplicas: 3
maxReplicas: 30
behavior:
scaleUp:
stabilizationWindowSeconds: 0
selectPolicy: Max
policies:
- type: Percent
value: 100
periodSeconds: 60
- type: Pods
value: 5
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 600
selectPolicy: Min
policies:
- type: Percent
value: 20
periodSeconds: 60
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 75resources:
requests:
cpu: "250m"
memory: "512Mi"
limits:
cpu: "1"
memory: "1Gi"[ ] 是否只有一个 HPA 管理该工作负载
[ ] 是否使用 autoscaling/v2
[ ] scaleTargetRef 是否正确
[ ] 目标对象是否支持 Scale 子资源
[ ] CPU/内存 request 是否存在
[ ] 指标是否代表真实业务负载
[ ] 指标是否存在延迟或缺失
[ ] 自定义指标是否正确聚合
[ ] Counter 是否转换成 rate
[ ] 标签基数是否可控
[ ] 是否配置 minReplicas
[ ] 是否配置 maxReplicas
[ ] maxReplicas 是否受下游容量约束
[ ] 是否配置扩容策略
[ ] 是否配置缩容稳定窗口
[ ] 是否考虑 Pod 冷启动
[ ] 是否考虑节点自动扩容
[ ] 是否考虑滚动发布 maxSurge
[ ] 是否考虑 Service Endpoint 更新延迟
[ ] 是否考虑 Sidecar 影响
[ ] 是否考虑长连接
[ ] 是否考虑缓存预热
[ ] 是否考虑数据库连接上限
[ ] 是否避免 GitOps 覆盖 replicas
[ ] 是否监控 HPA Conditions
[ ] 是否监控 desired/current/ready replicas
[ ] 是否进行过压力测试和缩容测试指标可靠
request 合理
Pod 可快速启动
Service 能及时接入新 Pod
节点有扩容能力
下游能承受更多副本
缩容不会破坏连接和缓存
发布不会耗尽配额
GitOps 不会覆盖副本数业务指标
-> Metrics Adapter
-> HPA
-> Deployment/StatefulSet
-> Pod
-> Scheduler
-> Cluster Autoscaler
-> Service/Ingress
-> 下游容量治理apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: order-worker
namespace: production
spec:
scaleTargetRef:
name: order-worker
minReplicaCount: 2
maxReplicaCount: 20
pollingInterval: 15
cooldownPeriod: 300
triggers:
- type: kafka
metadata:
bootstrapServers: kafka.production.svc:9092
consumerGroup: order-worker
topic: orders
lagThreshold: "1000"创建对象
-> 调度
-> 拉取镜像
-> 创建容器
-> Init Container
-> 应用启动
-> 缓存预热
-> Readiness Probe
-> 加入 Servicetriggers:
- type: cron
metadata:
timezone: Asia/Shanghai
start: "0 08 * * 1-5"
end: "0 20 * * 1-5"
desiredReplicas: "10"topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app: apiHPA desiredReplicas
HPA currentReplicas
HPA minReplicas
HPA maxReplicas
当前指标
目标指标
Deployment replicas
Ready replicas
Available replicas
Pending replicas
Endpoint 数量
Pod 启动耗时
请求量
错误率
P95/P99 延迟
节点资源
下游连接数指标:
CPU + 每 Pod RPS
minReplicas:
至少覆盖单节点故障后的服务能力
maxReplicas:
受节点、数据库和外部依赖限制
扩容:
快速
缩容:
缓慢,稳定窗口 5 到 10 分钟
配套:
Readiness、Cluster Autoscaler、PDB、入口限流指标:
queue backlog 或 consumer lag
minReplicas:
至少满足基础消费能力
maxReplicas:
不超过分区数或有效并发数
扩容:
根据积压和目标清理时间
缩容:
较慢,确保正在处理的任务安全结束
配套:
幂等、重试、优雅终止、死信队列[ ] 这个应用是否可以真正横向扩展?
[ ] 增加 Pod 后吞吐是否会增加?
[ ] 单个 Pod 的容量是多少?
[ ] 什么指标最能代表负载?
[ ] 指标采集是否可靠?
[ ] Pod 启动需要多久?
[ ] 新 Pod Ready 需要多久?
[ ] 集群能否及时提供节点?
[ ] 下游是否能承受更多副本?
[ ] 最大副本数如何确定?
[ ] 缩容是否会破坏连接、缓存或任务?
[ ] 是否需要事件驱动扩缩?
[ ] 是否存在 HPA、VPA、GitOps 并发修改副本数?
[ ] 是否有扩容无效和指标异常告警?
[ ] 是否进行过压力、故障和缩容演练?原生 HPA:
适合反应式副本扩缩
KEDA:
适合事件驱动和队列型扩缩
VPA:
适合调整单 Pod 资源
Cluster Autoscaler:
适合调整节点数量
Ingress/Gateway:
负责入口流量治理
应用和下游系统:
决定横向扩展是否真正有效业务指标
-> Prometheus/Adapter 或 KEDA
-> HPA
-> Deployment/StatefulSet
-> Pod
-> Scheduler
-> Cluster Autoscaler
-> Service
-> 下游系统status:
currentReplicas: 5
desiredReplicas: 8
currentMetrics:
- type: Resource
resource:
current:
averageUtilization: 85
conditions:
- type: AbleToScale
status: "True"
- type: ScalingActive
status: "True"
- type: ScalingLimited
status: "False"| Pods 类型指标不可用 |
kubectl get deployment api -n production -o yaml
kubectl get rs -n production -l app=api
kubectl get pods -n production -l app=apibehavior:
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Percent
value: 100
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 600
policies:
- type: Percent
value: 10
periodSeconds: 60业务工作负载
|
|-- 合理的 resources.requests
|-- Readiness/Startup Probe
|-- 可横向扩展
|-- 明确的单 Pod 容量
|
v
指标系统
|
|-- metrics-server
|-- Prometheus
|-- Custom Metrics Adapter
|-- KEDA
|
v
HPA
|
|-- minReplicas
|-- maxReplicas
|-- metrics
|-- behavior
|
v
Deployment/StatefulSet
|
v
Scheduler
|
v
Cluster Autoscaler
|
v
Service/Ingress/Gateway
|
v
下游数据库、缓存、消息系统[ ] 指标真正代表业务压力
[ ] 指标链路具备高可用
[ ] request 配置合理
[ ] Pod 能够真正横向扩展
[ ] Readiness 准确
[ ] 启动时间已测量
[ ] minReplicas 能承受基础故障
[ ] maxReplicas 不超过下游容量
[ ] 扩容速度足够
[ ] 缩容不会造成抖动
[ ] Service 能及时接入新 Pod
[ ] Cluster Autoscaler 有容量
[ ] GitOps 不覆盖 HPA 副本数
[ ] HPA 与 VPA 没有冲突
[ ] 指标异常有告警和降级方案
[ ] 已进行压力、发布、故障和缩容演练看什么指标
什么时候扩容
扩多少
新 Pod 多久可用
节点是否放得下
下游是否承受得住
什么时候缩容
缩容是否影响连接和缓存
指标失效时如何兜底