4. HPA实战
前几节我们已经理解了 HPA 的控制器循环、指标来源与扩缩容算法。本节把视角落到工程现场:部署一个可观测的示例应用,为它配置同时基于 CPU 与内存的 HPA,再用压测制造负载,最后从指标、副本数和事件三个维度判断扩缩容是否按预期发生。整个过程的目标不是"跑通命令",而是建立一条可复现的验证链路:负载输入 → 指标变化 → HPA 决策 → 副本调整 → 结果判读。
一、准备示例应用与资源请求
HPA 的利用率是"实际用量 ÷ 请求值"的百分比,因此示例应用必须显式声明 requests,否则 CPU 利用率无法计算,HPA 会报 <unknown> 并拒绝扩缩容。下面部署一个基于 registry.k8s.io/hpa-example 的 PHP-Apache 应用,它会在收到请求时消耗 CPU,便于压测。
apiVersion: apps/v1
kind: Deployment
metadata:
name: php-apache
spec:
replicas: 1
selector:
matchLabels:
app: php-apache
template:
metadata:
labels:
app: php-apache
spec:
containers:
- name: php-apache
image: registry.k8s.io/hpa-example
ports:
- containerPort: 80
resources:
requests:
cpu: 200m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
---
apiVersion: v1
kind: Service
metadata:
name: php-apache
spec:
selector:
app: php-apache
ports:
- port: 80
targetPort: 80
这里把 CPU 请求设为 200m、内存请求设为 128Mi,是后续利用率计算的基准。注意 limits 与 requests 的差距不宜过大,否则 CPU 会被限流(throttling),表现为"负载很高但利用率上不去",干扰判断。应用就绪后,用 kubectl get pods 确认 Pod 处于 Running 且 Ready。
二、配置同时基于 CPU 与内存的 HPA
HPA 支持在 metrics 列表中声明多个指标,控制器会分别计算每个指标建议的副本数,并取最大值作为最终期望副本数。这是多指标 HPA 最关键的行为,也是本节验证的重点之一。
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: php-apache
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: php-apache
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 70
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 100
periodSeconds: 15
CPU 目标设为 50%,内存目标设为 70%。behavior.scaleDown.stabilizationWindowSeconds: 300 表示缩容前会回看最近 5 分钟的建议值并取最大,避免负载抖动导致副本数反复震荡。应用后可用 kubectl get hpa php-apache -w 持续观察,初始 TARGETS 应显示类似 1%/5% 的低利用率。
三、压测与观察
启动一个临时压测 Pod,向 Service 持续发起请求。这里用无限循环模拟稳定负载,便于观察 HPA 的持续响应:
kubectl run -i --tty load-generator --rm --image=busybox:1.36 --restart=Never -- \
/bin/sh -c "while sleep 0.01; do wget -q -O- http://php-apache; done"
另开一个终端执行 kubectl get hpa php-apache -w,可以观察到 TARGETS 从 1%/5% 逐步攀升。假设在某个采样点 CPU 利用率达到 200%、内存利用率达到 90%,按算法:CPU 分支 ceil(1 × 200% / 50%) = 4,内存分支 ceil(1 × 90% / 70%) = 2,取最大值后期望副本数为 4。这与上方 SVG 中的示例一致。随后 kubectl get deploy php-apache 会显示副本数从 1 增加到 4,kubectl get pods 能看到新 Pod 陆续创建。
--horizontal-pod-autoscaler-sync-period),且指标本身有采集延迟,因此从压测开始到副本数变化通常需要 30~60 秒,属于正常现象,不要误判为配置失效。四、结果分析与常见异常判读
停止压测(在 load-generator 终端按 Ctrl+C)后,CPU 利用率会快速回落,但副本数不会立即下降。由于配置了 300 秒的缩容稳定窗口,HPA 会回看最近 5 分钟的建议值并取最大,因此大约 5 分钟后副本数才逐步回落到 1。这正是 stabilizationWindowSeconds 的作用:用时间换稳定,抑制抖动。
验证过程中常见的异常及判读方式如下:
| 现象 | 可能原因 | 排查方向 |
|---|---|---|
TARGETS 显示 <unknown> | 缺少 requests 或 metrics-server 不可用 | 检查 Deployment 的 requests;kubectl top pods 是否可用 |
| CPU 利用率上不去但负载很高 | CPU 被 limits 限流 | 查看容器 throttling 指标,适当提高 limits |
| 副本数不增加 | 已达 maxReplicas,或未超过目标阈值 | 检查 kubectl describe hpa 的 Events 与当前副本数 |
| 副本数反复震荡 | 缩容窗口过短或指标抖动 | 增大 stabilizationWindowSeconds |
| 内存指标始终偏低 | 应用内存占用平稳,未随请求增长 | 属正常,此时由 CPU 分支主导扩容 |