Skip to content

思路:基于升级域与委托就绪的多机推理集群高可用升级

概述

本思路旨在解决 Kubernetes 节点升级过程中,多机推理工作负载(如 LWS、Ray 等)的通用、解耦的高可用性问题,而无需引入自定义 Webhook 或沉重的 AI 特定的调度器。

问题陈述

在传统的 Kubernetes 集群升级中,控制面(如 Node Drain)通常是工作负载无关(Workload Agnostic)的,且基于 Pod 维度进行优雅终止。然而,大模型多机推理(Multi-Host Inference)是典型的紧耦合(Gang)工作负载,要求组内所有 Pod “同生共死”。

这导致了以下核心矛盾:

  1. 原生 PDB 的盲区:原生的 PodDisruptionBudget 只能按 Pod 数量控制中断,无法理解“只要死一个 Worker,整组推理就瘫痪”的组级语义。
  2. 重复中断与容量雪崩:逐个驱逐节点会导致同一个组被反复打碎重建;随机并发驱逐则可能同时击碎多个组,导致服务容量雪崩。
  3. 平台与业务的强耦合:为了解决上述问题,业界常采用自定义 Webhook 或引入 Kueue 等 AI 调度器,但这往往需要平台去理解上层业务的特定 Label(如 LWS 的 group-index),破坏了平台与应用解耦的原则。

前提假设

本思路的有效性基于以下工程前提和假设:

  1. 资源受限或成本敏感:集群硬件资源是固定的,或者团队不愿意为了升级而拉起大规模的蓝绿节点池(Blue-Green Pool)造成资源浪费。
  2. 必须进行节点驱逐(Drain):集群节点和 OS 的升级需要进行节点驱逐。虽然业界在探索“免驱逐(Drainless)”的热升级技术,但它们并不原生支持,且不能适用于所有场景(例如涉及数据面 CVE 漏洞修复或内核更新时,必须重启节点)。
  3. 业务必须容忍容量降级:由前两条假设可以推导出,在升级期间我们必须以时间换空间——即在升级窗口内主动降低集群的总服务容量(Capacity),同时维持最低限度的高可用(HA)。上层应用必须接受这一阶段性的容量降级。
  4. 原生组级 PDB 缺失:Kubernetes 目前还没有原生支持 PodGroup 维度的驱逐和 Disruption Budget。虽然在前沿提案(如 KEP-4563: Eviction Request API)中已经开始讨论未来对上层 Workload 的支持,但目前仍处于早期阶段。本思路的目标是在仅利用现有 Kubernetes 原生机制的前提下,解决组级高可用升级的问题。

核心概念

本思路利用 Kubernetes 的原生基元与机制(如拓扑标签 Topology LabelsPod 就绪探针 Readiness ProbePodDisruptionBudget),并引入常见的 “升级域”(Upgrade Domain, UD) 拓扑概念。通过建立一个契约,让指定的 Pod(例如 Leader)聚合整个组的健康状态,我们可以使用标准的 PDB 来保护滚动升级期间组的可用性。

三层契约

为了接入平台并享受自动、安全的升级,工作负载必须遵守以下契约。注意:该契约仅适用于在升级过程中对可用性(Uptime)有强要求的工作负载。如果业务可以在维护窗口(Maintenance Window)内完全下线,则无需遵守此契约。

  1. 拓扑要求(跨 UD 打散):工作负载必须使用 topologySpreadConstraints 或反亲和性将不同的推理组(副本)打散到不同的升级域(UD)中。
    • 以 LWS 为例
      • 组内强亲和(Pack):配置 Worker Pod 与其对应的 Leader Pod 具有强亲和性(podAffinity),确保同一个推理组的所有 Pod 都被包裹在同一个升级域内,避免组内通信被跨域升级切断。
      • 组间反亲和(Spread):配置不同推理组的 Leader Pod 之间基于升级域的标签进行打散(使用 topologySpreadConstraintspodAntiAffinity),确保不同的推理组分布在不同的升级域中,从而在升级某个 UD 时,最多只会破坏一个组。
  2. 委托就绪(健康聚合):工作负载必须指定一个 Pod(例如 LWS Leader),其 ReadinessProbe 对组内的所有成员执行健康检查。如果任何成员失败或被驱逐,该代表 Pod 将变为 Unready
  3. 代表 Pod 的 PDB:针对代表 Pod 定义一个 PDB。由于该 Pod 的就绪状态反映了组的健康状况,因此 PDB 实际上成为了可用组数量的预算。

升级期间的工作流

平台以 升级域 级别执行升级。为了确保 PDB 的拦截机制真正生效,升级控制面在驱逐一个 UD 内的节点时,必须遵循以下精细化逻辑:

  1. 区分 Pod 类型:扫描目标升级域(如 UD 1)内所有的 Pod,将其分为“受 PDB 保护的 Pod”(如 Leader)和“无 PDB 保护的 Pod”(如 Worker)。
  2. 优先驱逐受 PDB 保护的 Pod必须首先向所有受 PDB 保护的 Pod 发起驱逐请求。这是因为无 PDB 保护的 Pod(Worker)一旦先被驱逐,会直接破坏组的完整性而绕过 PDB 的拦截。只有先驱逐受保护的 Pod,才能在触发 PDB 违规时被 Eviction API 正确拦截。
  3. 再快速驱逐其余 Pod:只有当该 UD 内所有受 PDB 保护的 Pod 都被成功驱逐后,升级控制面才可以快速驱逐该 UD 内剩余的无 PDB 保护的 Pod。
  4. 跨域拦截:如果存量可用组数不足,步骤 2 会被 PDB 阻塞,升级控制面将暂停推进,直到之前的组在其他 UD 的新节点上恢复并再次变为 Ready

总结与评估

本思路通过组合 Kubernetes 原生的拓扑标签、就绪探针和 PDB,在不破坏平台与应用解耦的前提下,实现了多机推理工作负载的通用高可用升级。该方案的优势在于其通用性与云原生性,无需为特定的 AI 框架定制控制器。但在落地时,升级控制面必须注意处理状态传播的延迟,且应用方必须严格将组健康检查置于 ReadinessProbe 中以防误杀。总体而言,这是一个遵循 Kubernetes 哲学,适合资源受限环境的通用高可用升级方案。

评论与点赞