Kubernetes Cluster Autoscaler 集群状态注册表(Cluster State Registry)设计解析:从"不可用即停摆"到"带病容错"的演进
【免费下载链接】autoscalerAutoscaling components for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/au/autoscaler
导读
本文基于 autoscaler 仓库中 Kubernetes Cluster Autoscaler(CA)的官方设计提案 clusterstate.md,系统讲解 CA 如何通过"集群状态注册表(Cluster State Registry)"应对节点不可用(unready)场景。提案针对早期版本 CA"云端节点数与 K8s Ready 节点数不一致就整体停摆"的缺陷,设计了一套从"集群健康度评估、节点组健康度评估、预期到达节点记账、缺失节点时长追踪"四个维度出发的自愈式主循环算法。读完本文,你将掌握 8 类不可用节点场景(UC1~UC8)的判别特征与处置动作、状态注册表提供的 4 类关键信息(S1~S4)、9 步主循环算法的执行顺序,以及在当前仓库源码与命令行参数中的落地方式。
一、背景:为什么 CA 曾经"一遇到不可用节点就停摆"
在 Kubernetes Cluster Autoscaler 的第一个版本中,只要云端(如云厂商的 MIG / ASG 一侧)观测到的节点数量与 Kubernetes 侧 Ready 节点的数量不一致,CA 就会停止一切伸缩操作。这一设计初衷是防止 CA 在已经出问题的集群上"越帮越忙"、扩大故障。然而社区的客户端反馈表明,这种行为在许多场景下是次优的,甚至让运维人员感到困惑:
- 一次正常的扩容操作会瞬间破坏"两侧数量一致"的前提,导致 CA 自己把正常扩容"冻结";
- 节点启动慢、注册慢、云配额不足等常见情况被一视同仁地当作"集群故障"处理;
- 运维人员无法区分"节点正在路上""节点启动失败""节点彻底失联"等截然不同的状况。
本提案(由 Cluster Autoscaler 团队撰写,定稿于 K8s 后续版本发布前)正是要废除"数量不一致即停摆"的简单策略,改为让 CA 精确感知每个节点的状态与因果,从而在大部分场景下继续安全操作,仅在真正全局性故障时才暂停。
二、8 类不可用节点使用场景(Use Cases)
提案将"Ready 节点数与云端节点数不一致"分解为 8 个相互独立、可判别的场景,每个场景都给出了判别特征(Indicating factors)与建议动作(Suggested action)。
UC1:节点已扩容、尚未注册(扩容进行中)
节点组规模已增大,但新节点尚未在云侧创建 / 启动 / 注册到 K8s(在 GCP 上通常需要几分钟)。
- 判别特征:过去几分钟内发生过扩容;缺失节点数不超过本次扩容的规模。
- 建议动作:继续运行,但在所有扩容计算中把"即将到达的节点"计入资源占用。
UC2:节点已注册、尚未 Ready(注册后初始化中)
节点已在集群中注册,但尚未切换为 Ready 状态,通常几秒内即可恢复。
- 判别特征:不可用节点是"新"节点,CreateTime 在最近几分钟内。
- 建议动作:同 UC1,继续运行并把即将 Ready 的节点纳入扩容考量。
UC3:节点启动超时(注册成功但无法完成启动)
节点已注册到 K8s,但在合理时间内未能完全启动,短期内大概率无法恢复。
- 判别特征:节点处于 unready;且 CreateTime 等于 unready NodeCondition 的 LastTransitionTime(即从创建起就一直未 Ready)。
- 建议动作:继续运行,但不要扩展该节点池;该节点大概率会在闲置足够久后被缩容清理(见 UC5 / UC6)。
UC4:云侧无法供给节点(配额或技术问题)
云侧在合理时间内无法供给节点,常见原因是配额不足或技术故障。
- 判别特征:云侧目标节点数持续(超过几分钟)大于 K8s 内节点数,且差值不再变化;在云侧列举节点时看不到任何新增节点。
- 建议动作:将该问题节点组的目标规模缩减到当前实际规模(即把"虚标"的容量修正回来)。
UC5:节点供给成功但注册失败
云侧已创建节点,但节点始终没有注册进 K8s。
- 判别特征:云侧存在长时间未出现在 K8s 中的新节点。
- 建议动作:逐个删除这些未注册节点。
UC6:节点长期不可用(20 分钟以上)
节点进入不可用状态超过 20 分钟,且集群中不可用/未出现节点总数占比很低(低于 XX%),通常是节点上发生无法自愈的崩溃。
- 判别特征:节点 condition 为 unready 且 LastTransitionTime 距今 ≥ 20 分钟;K8s 中总节点数等于云侧目标节点数。
- 建议动作:将该节点纳入缩容候选,但使用更大的(可配置的)"非必需(unneeded)"时长,并且仅在节点控制器已将其上所有 Pod 驱逐完毕后执行。
UC7:CA 主动删除的节点
节点正被 Cluster Autoscaler 移除。
- 判别特征:节点 unready 且带有
ToBeRemovedtaint。 - 建议动作:继续运行,节点很快会被删除。
UC8:大面积非合理不可用(网络分区或全局故障)
与扩容、缩容无关的不可用节点占比超过 XX%,说明集群可能遭遇网络分区或通用性故障。
- 判别特征:超过 XX% 的节点 unready。
- 建议动作:暂停所有操作,并告警系统管理员。
其中 UC1~UC5 聚焦"数量不足"侧的节点到达问题,UC6~UC8 聚焦"存量节点失联"侧的稳定性问题,二者共同构成状态注册表设计的输入全集。
三、提案方案:集群状态注册表(Cluster State Registry)
提案的核心是引入一个集群状态注册表(Cluster State Registry),对外提供 4 类关键信息(S1~S4),作为 CA 主循环决策的依据:
| 编号 | 提供的信息 | 含义与用途 |
|---|---|---|
| S1 | 集群整体是否"足够健康"以允许 CA 运行 | 若大部分节点处于 Ready、且非合理(与伸缩无关)的不可用节点数量受限,则集群健康。集群不健康时 CA 应暂停操作并告警系统管理员(对应 UC8) |
| S2 | 给定节点组是否"足够健康"以允许 CA 对其操作 | 若某节点组中不可用(非因当前伸缩引起)或完全未出现(云侧尚未启动)的节点数量受限,则该组健康。CA 应对不健康节点组"格外小心",在其状况改善前不再继续扩容(对应 UC3) |
| S3 | 哪些节点即将到达集群 | 供估算器(estimator)将其计入资源占用,避免为已被这些节点覆盖的 Pod 重复申请资源;同时估算器无需再等待节点真正出现在集群中(对应 UC1、UC2) |
| S4 | 节点组缺失节点持续了多久 | 若固定数量的节点长时间缺失,可能暗示配额问题,应将此类节点组缩容到实际规模(对应 UC4) |
在此基础上,CA 将在"集群中可能存在不可用节点"的前提下照常工作:这类节点会被缩容逻辑选中,因为 Kubernetes 的 controller-manager 最终会从不可用节点上驱逐所有 Pod;因此,若这些节点不能恢复健康,在不可用足够久之后都会被移除(并可能被新节点替换)。
四、主循环算法:9 步迭代流程
提案给出重构后的 CA 主循环算法,其核心思想是每一步都只处理一类明确界定的问题,且多数情况下"继续前进"而非"整体停摆":
- 获取全部节点:从集群中拉取所有节点列表。
- 集群健康度检查(用 S1,对应 UC8):若集群整体不健康(大部分节点未 Ready),则告警用户、跳过本轮迭代并等待 10 秒;同时清空第 8、9 步维护的 unneeded 统计,防止把"故障期"误算成"闲置期"。
- 清理注册失败的节点(对应 UC5):检查各节点组是否存在"注册失败"的节点,若存在则逐个删除。
- 修正长期缺失节点的节点组(用 S4,对应 UC4):若节点组存在长期缺失节点,则将节点组规模按缺失数缩减,然后跳过本轮的剩余步骤。
- 检查待调度 Pod(pending pods):先剔除那些可以被当前 Ready 节点(不包括即将被删除的节点,见 UC7)调度的 Pod。
- 筛选可扩容节点组(用 S2,对应 UC3):对仍无法调度的 Pod,找出可扩容的节点组,跳过不健康的节点组(含大量不可用节点或启动失败节点)。
- 估算所需节点数并扩容(用 S3,对应 UC1、UC2):估算所需节点数时扣除"即将到达"的节点,然后按需扩容选中的节点组。
- 计算全集群 unneeded 节点(对应 UC6):包括不可用节点在内,统计"非必需"节点;这些节点必须在每轮迭代中被持续监控,以确保它们已"非必需"足够长时间(而不是某一瞬的误判)。
- 尝试删除 unneeded 节点:若近期没有扩容且节点"非必需"超过 10 分钟,则尝试删除;不可用节点使用更高的延迟阈值(即 UC6 所述的可配置更长 unneeded 时间)。
算法的节奏是"边操作边观察":第 2 步的 10 秒等待、第 9 步的 10 分钟延迟、第 8 步的持续监控,共同保证 CA 不会在节点短暂异常时做出不可逆的破坏性动作。
五、在仓库源码与参数中的落地印证
该提案虽然描述的是设计蓝图,但当前仓库的 Cluster Autoscaler 实现已经将其核心思想落地为可配置的行为,以下证据可以帮助你把提案与实际运行行为对应起来。
5.1 不可用节点容忍度:集群健康门槛(对应 S1 / UC8)
提案中的"集群健康阈值 XX%"在实现中体现为两个 flag(见 FAQ.md 的 flag 列表与"CA 如何处理不可用节点"一节):
--max-total-unready-percentage:集群中不可用节点的最大百分比,超过后 CA 停止所有操作,默认 45;--ok-total-unready-count:允许的不可用节点绝对数量(不受百分比限制的兜底),默认 3。
FAQ 中明确说明:早期 CA 1.2.1 及更早版本默认容忍 33% 或最多 3 个不可用节点(取较大者),此后改为由上述两个 flag 配置;当不可用节点超过阈值时,CA 停止一切操作直到情况好转。这正是提案 S1"集群不健康则 halt + 告警"(UC8)的工程化实现。在 Helm 部署中,这两个参数同样可通过 charts/cluster-autoscaler/values.yaml 配置。
5.2 未注册节点与缺失节点的清理(对应 UC4 / UC5)
--max-node-provision-time:节点从创建到出现在集群中的最大等待时间,超时后 CA 停止在扩容模拟中考虑这些节点,并可能触发补扩;超过该时间仍未注册的节点会被处理(见 FAQ.md 中"未注册节点"相关章节)。--force-delete-unregistered-nodes:是否强制删除长期未注册节点,无论它们所属节点组的最小规模(min size)是多少。这对应提案 UC5"逐个删除未注册节点"的建议动作,且提供了突破节点组 min size 限制的开关。
5.3 不可用节点的缩容策略(对应 UC6 / UC7)
--scale-down-unready-enabled:是否允许 CA 缩容不可用节点,默认 true;--scale-down-unready-time:不可用节点在被判定为"非必需"后需等待多久才具备缩容资格,默认 20m0s。
这两个 flag 精确对应提案 UC6"对不可用节点使用更大(可配置)的 unneeded 时间"以及"仅在节点控制器已驱逐其全部 Pod 后缩容"。而 UC7 中提到的ToBeRemovedtaint 在实现中同样被各云厂商缓存与节点状态追踪所识别(例如 gce/cache.go 中维护的 MIG 实例状态计数缓存migInstancesStateCountCache,以及 azure、tencentcloud 等提供商的缓存实现),确保被 CA 标记删除的节点不会在步骤 5 中被当作可用调度资源。
5.4 从源码结构看"状态感知"的实现形态
从源码结构看,提案中"注册表"所需的两类原始数据——K8s 侧节点状态与云侧节点供给状态——在实现中由两层协同提供:
- 云侧缓存层:以 gce/cache.go 为代表的
GceCache维护 MIG 列表、实例列表、MIG 与实例的映射、目标规模(migTargetSizeCache)、实例状态计数(migInstancesStateCountCache)等,并用互斥锁保证并发安全,从而支撑 UC4/UC5 所需的"云侧目标规模 vs 实际实例"对比; - K8s 节点状态层:CA 主循环从集群 API 获取节点与 NodeCondition(Ready / unready / LastTransitionTime),配合 taint(如
ToBeRemoved)与节点创建时间,即可完成 UC1~UC3、UC6~UC8 的判别特征匹配。
可以推断,提案中统一抽象的"Cluster State Registry"最终演化为分布在核心主循环与各云提供商缓存中的一系列状态采集与健康判定逻辑,其对外可见的形态就是上述一组可调参数与主循环中的健康检查步骤。
六、参数速查表
以下汇总提案相关行为在 FAQ.md 中列出的核心 flag(默认值以当前仓库为准):
| Flag | 作用 | 默认值 |
|---|---|---|
--max-total-unready-percentage | 集群不可用节点最大百分比,超过则 CA 暂停操作 | 45 |
--ok-total-unready-count | 允许的不可用节点绝对数量,不受百分比限制 | 3 |
--scale-down-unready-enabled | 是否允许缩容不可用节点 | true |
--scale-down-unready-time | 不可用节点满足"非必需"后等待多久才可被缩容 | 20m0s |
--max-node-provision-time | 节点创建后等待其出现在集群中的最大时长,超时后停止在模拟中考虑并可能补扩 | 15m0s(见 FAQ 说明) |
--force-delete-unregistered-nodes | 是否强制删除长期未注册节点(无视节点组 min size) | false |
说明:以上 flag 均可在 CA 部署的启动参数(如 Helm values 中的
extraArgs或部署清单中的 command 参数)中配置;不同云提供商的部署清单示例可参见各 provider 的examples/目录(如 gce 部署相关文档 与 charts/cluster-autoscaler/values.yaml)。
七、设计要点总结
- 从"全有或全无"到"分级容错":旧策略因数量不一致就整体停摆;新设计将不一致细分为 8 类场景,绝大多数场景下 CA 继续运行,只有全局性故障(UC8)才暂停。
- "预期到达节点"参与资源记账(S3):估算器把即将到达的节点算作已占用资源,避免重复扩容,也无需等待节点真正出现,缩短扩容决策延迟。
- 健康门槛分级(S1/S2):集群级健康门槛负责全局安全阀,节点组级健康门槛负责局部"免疫",不健康节点组不再被继续扩容(UC3)。
- 对"虚标容量"主动纠偏(S4/UC4):长期缺失节点的节点组会被缩容到实际规模,避免 CA 永远朝着一个永远无法满足的目标扩容。
- 不可用节点进入缩容管线(UC6):不可用节点只是"更晚、更谨慎"地被缩容,而不是永远无人处理;
--scale-down-unready-time提供了可配置的延迟,配合 controller-manager 的 Pod 驱逐行为完成闭环。
该设计提案为后续 Cluster Autoscaler 的"带病工作"能力奠定了基础,其思想——把抽象的"数量不一致"细化为可判别的具体场景、为每个场景分配明确的判别特征与动作——至今仍是分析 CA 行为与排障(例如通过 FAQ.md 中集群健康状态检查指引)的重要心智模型。
【免费下载链接】autoscalerAutoscaling components for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/au/autoscaler
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考