4. 基于CPU与内存的HPA实战
Horizontal Pod Autoscaler(HPA)是 OpenShift 中实现工作负载水平弹性伸缩的核心控制器。它并不直接创建 Pod,而是通过持续读取指标、计算期望副本数,再修改目标 Deployment(或 ReplicaSet、StatefulSet 等)的 spec.replicas 字段,由 Deployment 控制器完成实际的 Pod 增减。理解这条“指标采集 → 期望副本计算 → 修改副本数 → 控制器扩缩”的链路,是本节实战的关键。
HPA 的期望副本数由如下公式决定:
desiredReplicas = ceil( currentReplicas × ( currentMetricValue / targetMetricValue ) )
其中 currentMetricValue 是所有目标 Pod 指标的平均值(例如平均 CPU 使用率),targetMetricValue 是 HPA 中设定的目标值。举例来说,若当前有 2 个副本,平均 CPU 使用率为 80%,目标为 50%,则期望副本数为 ceil(2 × 80/50) = ceil(3.2) = 4。这个公式决定了 HPA 的伸缩方向与幅度,也是观察负载变化时判断“为什么扩到 4 个而不是 3 个”的依据。
前置条件:Deployment 必须声明资源 requests
HPA 计算 CPU 使用率时,分母是 Pod 的 CPU requests,而不是 limits,也不是节点容量。因此目标 Deployment 的容器必须显式声明 resources.requests.cpu,否则 HPA 无法计算百分比,会报 missing request for cpu 并停止伸缩。内存指标同理,需要 resources.requests.memory。下面是一个可用的 Deployment 片段:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-frontend
namespace: demo-hpa
spec:
replicas: 2
selector:
matchLabels:
app: web-frontend
template:
metadata:
labels:
app: web-frontend
spec:
containers:
- name: app
image: quay.io/example/web-frontend:1.0
ports:
- containerPort: 8080
resources:
requests:
cpu: "200m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "512Mi"
这里 requests.cpu 为 200m,意味着单个 Pod 的 CPU 使用率 100% 对应 200m 的实际用量。若 HPA 目标设为 60%,则每个 Pod 平均使用 120m 时即达到目标。
方式一:使用 oc 命令快速创建 HPA
OpenShift 的 oc autoscale 命令可以在一条命令内完成 HPA 创建,适合快速验证:
oc autoscale deployment/web-frontend \
--name=web-frontend-hpa \
--min=2 --max=8 \
--cpu-percent=60 \
-n demo-hpa
参数含义:--min 与 --max 限定副本数区间,HPA 永远不会把副本数调整到该区间之外;--cpu-percent=60 表示目标平均 CPU 使用率为 60%。创建后可用 oc get hpa -n demo-hpa 查看,TARGETS 列会显示类似 3%/60% 的当前值与目标值。
方式二:使用 YAML 定义,支持多指标
当需要同时基于 CPU 和内存伸缩,或需要更精细的行为控制时,应使用 YAML 定义。以下示例同时配置 CPU 与内存两个指标:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web-frontend-hpa
namespace: demo-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web-frontend
minReplicas: 2
maxReplicas: 8
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 75
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 50
periodSeconds: 60
多指标时,HPA 会分别计算每个指标对应的期望副本数,然后取最大值作为最终结果。也就是说,只要 CPU 或内存任一指标要求更多副本,就会按更大的那个扩。这保证了不会因为某一维度被忽略而出现瓶颈。behavior.scaleDown.stabilizationWindowSeconds: 300 表示缩容前会观察 5 分钟内的历史推荐值,取其中最大值,避免负载短暂回落就立即缩容造成抖动。
观察负载变化下的副本调整
创建 HPA 后,可用 oc get hpa web-frontend-hpa -n demo-hpa -w 持续观察。为了制造负载,可对 Service 发起压测,例如使用 hey 或 ab 持续请求:
oc run load-generator --image=williamyeh/hey --restart=Never -n demo-hpa \
-- -z 5m -c 50 http://web-frontend.demo-hpa.svc.cluster.local:8080/
随着请求量上升,平均 CPU 使用率会从个位数攀升。当超过 60% 时,HPA 开始扩容,副本数从 2 逐步增加到 4、6,直至接近 maxReplicas=8 或负载被摊薄到目标值以下。压测结束后,CPU 回落,HPA 在 stabilizationWindow 结束后开始缩容,副本数逐步回到 minReplicas=2。整个过程可通过 oc get pods -n demo-hpa -w 看到 Pod 的创建与终止。
结果判读与常见问题
观察 HPA 时,重点看三列:TARGETS 显示当前指标与目标值,MINPODS/MAXPODS 显示区间,REPLICAS 显示当前副本数。若 TARGETS 长期显示 <unknown>/60%,通常说明 Metrics Server 未就绪或 Pod 缺少 requests;若副本数在目标值附近反复跳动,可适当增大 stabilizationWindowSeconds 或调整目标值留出缓冲。扩容受 maxReplicas 限制,缩容受 minReplicas 限制,这两个值应结合节点容量与业务最低可用副本数设定,而不是随意取大。
spec.replicas 存在“争夺”:若手动 oc scale 修改副本数,HPA 会在下一次同步时按计算结果覆盖。需要临时固定副本数时,应先暂停或删除 HPA。完成本节实战后,应能独立完成:为带 requests 的 Deployment 创建 HPA、用 oc 与 YAML 两种方式定义、通过压测观察副本从 2 扩到 8 再缩回 2 的完整过程,并能根据 TARGETS 与事件判断伸缩是否符合预期。