上一章讲了 Volume。本章讲 HPA(Horizontal Pod Autoscaler),让 Pod 数量根据负载自动增减。
9.1 为什么需要 HPA
业务流量不是均匀的。电商大促时流量翻十倍,深夜流量可能降到十分之一。手动扩容有几个问题:
- 人不可能 24 小时盯着监控
- 扩容速度跟不上流量峰值
- 缩容不及时造成资源浪费
HPA 的作用就是:根据 CPU、内存或自定义指标,自动调整 Pod 副本数。
CPU 高 → HPA 增加 Pod
CPU 低 → HPA 减少 Pod
9.2 HPA 依赖什么
HPA 需要知道 Pod 的实时指标,这依赖 Metrics Server 或 Prometheus。
9.2.1 Metrics Server
Metrics Server 是 K8s 官方推荐的轻量级指标采集器,默认每 15 秒采集一次 CPU 和内存使用率。
安装:
$ kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
安装后验证:
$ kubectl top node
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
k8s-master 250m 12% 2048Mi 34%
k8s-node1 180m 9% 1536Mi 25%
k8s-node2 160m 8% 1408Mi 22%
$ kubectl top pod
NAME CPU(cores) MEMORY(bytes)
nginx-7c4d9f8b5c-2jx 5m 12Mi
如果 kubectl top 报 "Metrics API not available",说明 Metrics Server 没装好。
9.2.2 Prometheus adapter
HPA 默认只能用 CPU 和内存。如果想根据 QPS、队列长度、消息积压等自定义指标扩容,需要 Prometheus + prometheus-adapter。
应用暴露指标 → Prometheus 抓取 → adapter 注册为 K8s metrics API → HPA 读取
企业级弹性伸缩通常都会上 Prometheus + adapter,配合自定义指标。
9.3 HPA 的核心字段
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: 50
| 字段 | 含义 |
|---|---|
scaleTargetRef | 要自动伸缩的目标,比如 Deployment |
minReplicas | 最小副本数,即使负载为 0 也不低于这个数 |
maxReplicas | 最大副本数,防止无限扩容 |
metrics | 触发扩容的指标 |
averageUtilization | 目标 CPU 利用率 |
9.4 targetCPUUtilizationPercentage 的坑
初学者常遇到 HPA 不生效,其中一个原因是:Pod 没有设置 resources.requests。
HPA 计算利用率时,分母是 requests.cpu,不是 limits.cpu。如果 Pod 没配 requests,HPA 不知道 "利用率" 是相对于多少,就无法计算。
resources:
requests:
cpu: "200m"
limits:
cpu: "500m"
上面的配置,HPA 目标是 50%,即当 CPU 使用超过 100m 时,开始扩容。
老版本 HPA 用 targetCPUUtilizationPercentage 字段:
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
spec:
targetCPUUtilizationPercentage: 50
v2 版本更灵活,支持多指标、自定义指标、更精细的扩缩行为。
9.5 scale up 和 scale down 行为
HPA 的扩缩行为默认比较简单:每 30 秒检查一次,根据指标决定是否要扩缩。v2 版本可以配置更精细的行为。
spec:
behavior:
scaleUp:
stabilizationWindowSeconds: 60
policies:
- type: Percent
value: 100
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Pods
value: 1
periodSeconds: 60
| 字段 | 含义 |
|---|---|
stabilizationWindowSeconds | 指标稳定窗口,防止抖动 |
scaleUp | 扩容策略 |
scaleDown | 缩容策略 |
policies | 每次最多扩/缩多少 |
scaleDown.stabilizationWindowSeconds: 300 表示缩容前先看 5 分钟指标,避免流量短暂下降就急着缩容。扩容通常可以更激进,缩容要保守。
9.6 实战:HPA 配置与压力测试
先创建一个带资源声明的 Deployment:
# web-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: nginx:alpine
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "200m"
memory: "256Mi"
ports:
- containerPort: 80
创建 HPA:
# web-hpa.yaml
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: 50
应用并查看:
$ kubectl apply -f web-deployment.yaml -f web-hpa.yaml
$ kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
web-hpa Deployment/web 0%/50% 2 10 2 1m
对 Service 进行压力测试:
$ kubectl run -it --rm load --image=busybox:1.28 --restart=Never -- sh
# 在容器内执行
$ while true; do wget -q -O- http://web; done
或者用 ab、wrk 等工具:
# 在集群内临时起一个压力测试 Pod
$ kubectl run -it --rm load --image=williamyeh/wrk --restart=Never -- \
-t4 -c100 -d60s http://web
观察 HPA 变化:
$ kubectl get hpa -w
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS
web-hpa Deployment/web 75%/50% 2 10 4
web-hpa Deployment/web 82%/50% 2 10 6
web-hpa Deployment/web 60%/50% 2 10 8
停止压测后,过一段时间副本数会逐步降下来。
9.7 HPA 的局限与注意事项
| 问题 | 说明 |
|---|---|
| 需要配 requests | 没有 CPU requests 时 HPA 无法计算利用率 |
| 扩容有延迟 | 默认 30 秒检查一次, metrics 采集也有延迟 |
| 冷启动问题 | 新 Pod 启动慢,流量高峰可能已经过了 |
| 缩容冷却 | 默认缩容有 5 分钟稳定窗口 |
| 只能水平扩容 | HPA 增加 Pod 数量,不能扩大单个 Pod 资源 |
| 不能缩到 0 | 传统 HPA minReplicas 不能为 0,KEDA 可以 |
企业级弹性方案通常不是只用 HPA,而是组合使用:
- HPA 做 Pod 水平扩缩
- VPA 做 Pod 资源垂直调整
- Cluster Autoscaler 做节点水平扩缩
- KEDA 做事件驱动缩容(包括缩到 0)
9.8 本章小结
- HPA 根据指标自动调整 Pod 副本数
- CPU 指标依赖 Metrics Server,自定义指标需要 Prometheus + adapter
averageUtilization的分母是resources.requests.cpu- v2 版本支持多指标和精细的扩缩行为控制
- 缩容要比扩容保守,用 stabilizationWindowSeconds 避免抖动
- HPA 是弹性伸缩的基础,但不是全部
9.9 课后练习
- 安装 Metrics Server,确认
kubectl top node和kubectl top pod能正常输出。 - 创建一个带 CPU requests 的 Deployment,并配置 HPA 目标 50%。
- 对 Service 加压,观察副本数从 2 扩到 10 的过程。
- 停止压测,观察缩容过程,理解
stabilizationWindowSeconds的作用。