3. Horizontal Pod Autoscaler基础
Horizontal Pod Autoscaler(HPA)是 OpenShift 中最常用的工作负载水平伸缩控制器。它不直接创建 Pod,而是通过调整 Deployment、ReplicaSet、StatefulSet 等可伸缩对象的 replicas 字段,间接改变实际运行的 Pod 数量。理解 HPA,关键要抓住四件事:控制回路如何运转、指标从哪里来、期望副本数怎么算、以及为什么需要冷却窗口。
一、HPA 的控制回路
HPA 本质上是一个周期性运行的负反馈控制回路。它每隔一段时间(OpenShift 默认约 15 秒,由 --horizontal-pod-autoscaler-sync-period 控制)执行一次同步:从指标源采集当前指标,与用户设定的目标值比较,计算出一个期望副本数,再通过 Scale 子资源把副本数写入目标工作负载。整个过程可以概括为“采集 → 比较 → 计算 → 写入 → 等待下一轮”。
需要特别注意的是,HPA 只负责“决定要几个副本”,真正把 Pod 调度、拉镜像、启动起来的是 Deployment/ReplicaSet 控制器和调度器。因此从 HPA 调整副本数到新 Pod 真正 Ready 并开始分担流量,存在明显延迟。这个延迟正是冷却窗口和稳定窗口存在的原因。
二、指标来源:HPA 看什么
HPA 支持三类指标,它们决定了 HPA 能“感知”什么:
- 资源指标:CPU 和内存利用率,来自 metrics-server。这是最常见、最容易上手的来源。利用率是相对于 Pod 中容器
resources.requests的百分比,而不是相对于节点容量或 limit。 - 自定义指标:来自应用自身暴露的指标,例如每秒请求数、队列长度,通过 Prometheus Adapter 等适配器接入。
- 外部指标:来自集群外部系统,例如云消息队列积压量、云监控指标。
这里有一个极易踩坑的点:资源指标的分母是 requests,不是 limit。如果某个容器没有设置 CPU requests,HPA 就无法计算该 Pod 的 CPU 利用率,会直接报错或跳过。因此在启用 HPA 前,必须为容器设置合理的 requests。例如一个容器设置 requests.cpu: 200m,当它实际使用 100m 时,利用率就是 50%。
三、目标值计算:期望副本数怎么来
HPA 的核心公式是:
期望副本数 = ceil( 当前副本数 × ( 当前指标值 / 目标指标值 ) )
以 CPU 利用率为例,假设当前有 4 个副本,目标 CPU 利用率设为 60%,而当前平均利用率是 90%,则:
期望副本数 = ceil( 4 × ( 90% / 60% ) ) = ceil(6) = 6
HPA 会把副本数从 4 调到 6。反过来,如果当前平均利用率降到 30%,则 ceil(4 × 0.5) = 2,HPA 会尝试缩到 2 个副本。计算完成后,结果还会被 minReplicas 和 maxReplicas 夹紧,防止越界。
需要理解的是,HPA 使用的是“当前副本数”而不是“上一轮期望值”,并且每轮都重新采集指标。这意味着指标波动会直接反映到副本数上,这也是为什么需要稳定窗口来平滑抖动。
四、冷却窗口与稳定窗口
如果 HPA 每 15 秒就根据瞬时指标调整一次副本数,系统会剧烈震荡:扩容后指标下降,立刻缩容,缩容后指标又上升,再扩容。为避免这种抖动,HPA 引入了两个时间维度的保护:
| 窗口类型 | 默认值 | 作用 |
|---|---|---|
| 扩容稳定窗口 | 0 秒 | 允许快速扩容,及时应对突发流量 |
| 缩容稳定窗口 | 300 秒 | 缩容前观察一段时间,取窗口内最大推荐值,避免误缩 |
| 同步周期 | 约 15 秒 | HPA 重新采集指标并计算的间隔 |
缩容稳定窗口的逻辑是:HPA 会记录过去 300 秒内所有计算出的期望副本数,缩容时取其中的最大值作为最终结果。也就是说,即使当前指标显示可以缩到 2 个副本,只要过去 5 分钟内曾推荐过 5 个副本,HPA 仍会保持 5 个,直到这个高推荐值滑出窗口。扩容方向则不受此限制,可以立即执行。
五、一个可参考的 HPA 配置示例
下面是一个基于 CPU 利用率的 HPA 示例,目标利用率 60%,副本范围 2 到 10:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web-hpa
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:
scaleDown:
stabilizationWindowSeconds: 300
scaleUp:
stabilizationWindowSeconds: 0
要让这个 HPA 正常工作,Deployment 中的容器必须设置 CPU requests,例如 requests.cpu: 200m。部署后可以用 oc get hpa web-hpa 观察 TARGETS 列,它会显示类似 45%/60% 的当前值与目标值对比;oc describe hpa web-hpa 则能看到最近的事件、计算过程和是否触发了稳定窗口。
TARGETS 显示 <unknown>/60%,通常说明 metrics-server 未就绪,或容器缺少 CPU requests。此时 HPA 不会调整副本数,需要先排查指标链路。