Kubernetes HPA 设计与实现

Kubernetes HPA 设计与实现

💡 原文中文,约12200字,阅读约需30分钟。
📝

内容提要

本文分析 Kubernetes v1.28 中 HPA(水平 Pod 自动伸缩)的源码实现。核心组件 HorizontalController 通过 informer 监听 HPA 事件并加入延迟队列,由多个 worker 循环处理。reconcileAutoscaler 先按最小/最大副本数约束,再遍历各指标计算期望副本数并取最大值,经行为策略调整后向 API Server 发起扩缩容。资源指标计算中,资源利用率=当前指标/期望指标,期望副本数=ceil(当前副本数×利用率),并处理未就绪及缺失指标的 Pod。

🔎

延伸解读

多指标取最大值:HPA 的保守伸缩逻辑

HPA 会遍历所有配置的指标分别计算期望副本数,并取其中的最大值作为最终结果。例如 CPU 算出 10 个、内存算出 15 个,则采用 15 个。这意味着只要任一指标超过目标,就会触发扩容,避免某个维度成为瓶颈;但反过来,缩容时也必须所有指标都低于目标才会执行,因此多指标配置下缩容会更谨慎、更滞后。

未就绪与缺失指标 Pod 的处理差异

源码对未就绪 Pod 和缺失指标 Pod 采取了不同策略。扩容且存在未就绪 Pod 时,将其指标视为 0%,避免因新 Pod 尚未上报数据而误判负载偏低;缺失指标的 Pod 在缩容模式下按 100% 利用率估算,在扩容模式下按 0% 估算。这些处理会影响最终副本数,理解它们有助于排查伸缩结果与预期不符的情况。

容差与逆向伸缩保护

重新计算利用率后,若与 1.0 的偏差在容差范围内,或新利用率会导致扩容与缩容方向反转,控制器会直接返回当前副本数。这一机制防止指标小幅波动引发频繁伸缩,也避免因补充缺失指标后计算出相反方向的调整。它解释了为何实际副本数有时不会严格等于公式计算结果。

默认行为参数对伸缩节奏的影响

默认配置中,HPA 同步周期为 15 秒,扩容禁止窗口为 3 分钟,缩容稳定窗口为 5 分钟,并发处理协程数为 5。这些参数决定了控制器多久评估一次、两次扩容或缩容之间至少间隔多久。缩容稳定窗口较长,意味着缩容决策会更保守,读者在观察伸缩延迟时应结合这些默认值理解。

❓

Q&A

Kubernetes HPA 的核心控制器是什么?它如何监听和处理 HPA 事件?

核心控制器是 HorizontalController。它通过 informer 监听 HPA 的新增、修改、删除事件,将变化的 HPA 对象加入延迟队列,然后由多个 worker goroutine 循环从队列中取出并处理。

HPA 计算期望副本数的基本公式是什么?能举个例子吗?

公式为:Pod 期望副本数 = ceil[Pod 当前副本数 × (当前指标 / 期望指标)]。例如当前 CPU 使用量为 200m,期望指标为 100m,当前副本数为 5,则期望副本数 = ceil[5 × (200m/100m)] = 10。

当 HPA 配置了多个指标(如 CPU 和内存)时,最终副本数如何确定?

HPA 会遍历所有指标分别计算期望副本数,然后取其中的最大值作为最终期望副本数。例如 CPU 算出 10 个,内存算出 15 个,则最终采用 15 个。

HPA 如何处理未就绪或缺失指标的 Pod?

HPA 会将 Pod 分组为就绪、未就绪、缺失指标和忽略的 Pod。缩容时缺失指标的 Pod 假设利用率为 100%(或目标利用率),扩容时假设为 0%;扩容时未就绪 Pod 的利用率也设为 0%。之后重新计算利用率,若变化不大或会引起逆向伸缩,则保持当前副本数。

HPA 控制器有哪些重要的默认配置参数?

默认并发处理 HPA 的 goroutine 数为 5;延迟入队时间为 15 秒;两次扩容的间隔禁止窗口为 3 分钟;缩容稳定窗口为 5 分钟。

HPA 在什么情况下会跳过自动扩缩容?

如果当前副本数为 0 且最小副本数不为 0,则关闭自动扩容,期望副本数设为 0;此外,如果重新计算后的资源利用率变化在容忍范围内,或会引起逆向伸缩(扩容变缩容、缩容变扩容),则直接返回当前副本数,不执行扩缩容。

🏷️

标签

➡️

继续阅读