Loading

K8S的HorizontalPodAutoscaler

原文博客:https://nosae.top/posts/k8s的horizontalpodautoscaler

介绍

K8S 的 HorizontalPodautoscaler(HPA)用于根据实际负载,动态地调整 workload 资源的 pod 数量,比如 Deployment、StatefulSet 等。

image-20260217172934965

一个实际的例子可以参考:https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/

HPA 的工作流程是:

找到目标 → 选出 Pod → 获取指标 → 求平均 → 算比例 → 推导副本数

找到目标

在 HPA 中设置 scaleTargetRef 用于找到目标对象:

spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app

然后读取该对象的 .spec.selector,找出所有匹配的 pod。

因此我们也可以发现,HPA 并不是直接管理 Pod,而是通过 Deployment/StatefulSet 的 selector 间接管理。

获取指标

指标有三种来源:

  1. Pod 资源指标,比如内存、CPU
  2. Pod 自定义指标,比如每个 Pod QPS
  3. 外部指标,比如某个 Ingress 的总 QPS、kafka topic lag

计算副本数

  1. 计算每个目标 pod 的指标,比如 CPU 利用率

  2. 计算上述指标的平均值,得到 \(currentMetricValue\)

  3. 结合目标指标值,以及当前副本数,计算目标副本数:

    \[desiredReplicas =\lceil currentReplicas\times \frac{currentmetircValue}{desiredMetricValue}\rceil \]

举个例子,当前副本数为 3,每个 pod 的 cpu request 值为 100m,实际使用:

Pod1: 80m
Pod2: 60m
Pod3: 100m

利用率分别为:

80%
60%
100%

求平均得到:

(80 + 60 + 100) / 3 = 80%

如果 desiredMetricValue 为 50%,则根据公式计算得到目标副本数为:

desiredReplicas = ceil(3 * 80 / 50) = ceil(4.8) = 5

其它规则

是否参与计算

  • 对于 deletetion timestamp 不为空的 pod,以及 failed pod,将不会参与计算。
  • 对于缺失指标的 pod、not ready pod(包括启动 30s 内的 pod、启动 5min 内最近一次指标采集发生在最近一次 ready 之前的 pod、启动 5min 分钟后处于 not ready 的 pod),将被 set aside,即参与 保留计算。(这里的 30s 和 5min 是默认值,由 HPA 控制器的启动参数决定)

保留计算

保留计算的目的是抑制扩缩容,用于 HPA 内部防抖动。

步骤是先用正常的 pod 进行计算得到基础缩放比例,随后,

  • 对于指标缺失的 pod,如果趋势是 scale up,那么将该 pod 的指标视为 0%;如果趋势是 scale down,那么将该 pod 的指标视为 100%。
  • 对于 not ready pod,如果趋势是 scale up,那么将该 pod 的指标视为 0%;趋势是 scale down 则不参与计算。

最后用这些指标以及正常 pod 的指标来计算得到最终的目标副本数。

原始指标与实际指标

原始指标指的是用正常 pod 计算得到的指标,这是你 kubectl get hpa -o yaml 所能看到的数值。

实际指标指的是保留计算后得到的指标,它才是影响最终扩缩容的指标,目的是 HPA 内部用于防抖动。因此在排查问题时,你可能会看到:

HPA status: 85%
target: 50%

却发现:

没有 scale up

因为实际指标很可能小于 50%。

多个指标

如果 HPA 指定了多个指标,则会分别计算,最终取最大的目标副本数;如果部分指标无法获取,并且那些可获取的指标建议缩容,那 HPA 将采取更保守的做法,即不会缩容。

缩容前的观测时间窗

HPA 每次调谐循环都会算出一个 desiredReplicas,例如:

时间 计算结果
00:00 10
00:15 8
00:30 6
00:45 9
01:00 7

如果没有额外机制,直接触发缩容,副本数会频繁上下跳动。而我们可以指定--horizontal-pod-autoscaler-downscale-stabilization = 5m,含义是在准备缩容前,HPA 会查看最近 5 分钟内的所有“副本推荐值”,并选择其中最大的一个。

假设最近 5 分钟的推荐值为:

10, 8, 6, 9, 7

即使当前计算是 7,HPA 也会使用 10 这个值。

从整体上看,取这段时间窗口内最大值的目的是:HPA 必须确定系统持续低负载一段时间后再决定缩容,而不是一次波动就缩容

总的来说,缩容前的观测时间窗可以一定程度上避免:Pod 不断销毁重建、连接抖动、冷启动放大等问题。

posted @ 2026-02-18 18:16  NOSAE  阅读(5)  评论(0)    收藏  举报