跳转至

数百个 Kubernetes 集群的稳定性建设

集群数量增加后,日常运维中的小问题会逐渐变成平台问题。一次组件升级需要面对不同的内核和运行时,一次节点维护需要协调业务副本与剩余容量,一份统一配置则可能同时改变多个集群的行为。原来靠工程师逐台检查就能完成的工作,需要逐步沉淀为能够批量执行、随时停止并保留结果的流程。

稳定性建设也会随之发生变化:发现异常之后,谁停止后续发布,哪些节点允许继续维护,积压请求如何恢复,业务由谁验收。这些决定如果一直留到故障现场,集群越多,协调成本就越高。把它们提前写进平台的执行逻辑,才能让监控真正参与故障控制。

这篇文章结合 Uber、LinkedIn、Google 的公开实践,以及本站的 APF 实测,整理多集群稳定性建设中的设计取舍与落地方法。涉及企业实现的内容附有来源;发布批次和指标计算采用明确标注的算例,便于说明机制。

1. 规模扩大后,先处理差异与共同依赖

300 个小集群与 3 个大集群,面临的主要约束并不相同。前者更容易遇到版本组合、配置漂移、凭据管理和批量操作问题;后者可能更先遇到单集群 API、调度与网络容量上限。只比较集群数量,会掩盖这些差异。

风险 数百个集群下的典型表现 需要建立的控制
配置与版本分化 同一个 CNI 升级,在部分内核或运行时组合上失败 资产台账、兼容矩阵、基线与例外管理
同时发生的故障 中央发布系统把错误配置同步到全部集群 分批发布、独立停止开关、故障域约束
公共依赖故障 镜像仓库、身份服务或共享 Webhook 影响多个集群 依赖地图、区域隔离、明确失联行为
人工操作增长 每次证书更新、节点维护都需要逐个处理 有状态、可恢复的自动化工作流
指标掩盖局部故障 大集群的正常流量掩盖小集群完全不可用 单集群、业务等级与全局三个观察维度

集群台账的价值在变更和排障时最明显:选取灰度对象需要知道版本与硬件组合,发生区域故障需要知道业务归属,恢复时需要找到备份和负责人。因此台账除了环境、区域、节点与 Pod 规模,还要记录业务等级、故障域、版本组合、共享依赖、备份位置、最近一次恢复验证和正在进行的变更。

台账需要与实际状态持续对账。对因历史兼容问题保留的例外配置,记录原因、负责人和退出条件;否则一次统一配置同步,就可能把仍有用途的差异当成漂移覆盖掉。

平台最需要避免的是让同一个错误同时传播到多个独立集群。 因此,多集群管理平台本身也属于需要隔离和演练的对象。

2. 从业界实践中提炼可复用的做法

Uber:规模验证与受控扩缩容

Uber 在 Kubernetes 迁移文章中介绍了版本集成和性能验证体系,并在 7500 节点、20 万 Pod 的环境中进行基准验证;运行侧采用 APF 管理高成本 API 调用,扩缩容则拆成小批次,前一批成功后再继续。这说明发布验证和执行节奏需要专门建设,不能仅依赖组件默认参数。Uber 工程文章

LinkedIn:维护操作需要理解应用状态

LinkedIn 的 Stateful Workload Operator 与 Application Cluster Manager 协作,在部署、维护和扩缩容前检查应用是否能够承受中断,例如分片是否有足够副本。平台统一编排动作,应用提供领域相关的安全判断。LinkedIn 工程文章

Google:集群分阶段升级与工程时间保障

GKE 的 rollout sequencing 支持对集群分组,按顺序升级并保留观察期;其自定义阶段能力允许先覆盖少量生产集群,再扩大范围。可借鉴的是跨集群升级的组织方式,而不是把某个观察时长当成通用标准。GKE 官方文档

组织层面,Google SRE 书中提出将重复运维工作控制在 SRE 时间的 50% 以下,为工程项目保留时间。这是 Google 描述的组织目标,不是所有公司的人员配比标准。它说明稳定性投入需要排入研发工作,而不能完全依靠值班期间顺手解决。Google SRE:Eliminating Toil

这些实践有一个共同点:把发布、维护和恢复过程中依赖人工判断的环节,转成明确的执行条件。下面沿着多集群平台的日常工作展开,讨论这些条件如何落地。

3. 管理统一,故障域保持独立

统一管理可以减少重复配置,但也会扩大中央组件的影响范围。一个可行的划分是:中央负责库存、版本和策略;区域或业务分组负责执行预算与发布批次;集群内负责本地协调、流控和证据采集。这样可以把“决定发布什么”和“当前是否允许执行”分开处理。中央管理平台失联时,已经运行的工作负载应尽可能继续工作,新增高风险变更暂停。

多集群参考架构:中央策略、分组执行预算和集群内自治

这是设计目标,需要通过失联演练验证。若 Pod 准入仍同步调用中央 Webhook,或者每次业务鉴权都必须访问同一身份服务,部署在不同集群也可能同时受影响。

失联演练需要覆盖断开和重新连接两个过程。断开时检查已有服务,恢复连接后检查积压任务是否分批执行;如果旧执行器尚未退出、新执行器已经接管,还要确认同一任务不会被重复执行。任务需要幂等键、执行租约或等效的防重复机制,目标集群身份和配置版本必须固定,不能只依赖当前 kubeconfig context。

对于外部 Webhook,应限制匹配范围、设置有界超时并消除循环依赖。failurePolicy 需要根据安全与可用性要求逐项决定,不能为了可用性统一设置为 Ignore。Kubernetes 官方还建议评估用内置准入能力替代部分外部调用。Webhook 最佳实践

4. 把变更变成可停止、可核对的过程

发布的是经过验证的版本组合

组件在测试集群升级成功,只验证了当时的环境组合。如果生产集群使用不同内核、网络配置或存储插件,扩大覆盖面后仍可能出现问题。灰度对象的选择因此要考虑代表性,而不能只选最空闲、最容易操作的几个集群。

一个发布单元应包含 Kubernetes、etcd、容器运行时、内核、CNI、CSI 和关键控制器的版本与配置摘要;GPU 集群还需包含驱动、设备插件和相关运行时。保存镜像 digest、配置差异、兼容条件和恢复入口,避免“同一个版本名,实际内容不同”。

验证至少覆盖资源创建、DNS、跨节点网络、Service、卷挂载、调度和代表性业务。组件启动成功、Pod Ready、业务请求成功属于不同的验收层次。一次 CNI 升级即使 DaemonSet 全部 Ready,也需要检查跨节点连通和现有连接的行为。

同时控制集群批次与节点批次

下面是假设的 300 集群发布算例,各阶段集群不重叠,合计 300。批次不是固定生产建议;首次验证应覆盖主要版本和硬件组合,且核心业务应单独设置推进条件。

阶段 本阶段新增集群 主要目的 推进条件
实验环境 2 验证流程和恢复入口 功能验证与恢复检查通过
非关键业务 8 观察真实业务行为 有效观测窗口内业务指标合格
代表性生产组 30 覆盖主要组件与硬件组合 各组合分别通过,未出现新增严重故障
分组扩大 60 验证更大覆盖面 分组容量与变更预算均允许
剩余集群 200 完成覆盖 再拆成若干小批;核心业务单独验证

假设 300 集群逐批发布,每阶段经验证后推进,异常或观测缺失则停止

集群批次数只是一个维度。还要分别限制同一区域、同一业务副本组和单集群内同时维护的节点数。三个小集群与三个大集群的业务影响可能完全不同,因此不能仅按数量计算风险预算。

发布工作流可以表达为:预检 → 固定目标与版本 → 执行一批 → 业务验证 → 观察 → 下一批。异常、指标缺失或执行状态不明确时,先停止新增动作,再判断撤回配置、修复组件或迁移业务。暂停发布不能自动撤销已经传播的变更。

“回滚”也需要按对象定义:应用或组件可以恢复已验证配置;Kubernetes 控制面降级、etcd 数据恢复、CRD 存储版本变化有独立约束,不能用一次 Git revert 承诺全部恢复。

5. 运行期间:限制异常请求和资源争用

控制面保护需要同时治理客户端和服务端。客户端使用缓存、合理的 LIST/WATCH 范围、重试退避与请求预算;服务端通过 APF 分类和份额约束减少相互干扰。应区分普通 GET、代价较高的 LIST、长连接和写入,结合对象数量、响应大小与处理耗时评估容量。机制说明见 Kubernetes 流控指南

本站的 APF 隔离实测 提供了一个小范围证据:在 Kubernetes 1.30.4 上,零席位 Queue 阶段的 450 个批量请求中,448 个返回 429,另 2 个在恢复份额后成功;全程 359 个对照请求成功。零席位 Reject 却仍放行低并发请求,文章对照源码解释了边界。

这次实测中,排查的关键是先通过响应头核对请求实际命中的 FlowSchema 和优先级,再对照拒绝计数器、客户端状态码与版本源码。只看配置中的零席位,很容易把“规则已创建”误判为“请求已被阻断”。将这类策略推广到其他集群时,需要保留同样的验证过程,覆盖目标版本、业务请求类别、控制器重试和高负载行为。APF 也不承担业务 HTTP 请求的限流。

资源侧则要分别考虑普通业务、平台组件和离线任务:CPU、内存、临时盘、PID、IP 地址和存储吞吐都可能先于节点总算力耗尽。资源配额与优先级需要结合实际预留容量验证,不能仅凭 PriorityClass 判断关键组件一定能够运行。

6. 容量保障:看发生故障后能否承接

节点维护和故障迁移都会消耗剩余容量。即使正常时平均利用率不高,工作负载也可能因拓扑或存储条件无法迁移。容量评估需要从“还有多少资源”进一步落实到“这些任务能够迁到哪里”,并按关键资源分别计算:

故障后的容量余量
= 满足拓扑和依赖条件的健康可分配容量
− 峰值需求
− 已批准的维护占用与安全预留

这是容量评估框架,不是调度器公式。CPU、内存、GPU、Pod IP、卷挂载数量、存储和网络需要各自满足约束;不同维度不能相加。

例如总计空闲 16 张 GPU,并不保证能承接一个要求同机 8 卡的任务。跨区域剩余容量也可能因数据、本地盘、网络延迟或配额限制而无法使用。对于分布式训练,还要检查节点集合、RDMA 和重启成本。

容量验证应包含节点故障、区域容量减少、批量 Pod 重建,以及镜像或模型重新下载的流量。只有启动后的稳态压测,无法发现恢复时的镜像仓库拥塞和控制面突发压力。可结合 模型冷启动优化GPU 拓扑调度案例 评估。

7. 节点维护与自动修复:先判断是否允许中断

节点维护最容易遗漏的是中间状态:节点已经禁止调度,Pod 只迁走一部分,执行器却退出了。重新运行时如果从头执行,就可能重复驱逐或跳过必要检查。因此维护过程需要持久化每一步状态:检查业务与容量 → 隔离新调度 → 有序驱逐或应用迁移 → 维护 → 节点验证 → 业务验证 → 重新接纳。

cordon 主要阻止新的普通调度,不会自动迁移现有 Pod。drain 在通过 Eviction API 工作时尊重 PDB,但 PDB 不能保证避免所有类型中断,也不能替代数据库分片或训练 Checkpoint 的判断。维护遇到 PDB 阻塞时,应先查副本和容量,不应默认绕过驱逐保护。Kubernetes 安全维护节点

自动修复需要明确“诊断信号”和“允许执行的动作”。例如单节点连续故障时可以进入隔离流程;同一区域大量节点同时不可达时,应先考虑网络或公共依赖异常,暂停批量重建。增加重试次数可能扩大故障。

控制 建议行为
故障确认 结合持续时间、多个信号和近期变更,避免单次采集缺失触发重启
修复预算 对全平台、区域、集群和业务副本分别设置上限
中止条件 异常节点比例扩大、关键探针失败或观测失联时停止新增动作
恢复冷却 修复后保留观察期,限制同一对象反复重启
状态与审计 记录原因、对象 UID、执行版本、每一步结果和人工接管情况

自动修复也需要验证:制造一个可控故障后,除了检查故障节点被处理,还要确认正常节点未被误操作、执行器重启不会重复操作、停止开关确实有效。

8. 灾备:恢复对象、数据和业务链路

恢复工作常常卡在快照之外:拿到了备份,却缺少解密密钥;控制面启动了,业务卷没有恢复;Pod 已经运行,入口和身份依赖仍不可用。灾备流程需要沿着业务访问链路检查,而不能在快照导入成功时结束。可以把恢复材料与验收分为三个范围:

范围 恢复材料 验收内容
控制面 etcd 快照、配置、证书、加密配置与外部密钥依赖 API 可用、控制器正确协调、资源状态一致
应用数据 数据库备份、卷数据、对象存储及应用一致性信息 数据可读写,丢失范围符合目标
业务链路 镜像、配置、入口、DNS、身份和依赖服务 代表性业务从入口到数据层完成请求

etcd 快照不能替代业务卷备份。恢复旧快照还可能造成 revision 回退,影响依赖 Watch 的缓存;etcd 3.6 官方恢复文档讨论了 revision bump 与 compact 标记。应按实际版本验证恢复流程,不能直接把某一版命令作为所有集群的通用脚本。etcd 灾备文档

RPO 描述可接受的数据丢失窗口,RTO 描述目标恢复时长。报告实际结果时,应明确起止点:从故障发生到业务恢复,与从执行恢复命令到 API 可用,衡量的是不同能力。备份所在存储、解密密钥和操作凭据也应具备故障期间的可达性。

对 GPU 训练,还要验证 Checkpoint 是否完整、能否恢复训练以及损失了多少有效 GPU 小时;对推理,需验证模型加载、就绪检查、请求质量和延迟,而不仅是容器存活。

9. 让监控参与决策,并保持指标口径清楚

平台侧指标与业务感受之间需要建立对应关系。API 请求成功,并不意味着应用完成部署;Pod 创建成功,也可能长时间等待卷挂载。除 API 成功率外,还需要观察符合条件的部署完成率、Pod 启动时间、PVC 挂载成功率、DNS 与服务连通成功率。排除用户主动取消、无效规格等情况时,应预先定义规则,同时保留原始总数,避免通过修改分母让结果变好看。

多集群看板至少同时展示三个视角:流量加权的全局指标、每个集群的指标、按业务等级统计的不达标集群数。探针失联应显示为未知或观测故障,不能默认为成功;低流量集群需要结合主动探针。

指标 可复核口径示例 对应行动
发布成功率 窗口内成功变更数 / 已完成变更数,失败与取消另列 暂停问题版本扩散
变更故障率 引发规定级别事故的变更数 / 总变更数,明确归因窗口 改进预检与灰度覆盖
恢复时间 故障开始到业务验收通过,报告中位数、P95 和样本数 优化最慢恢复环节
恢复验证覆盖率 已按要求验证的关键集群或应用数 / 应验证总数 补齐没有恢复证据的对象
人工操作成本 每百集群每月重复操作工时 决定优先自动化哪些步骤

错误预算可以将 SLO 与发布决策连接。例如假设某项请求成功率目标为 99.9%,允许失败比例为 0.1%;某窗口内失败率达到 1%,消耗速度就是预算对应速率的 10 倍。实际告警应结合长短窗口、流量和业务重要性,避免只盯一个瞬时值。该方法参考 Google SRE 的 SLO 告警设计

看板需要支持回答“哪批变更后发生异常、影响哪些集群、是否已停止推进、恢复是否通过”。可以把发布 ID、版本和阶段事件加入时间线,将指标连接到工单与执行记录。仅增加面板数量不会自动缩短恢复时间。

10. 开源组件可以承担哪些部分

选择工具时应先确定能力边界。下面是可参考的组件,不是要求同时部署的清单;功能状态和 API 应按拟采用版本核对。

组件或机制 可承担的部分 仍需平台补齐的部分
Argo CD ApplicationSet Progressive Syncs 按组推进 Application 更新 当前官方页仍标为实验性;业务验收、跨故障域预算、恢复流程需要另行设计
Cluster API 健康检查 在 Cluster API 管理范围内检测 Machine 健康并衔接修复 需匹配 provider 与版本;接入现有裸机并非安装组件即可完成
Node Problem Detector 汇报节点问题信号 谁允许重启、何时隔离以及批量修复限制
Velero Kubernetes 资源和配套数据保护流程 存储插件、应用一致性、外部依赖和真实恢复验收
Kubernetes APF API 请求分类、并发份额与排队 客户端治理、版本验证和业务流量限流

GitOps 能帮助保存声明式配置和差异,但同步成功不等于业务健康;节点问题检测也不等于完整自愈。平台的工程投入通常落在组件之间:身份、状态、执行预算、验收与审计需要连接起来。

11. 把稳定性工作放进持续研发

平台团队可以统一维护入口和执行框架,但数据库分片是否允许中断、训练任务何时完成 Checkpoint,仍需要应用提供判断。职责分工应落到具体接口上:平台负责基础设施标准、执行预算与控制面能力;业务提供服务等级、数据一致性与中断条件;双方共同确认维护和灾备的验收标准。网络、存储、身份等公共服务也要有明确的故障联系人和恢复责任。

优先级可以依据已有事故与操作记录确定:先找重复发生、影响范围大、恢复耗时长的问题,再选择能反复降低风险的工程改动。不要把“安装更多组件”直接等同于成熟度。

当前缺口 优先交付物 验收方式
不清楚集群差异 台账、版本矩阵、例外清单 抽样与实际状态一致,关键对象有责任人
批量发布不能停止 分批执行器、停止开关、配置留档 演练中发生异常后不再触及后续批次
备份从未恢复 独立环境恢复流程与证据 API、数据和业务分别验收并记录耗时
节点故障全靠手工 有预算的隔离与修复流程 可处理中途失败,正常节点不被误操作
每次事故都重新排查 证据自动保留、诊断入口、可验收整改 后续演练能够复现并验证防护效果

稳定性投入包括研发时间、验证环境、备用资源和演练时间。是否值得,应看业务影响、恢复成本与风险减少程度;没有适用于所有企业的“每百集群必须配几个人”的统一答案。

12. 让一次排障成为后续运维的依据

故障处理结束后,值得保留下来的不只是修复命令,还有命令为什么有效、适用哪些版本,以及哪些现象不能作为判断依据。把这些信息接入预检、发布验证和日常巡检,下一次才能更早发现问题。

APF 实测就提供了一个具体例子:零席位 Reject 仍然放行请求,最终通过响应头、客户端记录和源码核对得到解释。这项结果可以沉淀为目标版本的策略验证用例,在修改规则或升级 Kubernetes 后重新检查。同一次实验还发现,等待直方图的标签含义和分桶精度会影响读图结果,因此监控说明也需要与配置一起维护。

对多集群平台,可以沿着三个位置落实整改:在发布入口增加能提前发现问题的检查,在运行期间增加能限制影响范围的控制,在恢复流程中补齐曾经缺失的材料和验证步骤。每项整改都记录适用范围、负责人和验收结果,避免一次局部修复被当作所有集群都已解决。

日常运维也能产生这样的改进线索:反复手工确认的条件适合进入预检,频繁卡住的维护步骤需要明确状态与接管入口,恢复时临时寻找的文件需要提前归档。持续消除这些具体障碍,平台才能在集群数量增长时仍然保持可操作性。

延伸阅读:APF 隔离实测事故复盘方法AI 平台可靠性平台运维