在大规模 GPU 集群中,硬件故障是常态。Xid 错误、双位 ECC 错误、GPU 从 PCIe 总线脱落或 InfiniBand 链路抖动,都可能让分布式训练任务停滞或使推理副本下线。发现问题往往不难,难的是从故障发生到节点恢复健康之间的所有环节。Together 今年早些时候推出了全自动节点修复功能,现已正式可用,本文详细拆解其设计和工作原理。
传统节点自动修复通常只依赖一个信号:节点变为 NotReady。但 NotReady 无法区分节点是真正故障还是短暂不可达。当存储或网络事件同时影响多个节点时,所有受影响节点都会变为 NotReady,容易触发大规模误替换。因此 Together 的自动修复遵循一条原则:没有失败的健康检查,就不进行节点修复,且每次修复都携带支持证据。
整个管道分为四个阶段:检测故障、决定是否及何时行动、修复节点、重新验证机器。前三个阶段在用户集群内运行,第四阶段在 Together 基础设施上对腾出的物理主机进行。检测从 hypervisor 两侧进行:VM 内部通过 exporter 监控内核日志中的 Xid 和 PCIe 脱落、DCGM 的 ECC 和热节流指标、Node Problem Detector 的文件系统只读等问题;主机侧则监控 InfiniBand 链路状态和主机可达性。所有告警都附带稳定的摘要、通俗描述和机器可读的证据负载,确保控制台、API 和通知中的信息一致。
策略层面,平台负责决定“做什么”——每个信号映射到能修复它的最轻量动作;用户决定“是否做”和“何时做”。在修复选项卡中,自动修复策略默认是“修复前批准”,即每条建议都等待人工接受或覆盖。用户也可以切换为“全自动”,但这不是一刀切开关,而是通过修复动作清单按故障分组选择信任的项。在 Xid 组内,还可以按代码设置同意策略,例如自动批准 Xid 119 和 95 的重启,而迁移仍需审批。等待空闲设置确保修复在节点真正空闲时进行(Kubernetes 上无 Pod 请求 GPU,Slurm 上无分配),最大等待时间默认 2 小时、上限 24 小时,也可选择“不中断运行中的作业”。每次修复都会记录请求者、批准者、规则和时间。
除了内置检测,团队可以通过 API、控制台或节点标签(预览)引入自己的检测系统。节点标签方式允许任何有 RBAC 权限的检测器通过添加注解和标签发起修复请求,系统会将其记录为外部请求者,确保可追溯且无法冒充用户。检测器名称加请求 ID 作为幂等键,防止重复扫描导致节点被多次重启。外部请求可要求重启、快速重建或迁移,但“移除”始终只能由人工发起。这些请求跳过审批队列,但仍需通过证据门禁、容量检查和预算限制,且每集群有上限,避免缺陷检测器造成灾难。
修复动作按从轻到重分为四级:重启(就地重启 VM,保留本地 /scratch 和 /tmp 数据)、快速重建(在健康主机上从干净镜像重建 VM,丢失本地数据)、迁移到新主机(在不同硬件上重建 VM,旧主机进入重新验证)、移除(拉出节点进行 RMA,始终人工发起)。同一修复不会无限循环:如果同一机器上同一动作已执行两次后故障再次出现,下一次建议会上升一级。阶梯按机器、集群、告警和 Xid 代码跟踪,超过一周的尝试不计入,已取消或自愈的建议也不计入。迁移需要关键告警证据,否则降级为快速重建。对于需要 GPU 断电的故障(如 Xid 79),预览版提供主机电源循环,无需 BMC 凭据,并通过启动 ID 检查防止重复循环。
系统内置多层独立护栏以应对告警风暴:信号必须持续一定时间才成为建议;每次修复后节点有约 30 分钟冷却;并发预算根据集群节点数设定,每个节点池同时只运行一个修复;当单个集群产生大量相关自动修复时断路器跳闸;每次修复只针对一个目标;告警清除后建议自动消失。控制平面采用复制架构,所有写入幂等并检查预期状态,两个副本竞争同一节点只会产生一个修复。
当节点迁移或移除后,原机器不会直接回到池中,也不会排队等待人工诊断。一旦旧 VM 消失,机器立即进入重新验证流程,在 Together 基础设施上运行诊断,确保只有健康的机器才能重新加入集群。目前,被动健康检查、修复建议、自动修复策略(包括按故障和按节点同意)、等待空闲控制、升级阶梯、安全护栏以及 API 和控制台修复均已正式可用;基于节点标签的修复合约处于预览阶段。Together 表示将持续增加新的检测信号和修复动作,以扩大覆盖范围并缩短恢复时间。