HPA 详解:Kubernetes 的水平自动扩缩容机制

This article is extracted from the chat log with AI. Please identify it with caution.

说明:本文由 Codex 根据作者提供的主题、素材与公开资料辅助生成,属于 AI 生成/整理内容,非作者原创。请读者自行甄别并交叉验证。

HPA 是什么#

HPA 是 Horizontal Pod Autoscaler,也就是水平 Pod 自动扩缩容。

它做的事情很明确:

根据指标变化,自动调整某个工作负载的副本数。

它通常作用在 Deployment、ReplicaSet、StatefulSet 这类支持 scale 子资源的对象上。

HPA 不负责:

  • 修改单个 Pod 的 CPU 或内存 request。
  • 增加或减少节点数量。
  • 判断业务是否真的健康。
  • 替应用解决启动慢、连接耗尽、数据库瓶颈等问题。

可以先用一句话记住:

HPA 调 Pod 数量,VPA 调 Pod 资源规格,Cluster Autoscaler 调节点数量。

HPA 的控制循环#

HPA Controller 会周期性执行控制循环:

1. 找到 HPA 绑定的 scaleTargetRef
2. 读取目标对象当前副本数
3. 从 metrics API 读取指标
4. 按算法计算期望副本数
5. 通过 scale 子资源更新目标对象 replicas

典型链路是:

metrics-server / custom metrics adapter / external metrics adapter
metrics.k8s.io / custom.metrics.k8s.io / external.metrics.k8s.io
HPA Controller
Deployment scale subresource
ReplicaSet
Pod

所以 HPA 不工作时,排查重点通常是:

  • HPA 对象是否写对。
  • 目标对象是否支持 scale。
  • metrics API 是否可用。
  • Pod 是否有资源 request。
  • 当前指标是否真的超过阈值。

基本计算公式#

HPA 的核心公式可以理解为:

期望副本数 = ceil(当前副本数 × 当前指标值 / 目标指标值)

比如:

当前副本数:3
目标 CPU 利用率:60%
当前平均 CPU 利用率:90%

期望副本数 = ceil(3 × 90 / 60) = 5

如果当前平均 CPU 只有 30%:

期望副本数 = ceil(3 × 30 / 60) = 2

实际控制过程中还会受到这些因素影响:

  • minReplicasmaxReplicas
  • 控制器同步周期。
  • 扩缩容容忍区间。
  • 缺失指标和未 Ready Pod 的保守处理。
  • scaleUp / scaleDown 行为策略。
  • 稳定窗口,尤其是缩容稳定窗口。

所以看到 HPA 没有立刻扩缩容,不一定代表它坏了。

CPU 利用率和 request 的关系#

最常见的 HPA 配置是按 CPU 利用率扩缩容。

这里的利用率不是节点 CPU 使用率,而是相对于 Pod 容器 resources.requests.cpu 的比例。

例如容器配置:

resources:
  requests:
    cpu: 500m

如果当前使用 250m,则利用率大约是 50%。

如果没有设置 CPU request,HPA 很难计算 CPU utilization 类型指标。

这是 HPA 排查里最常见的问题之一:

HPA 使用 CPU utilization 时,Pod 必须有 CPU request。

一个 autoscaling/v2 示例#

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: web
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 60
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 0
      policies:
        - type: Percent
          value: 100
          periodSeconds: 60
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
        - type: Percent
          value: 50
          periodSeconds: 60

这份配置表达的是:

  • 副本数最少 2,最多 10。
  • 平均 CPU 利用率目标是 60%。
  • 扩容可以比较快。
  • 缩容会参考 300 秒稳定窗口,避免刚降下来又升上去。

指标来源#

HPA 支持多类指标。

指标类型API典型来源场景
Resourcemetrics.k8s.iometrics-serverCPU、Memory
Podscustom.metrics.k8s.ioPrometheus Adapter 等每个 Pod 的业务指标
Objectcustom.metrics.k8s.ioPrometheus Adapter 等Ingress QPS、队列长度等
Externalexternal.metrics.k8s.io外部指标适配器云队列长度、消息积压、第三方指标

Resource 指标适合入门,但它不一定最符合业务。

例如:

  • Web 服务可以考虑 QPS、并发请求数、P95 延迟等指标。
  • Worker 可以考虑队列长度、消息积压时间。
  • 推理服务可以考虑 GPU 利用率、请求排队时间。

不过越接近业务的指标,越要注意指标延迟、噪声和扩缩容后的反馈时间。

HPA、Deployment 和滚动更新#

HPA 通常和 Deployment 一起使用。

关系是:

HPA 修改 Deployment.spec.replicas
Deployment 控制 ReplicaSet
ReplicaSet 创建或删除 Pod

如果同时有人手动执行:

kubectl scale deployment web --replicas=3

HPA 仍会在下一轮控制循环里根据指标重新调整副本数。

所以启用 HPA 后,不建议再把副本数当成完全手工维护的值。

更好的做法是:

  • GitOps 或 YAML 中保留 HPA 配置。
  • Deployment 中给一个合理初始 replicas。
  • 运行后由 HPA 接管波动范围。

什么时候适合 HPA#

适合:

  • 无状态 Web 服务。
  • 可以水平扩展的 API 服务。
  • 消费队列的 Worker。
  • 流量有明显峰谷的服务。
  • 扩容后能较快分担压力的服务。

不太适合:

  • 单副本强状态服务。
  • 启动非常慢的服务。
  • 扩容不能改善瓶颈的服务,例如数据库已经成为瓶颈。
  • 对连接状态极其敏感,且没有优雅下线能力的服务。
  • 指标延迟很大或波动很剧烈的场景。

HPA 的前提是:

增加 Pod 副本,确实能提升处理能力。

如果瓶颈在数据库、锁、外部 API、磁盘 IO,HPA 只会增加更多等待者。

和 Cluster Autoscaler 的关系#

HPA 只负责创建更多 Pod。

如果集群节点资源不够,新 Pod 会 Pending。

这时需要 Cluster Autoscaler 或类似节点扩容机制把 Node 加进来。

链路是:

指标升高
HPA 增加 replicas
新 Pod Pending,因为节点资源不足
Cluster Autoscaler 增加节点
调度器把 Pod 放到新节点

所以线上自动扩容通常是组合拳:

HPA + 合理 requests/limits + Cluster Autoscaler + PodDisruptionBudget + 优雅退出

常见排查命令#

# 查看 HPA 当前状态
kubectl get hpa
kubectl describe hpa web

# 查看目标 Deployment
kubectl get deploy web
kubectl describe deploy web

# 查看 Pod 资源指标
kubectl top pod -l app=web
kubectl top pod -A

# 直接检查 metrics API
kubectl get --raw /apis/metrics.k8s.io/v1beta1/pods
kubectl get --raw /apis/metrics.k8s.io/v1beta1/nodes

# 查看 metrics-server
kubectl -n kube-system get deploy metrics-server
kubectl -n kube-system logs deploy/metrics-server --tail=100

kubectl describe hpa 很关键,它会显示当前指标、目标指标、无法扩缩容的原因和事件。

常见问题#

HPA 显示 unknown#

常见原因:

  • metrics-server 没有安装或不可用。
  • Pod 缺少 CPU request。
  • metrics API 聚合层异常。
  • 目标对象没有可读指标。

CPU 很高但不扩容#

检查:

  • 是否超过 maxReplicas
  • HPA 指标类型是不是写成了 AverageValueUtilization
  • Pod 是否有 CPU request。
  • 当前平均值是否真的超过目标值。
  • HPA 是否处在稳定窗口或策略限制内。

扩容了但服务仍然慢#

HPA 只说明 Pod 数量增加了,不说明系统瓶颈消失了。

继续看:

  • 应用启动时间。
  • readinessProbe 是否过早放流量。
  • 数据库连接池。
  • 下游 API 限流。
  • 队列消费速度。
  • 节点资源和调度情况。

频繁扩缩容#

可以调整:

  • 指标选择,避免过于抖动的指标。
  • behavior.scaleDown.stabilizationWindowSeconds
  • scaleUp / scaleDown policies。
  • minReplicas,保留基础容量。
  • 应用缓存和连接预热策略。

总结#

HPA 的本质是一个控制器:

观察指标 -> 计算期望副本数 -> 更新 scale 子资源。

它非常适合无状态、可水平扩展、指标反馈及时的服务。

但它不是容量治理的全部。真正稳定的自动扩缩容,需要同时处理资源 request、指标体系、节点扩容、应用启动、优雅退出和下游瓶颈。


参考资料#

本文共 2305 字,创建于 Jun 28, 2026

相关标签: Kubernetes, DevOps, ByAI