HPA 的本质就是:一个定时循环的控制器,根据"当前负载 / 目标值"的比例,用一个简单的公式不停地重算副本数,然后去改 Deployment 的 spec.replicas。
一. HPA 解决什么问题?
在 K8s 里,你给 Deployment 写死 replicas: 3,遇到流量高峰就会被打爆,流量低的时候又浪费资源。
HorizontalPodAutoscaler(HPA)做的事就是:
-
监控某个工作负载(Deployment / StatefulSet 等)的一些指标;
-
周期性地根据这些指标计算"应该有多少个 Pod";
-
自动修改目标对象的副本数,让副本数在
[minReplicas, maxReplicas]范围内跟着负载走。Kubernetes+1
二. HPA 的几个关键组件
-
HPA 对象(YAML 里的那个
kind: HorizontalPodAutoscaler)里面主要几项:
-
scaleTargetRef:要控制的对象,比如某个 Deployment。 -
minReplicas/maxReplicas:最小、最大 Pod 数。 -
metrics:用什么指标来驱动扩缩容(CPU、内存、QPS、自定义指标、外部指标等)。Red Hat Docs+1 -
(可选)
behavior:控制扩/缩容的速度、稳定窗口等。stormforge.io
-
-
HPA 控制器(kube-controller-manager 里的一个控制循环)
-
运行在控制面中;
-
每隔一段时间(默认 15 秒) 去拉一次目标对象的指标,然后计算期望副本数;Kubernetes
-
把算出来的值写回到目标的
spec.replicas。
-
-
Metrics 管道
HPA 并不直接采集 CPU,它是通过 K8s 指标 API 拿数据的:Medium+1
-
metrics.k8s.io(Resource Metrics API):默认的 CPU / 内存指标(一般由 Metrics Server 提供),最常用。 -
custom.metrics.k8s.io(Custom Metrics API):跟 K8s 对象绑定的自定义指标,比如"每个 Pod 的 QPS"。 -
external.metrics.k8s.io(External Metrics API):外部系统指标,比如"消息队列长度"。
HPA 只负责"拉 API + 算副本数",至于这些 API 后面连的是 Prometheus、CloudWatch 还是别的东西,是通过 metrics adapter 去适配的。Medium
-
三. HPA 支持的指标类型(v2 API)
在 autoscaling/v2 里,spec.metrics[*].type 大致有:Red Hat Docs+1
-
Resource/ContainerResource:CPU、内存这类资源指标; -
Pods:针对每个 Pod 的自定义指标(比如每个 Pod 的 HTTP QPS),然后求平均; -
Object:针对某个对象整体的指标(例如某个 Service 的总 QPS); -
External:完全外部的指标(例如外部队列长度)。
每个 metric 里还要设 目标值 target:
-
type: Utilization:目标利用率(百分比,例如 CPU 70%); -
type: AverageValue:每个 Pod 的目标平均值(比如 "每个 Pod 100 QPS"); -
type: Value:对象级别的绝对值(比如 "总共 QPS=1000")。
四. 核心算法:怎么算"需要多少个 Pod"?
无论你监控的是 CPU / 自定义指标,本质上 HPA 都是用一个很简单的比例公式:stormforge.io+3Stack Overflow+3perfectscale.io+3
desiredReplicas = ceil(currentReplicas × currentMetricValue / desiredMetricValue)
解释一下参数含义(以 CPU 利用率为例):
-
currentReplicas:当前正在运行的 Pod 数; -
currentMetricValue:当前平均指标值(比如当前平均 CPU 利用率 90%); -
desiredMetricValue:你配置的目标值(比如目标 CPU 60%)。
举个简单例子(CPU)
目标 CPU 利用率:60%
当前平均 CPU 利用率:90%
当前副本数:4
比例:currentMetricValue / desiredMetricValue = 90 / 60 = 1.5
于是:
desiredReplicas = ceil(4 × 1.5) = ceil(6) = 6
所以 HPA 会把 Deployment 的 replicas 从 4 改到 6,来摊薄负载。
同理,如果当前平均 CPU 是 30%,目标还是 60%,那比值是 0.5:
desiredReplicas = ceil(4 × 0.5) = ceil(2) = 2
就会触发缩容,把 Pod 从 4 个缩到 2 个。
多指标时怎么处理?
v2 可以配置多个 metrics,比如同时看 CPU 和 QPS。
算法是:对每个指标分别算一个 desiredReplicas,然后取其中最大的那个作为最终结果(偏向"宁可多扩不缩"以保证 QoS)。 people.wikimedia.org+2stormforge.io+2
1. desiredMetricValue 到底是什么?
在 CPU 利用率(type: Utilization) 这个场景下:
-
desiredMetricValue= 你在 HPA 里配置的"目标利用率百分比" -
比如你写:
metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 60那么:
-
desiredMetricValue = 60(%) -
含义是:希望"所有 Pod 的平均 CPU 利用率 ≈ 60%(相对于它们自己的 request)"
-
换句话说:你是希望"使用量 ≈ request 的 60%"。
2. 这里的"利用率"跟 request 的关系
CPU Utilization 的定义是:
利用率 =
当前 CPU 使用量 / Pod 的 CPU request× 100%
-
如果一个 Pod 的
resources.requests.cpu = 500m,当前实际用量是250m:- 那它的 CPU 利用率就是
250m / 500m = 50%
- 那它的 CPU 利用率就是
-
HPA 会对所有 Pod 做平均,得到一个 平均利用率 ,这就是前面说的
currentMetricValue。
所以:
-
Pod 的 request 是分母("容量")
-
当前使用量(usage)是分子
-
desiredMetricValue是你希望这个"利用率(usage/request)"稳定在多少百分比上,比如 60%。
3. 再用一个具体例子串起来
假设:
-
每个 Pod 的
requests.cpu = 500m -
当前有 4 个 Pod
-
实际监控到的平均使用量是
450m/Pod
则:
-
每个 Pod 利用率 =
450m / 500m = 90% -
平均利用率 =
90%(currentMetricValue) -
你在 HPA 里配置目标是
averageUtilization: 60
→desiredMetricValue = 60%
代入公式:
desiredReplicas = ceil(currentReplicas × currentMetricValue / desiredMetricValue) = ceil(4 × 90 / 60) = ceil(4 × 1.5) = 6
HPA 就会把副本数从 4 调到 6,让每个 Pod 平均负载降下来,目标是在一段时间后趋近 60% 左右。
4. 小结一句话
-
desiredMetricValue(在 CPU Utilization 场景)不是 request 本身,而是"相对于 request 的目标利用率百分比"。 -
Pod 的
request用来当分母算"利用率",HPA 配置的是"希望这个比例大概是多少"。
五. 如何避免来回抖动?(抖动抑制 & 缩容稳定窗口)
如果没有"缓冲",指标一抖动就改一次副本数,集群会疯狂扩缩容。K8s 做了几件事来平滑:
-
容忍度(tolerance)
有一个默认 10% 的容忍区间:只有当
currentMetricValue / desiredMetricValue超过 1.1 或小于 0.9 时才会真正扩缩容。Kubegrade-
比如目标 CPU 60%,当前在 63%(63/60 = 1.05),不会扩容;
-
只有达到 ~> 66% 或 < 54% 左右才会动。
-
-
缩容稳定窗口(scaleDown stabilizationWindowSeconds)
-
对"缩容"特别敏感,因为缩容错了会直接影响可用性;
-
通常会配置一个窗口(比如 300 秒),HPA 会在这个窗口里对多次计算结果做一个"保守"的合并(一般取这段时间内最大的 desiredReplicas ,防止刚缩下去马上又扩回来)。stormforge.io
-
-
扩缩容速率限制(policies)
在
spec.behavior.scaleUp/scaleDown.policies里,你可以限制每个周期最多扩/缩多少个 Pod 或多少百分比,例如:stormforge.io-
"每 15 秒最多扩容 100%";
-
"每 60 秒最多缩容 10%"。
-
六. HPA 和其他自动扩缩工具的边界
很多人会把几个概念混在一起,这里顺便帮你厘清下:CloudRaft+1
-
HPA(HorizontalPodAutoscaler)
-
调的是 Pod 的数量;
-
前提是集群里已经有足够 Node 能跑这些 Pod。
-
-
VPA(VerticalPodAutoscaler)
-
调的是 Pod 里 单个容器的资源 request/limit(比如 CPU request 从 200m 调到 500m);
-
适合长期稳定 workload 的"容量调优"。
-
-
Cluster Autoscaler
-
调的是 Node 的数量;
-
当 HPA 想扩 Pod 但 Node 不够时,CA 会去加机器。
-
三者一起配合,才是完整的自动扩缩容体系。