1. HPA 基础概念

1.1 什么是 HPA

HPA(Horizontal Pod Autoscaler) 是 Kubernetes 内置的水平 Pod 自动扩缩容控制器。它根据用户定义的指标(如 CPU 使用率、内存使用率或自定义业务指标)动态调整工作负载(Deployment、StatefulSet 等)的 Pod 副本数量,使应用始终运行在期望的负载水平上。

核心定义:HPA 是一个控制循环,定期(默认每 15 秒)检查目标指标值,计算期望副本数,然后通过修改工作负载的 replicas 字段完成扩缩容操作。

1.2 HPA 在 Kubernetes 中的角色

HPA 位于 Kubernetes 控制平面的 kube-controller-manager 组件中,属于自动扩缩容体系的核心成员。它与集群中的其他组件协作,形成完整的弹性伸缩链路:

HPA 在 Kubernetes 控制平面中的角色 用户 / 运维 HPA 控制器 kube-controller-manager 内 查询指标 Metrics Server 更新 replicas Deployment / StatefulSet Pod 副本组 HPA 通过 Metrics Server 获取 Pod 指标 → 计算期望副本数 → 更新工作负载的 replicas 字段

HPA 在集群中的关键职责包括:

  • 指标采集:通过 Metrics Server 或自定义 API 获取 Pod 的实时资源使用数据。
  • 副本计算:根据当前指标值与目标值的偏差,计算所需的 Pod 副本数。
  • 滚动更新协调:与 Deployment 的滚动更新策略协同,避免扩缩容与发布冲突。
  • 稳定性保护:内置冷却窗口和速率限制,防止频繁抖动。

1.3 HPA 与手动扩缩容的对比

手动扩缩容是运维人员通过 kubectl scale 命令或修改 YAML 文件中的 replicas 字段来调整 Pod 数量。HPA 则实现了自动化、指标驱动的弹性伸缩。两者在多个维度存在显著差异:

对比维度 手动扩缩容 HPA 自动扩缩容
触发方式 人工执行命令或修改配置 基于指标阈值自动触发
响应速度 取决于运维响应时间(分钟级) 秒级至分钟级(取决于指标采集周期)
准确性 依赖经验判断,容易过度或不足 基于实时数据,精确匹配负载需求
运维成本 高,需要 7×24 值班关注 低,配置后自动运行
适用场景 固定负载、计划性扩容、故障应急 波动负载、潮汐流量、微服务弹性
资源利用率 通常偏低(预留余量) 高,按需分配
风险控制 人工审核,风险可控但慢 需配置限速和冷却,防止震荡
实践建议:在生产环境中,不要同时对一个工作负载使用手动扩缩容和 HPA。手动修改 replicas 会被 HPA 的下一次调协覆盖,导致预期外的副本数变化。如果必须临时调整,建议先暂停 HPA(kubectl scale hpa <name> --replicas=0)或使用 kubectl autoscale 的 --min/--max 参数限制范围。

1.4 HPA 的工作流程

HPA 控制器的每个调协周期(默认 15 秒)执行以下步骤:

  1. 获取目标工作负载:从 API Server 获取 HPA 对象关联的 Scale 子资源(Deployment/StatefulSet)。
  2. 采集指标数据:通过 metrics API 获取所有 Pod 的当前指标值(CPU、内存或自定义指标)。
  3. 计算期望副本数:使用公式 期望副本数 = ceil(当前副本数 × (当前指标值 / 目标指标值))。
  4. 应用约束:将期望副本数限制在 HPA 定义的 minReplicas 和 maxReplicas 范围内。
  5. 执行扩缩容:通过 API Server 更新工作负载的 replicas 字段,触发控制器创建或删除 Pod。
HPA 单次调协周期流程 1. 获取工作负载 2. 采集指标 3. 计算期望副本 4. 应用约束 5. 更新 replicas 核心计算公式 期望副本数 = ceil( 当前副本数 × ( 当前指标值 / 目标指标值 ) ) 冷却窗口:扩容冷却默认 3 分钟,缩容冷却默认 5 分钟,防止频繁震荡 可通过 --horizontal-pod-autoscaler-downscale-stabilization 等 kube-controller-manager 参数调整
常见误区:HPA 的副本计算公式是比例放大/缩小,而非线性增减。例如,当前 10 个 Pod,CPU 使用率为 80%(目标 50%),则期望副本数 = ceil(10 × (80/50)) = ceil(16) = 16 个 Pod。这意味着 HPA 会一次性扩容 6 个 Pod,而不是逐个增加。