HPA 水平自动扩缩
本教程共 65 篇 · 第 48 篇 · 更新于 2026-08-14 · 约 16 分钟阅读
本节目标:搞懂 HPA 为什么能”按需增减副本”,会用
autoscaling/v2写一个基于 CPU 的扩缩规则,并理解它的伸缩算法、扩缩行为和那些容易踩的坑。
白天流量高,你希望多开几个 Pod 一起扛。深夜流量低,你希望关掉多余 Pod 省资源。这种”看指标办事”的活儿,不用你半夜爬起来敲命令——交给 HPA 就行。
HPA 的全名是 HorizontalPodAutoscaler,意思是”水平 Pod 自动扩缩器”。它盯着某个工作负载(通常是 Deployment 或 StatefulSet),根据实时指标自动改它的副本数。注意是”水平”——加的是 Pod 个数,不是给单个 Pod 加 CPU。给单个 Pod 加资源那是第 49 章的 VPA 管的事。
48-1 什么是水平扩缩
先分清两个方向,很多人会混:
- 水平扩缩(Horizontal):负载高了就多跑几个 Pod。好比多开几条收银台。
- 垂直扩缩(Vertical):给正在跑的 Pod 加更多 CPU 或内存。好比把一条收银台加宽。
Kubernetes 里 HPA 负责前者,VPA 负责后者。本章只讲 HPA。
HPA 本身也是一个 Kubernetes 对象,类型是 HorizontalPodAutoscaler。你创建它,它就常驻在集群里,由一个控制器每 15 秒轮询一次指标(这个间隔由 --horizontal-pod-autoscaler-sync-period 控制,默认 15 秒)。
NoteHPA 管理的目标是带
scale子资源的对象,最常见的是 Deployment 和 StatefulSet。DaemonSet 没有副本数的概念,所以不能挂 HPA。
48-2 HPA 的工作原理
HPA 控制器做四件事,可以按这个顺序理解:
- 拿到你指定的目标对象(比如名叫
web的 Deployment)。 - 通过
scaleTargetRef找到它,问 Metrics 接口要指标。 - 拿”当前指标值”和”你期望的指标值”算一个比例,推出”想要几个副本”。
- 把目标对象的
.spec.replicas改成这个数,后面的 Deployment 控制器再去增删 Pod。
指标从哪来?最常见的是 metrics.k8s.io 这个 API,它由 Metrics Server 提供。注意 Metrics Server 不是默认装的,生产集群通常要单独部署。没有它,HPA 拿不到 CPU/内存数据,只能干瞪眼。
伸缩的核心算法很朴素,一句话:
期望副本数 = ceil( 当前副本数 × 当前指标值 ÷ 期望指标值 )
举例:现在 4 个副本,平均 CPU 用到 200m,你期望 100m。比例就是 200÷100=2,期望副本 = 4×2 = 8 个。反之如果 CPU 只有 50m,比例 0.5,期望副本 = 2 个,于是缩容。
Tip比例太接近 1 时 HPA 不动手。默认容差是 10%(即 0.9~1.1 之间不扩不缩),避免指标抖动导致副本数反复横跳。
48-3 用 autoscaling/v2 定义 HPA
v1.36 请直接用 autoscaling/v2。它相比老版本最大的好处是 metrics 变成了数组,可以挂多个指标,还支持内存、自定义、对象、外部指标。
下面是一个最典型的”按 CPU 利用率扩缩”的写法:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web-hpa
spec:
# 1. 绑定目标:要扩缩谁
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web
# 2. 副本数上下限
minReplicas: 2
maxReplicas: 10
# 3. 指标列表(v2 用数组)
metrics:
- type: Resource
resource:
name: cpu # 也可以是 memory
target:
type: Utilization # 按"利用率百分比"算
averageUtilization: 60
这里 type: Utilization + averageUtilization: 60 表示:希望所有 Pod 的平均 CPU 利用率维持在 60%。
Warning用 CPU 做指标,目标 Pod 的容器必须设了
resources.requests.cpu。不然 HPA 不知道”请求的 100%“是多少,会报<unknown>且无法计算。内存指标同理,要设requests.memory。
想用”绝对数值”而不是百分比?把 target.type 改成 AverageValue,用 averageValue:
metrics:
- type: Resource
resource:
name: memory
target:
type: AverageValue
averageValue: 500Mi # 每个 Pod 平均内存用量目标 500Mi
48-4 多指标与自定义指标
metrics 是数组,可以写多个。HPA 会对每个指标分别算出一个”期望副本数”,然后取最大值去执行。意思是:只要有一个指标说”该扩了”,它就扩。
除了资源指标(CPU、内存),v2 还支持三类需要额外监控系统的指标:
- Pods(Pod 指标):描述 Pod 自身的自定义指标,比如每秒数据包。只支持
AverageValue。 - Object(对象指标):描述同命名空间里另一个对象,比如某个 Ingress 的 QPS。支持
Value和AverageValue。 - External(外部指标):和集群内任何对象都没关系的外部数据,比如消息队列里堆积的任务数。
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
- type: Object
object:
metric:
name: requests-per-second
describedObject:
apiVersion: networking.k8s.io/v1
kind: Ingress
name: web-route
target:
type: Value
value: 10k
NotePod/Object/External 这几类自定义指标需要你额外部署 Prometheus Adapter 之类的组件,把监控数据暴露成
custom.metrics.k8s.io或external.metrics.k8s.io。新手先吃透 CPU/内存就够了。
48-5 扩缩行为 behavior
光说”扩到几个”还不够细。扩太快可能把后端打挂,缩太快可能瞬间没容量。HPA 用 spec.behavior 控制扩缩的”节奏”。
spec:
behavior:
scaleDown:
stabilizationWindowSeconds: 300 # 缩容稳定窗口,默认 300 秒
policies:
- type: Pods
value: 4
periodSeconds: 60 # 60 秒内最多缩 4 个
- type: Percent
value: 10
periodSeconds: 60 # 或 60 秒内最多缩 10%
selectPolicy: Min # 多个策略取"变化量最小"的那个
scaleUp:
stabilizationWindowSeconds: 0 # 扩容一般不等,立即响应
policies:
- type: Pods
value: 4
periodSeconds: 15
selectPolicy: Max # 扩容取"变化量最大"
几个要点:
scaleDown.stabilizationWindowSeconds默认 5 分钟。意思是:即使指标暂时掉下来,也会参考最近 5 分钟的建议,避免一掉就缩、一涨又扩的抖动。policies里可以同时写”按个数(Pods)“和”按百分比(Percent)“,selectPolicy决定取哪个。Max更激进,Min更保守,Disabled直接禁止缩容。- 扩容默认几乎不等待,这样流量来了能马上顶上。
TipWeb 服务建议:扩容敏感(容忍度低)、缩容保守(稳定窗口拉大)。批处理任务反过来,缩容可以更积极以省成本。
48-6 状态条件与排查
写完 HPA,怎么确认它真的在干活?两个命令:
# 看当前指标与目标,TARGET 显示 当前/期望
kubectl get hpa web-hpa
# 看详细状态、事件、条件
kubectl describe hpa web-hpa
kubectl describe hpa 里有个 Conditions 段,三个条件很关键:
AbleToScale:能不能扩缩(比如距上次扩缩时间够不够长)。ScalingActive:指标能不能正常拿到。如果是False,多半是 Metrics Server 没装或指标名写错。ScalingLimited:是不是被 min/max 副本数卡住了。
常见现象与原因:
TARGET显示<unknown>:目标 Pod 没设资源 requests,或 Metrics Server 没就绪。- 副本数一直不动:指标在容差区间内,或
ScalingLimited为 True(已到上下限)。 - 想缩却缩不动:
minReplicas设太高,或scaleDown.selectPolicy: Disabled。
WarningHPA 只能扩缩”副本数”。如果某个 Pod 内部有热点容器把 CPU 吃满、但整个 Pod 平均利用率还在范围内,HPA 不会扩。这时可以用容器级指标
ContainerResource(指定某个容器的名字)来更精准地触发。
小结
HPA 是弹性伸缩的第一块砖:按指标加减副本,省心又省钱。记住这几条:
- 用
autoscaling/v2,metrics是数组,能挂多指标。 - 目标 Pod 必须设
resources.requests,否则 CPU/内存指标算不出来。 - 指标拿不到先查 Metrics Server;副本不动先看 Conditions。
- 用
behavior给扩缩加节奏,别让容量坐过山车。
下一章看 VPA:当问题不是”几个 Pod”,而是”每个 Pod 该分多少资源”时,它就派上用场了。