5 月 14 日
在 NIPS 25 截稿日前,我们的 Crater 服务发生了故障,极大影响了同学们的科研工作。我们在这里对故障进行复盘,并提出改进措施。
事件背景
2025 年 5 月 14 日,机房空调故障,导致 Dell GPU 系列服务器需要重启。 由于 Crater 是本身基于 Kubernetes 部署,当 Pod 所在节点宕机时,Pod 会被调度到其他节点上,以保证服务的可用性。
但在实践过程中,由于 Crater 的依赖关系众多,一个环节的故障可能会导致整个服务的不可用。
故障原因 1
Crater 依赖现状
当前,Crater 包含 Web 前后端、文件服务器等组件。同时还引入了开源社区的 Grafana + Prometheus 可观测组件、高可用数据库、 Volcano 调度器、Harbor 镜像仓库等组件。之后,我们通过 MetalLB 和 Ingress 实现了对外的负载均衡和反向代理。
而当组件发生重建时,会被调度到新的节点上,需要重新从外部拉取镜像和数据。目前 Crater 主要有来自三个镜像仓库的依赖:
仓库 | 说明 |
---|---|
harbor | ACT 实验室最早的镜像仓库,由其他团队维护,机房是独立的 |
crater-harbor | Crater 团队在测试环境搭建的镜像仓库,配置了 Harbor Proxy,可以拉取 docker.io 等公共镜像 |
gpu-harbor | Crater 团队在生产环境搭建的镜像仓库,主要供用户使用,上传深度学习镜像 |
因此,Crater 的组件主要依赖于这些镜像仓库,具体来说,Ingress Contoller 的镜像位于 crater-harbor
上,
当 Ingress Controller 所在节点宕机时,Pod 被调度至其他节点,但好巧不巧,crater-harbor
服务也故障了。
crater-harbor
故障原因
在测试集群,我们同样有部分机器位于出现故障的机房,而 Harbor 和 Volcano 服务的 Pod, 就有一些没有做节点选择,因此之前被调度到了 GPU 节点,也就是本次由于机房空调故障而宕机的节点上。
然而,当节点宕机后,Harbor 在进行重建时,出现了如下错误:
status:
conditions:
- message:
'Internal error occurred: failed calling webhook "mutatepod.volcano.sh":
failed to call webhook: Post "https://volcano-admission-service.volcano-system.svc:443/pods/mutate?timeout=10s":
dial tcp 10.1.138.143:443: connect: connection refused'
reason: FailedCreate
status: "True"
type: ReplicaFailure
这个错误的原因是,Harbor 在重建时,Pod 需要进行 Admission Webhook 的调用,而 Admission Webhook 的服务也在 GPU 节点上, 导致无法进行调用。另一方面,Volcano 的 Webhook Pod 也依赖于 Harbor 的镜像,这就引发了死锁。
$ kubectl get all -n volcano-system
NAME READY STATUS RESTARTS AGE
pod/volcano-admission-c7d5d7b8b-pk49p 0/1 ImagePullBackOff 0 44m
pod/volcano-controllers-5b99b9c887-p6mg8 0/1 ImagePullBackOff 0 44m
pod/volcano-scheduler-7498778d9-2b6gz 0/1 ImagePullBackOff 0 44m
Volcano Webhook 作用域问题
事实上,Volcano 的 Admission Webhook 只应该在指定了 Volcano 调度器的 Pod 上生效。社区也意识到了这个问题, 有一个相关的 Issue 旨在限制 Webhook 作用的默认范围:
PR 合并后,Webhook 只会对指定了 Volcano Scheduler 调度器的 Pod 生效。
然而,这个 PR 在合并的过程中,被核心 Member 反对,认为用户还有一种使用 Case 是将 Volcano 替换集群的默认调度器, 因此需要在 Helm 中指定调度器的名称。 这使得原本相对较小的改动有着更大的影响范围。
修复方式
作为补救,我们需要手动对 Webhook 的作用域进行限制。在我们的使用案例下,所有需要使用 Volcano 调度的作业,
其命名空间均位于 crater-workspace
下,因此我们可以修改其作用范围:
name: mutatepod.volcano.sh
namespaceSelector:
matchExpressions:
- key: kubernetes.io/metadata.name
operator: NotIn
values:
- volcano-system
- kube-system
修改为:
name: mutatepod.volcano.sh
namespaceSelector:
matchExpressions:
- key: kubernetes.io/metadata.name
operator: In
values:
- crater-workspace
而关于社区的 PR,我们也会在后续进行跟进。
故障原因 2
按照上述原因,如果没有 crater-harbor
的故障,Crater 的服务应该是可以正常恢复的。
但在我进行补救的过程中,对 Ingress Controller 进行了额外的修改,导致服务无法转发。
Ingress Controller
Ingress Nginx 是 Kubernetes 上一个非常流行的 Ingress Controller,它非常简单,虽然性能可能不如 Traefik, 也没有跟进 Kubernetes 的 Gateway API,但它的使用非常广泛。
上文提到,当故障节点已经恢复时,Crater 系统依然无法正常访问。其原因是 Ingress Controller Pod 无法拉取镜像。 为了解决这个问题,我首先查看了当前集群的 Ingress 镜像:
➜ ~ kgd -owide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
ingress-nginx-controller 1/1 1 1 173d controller crater-harbor.act.buaa.edu.cn/registry.k8s.io/ingress-nginx/controller:v1.11.3@sha256:d56f135b6462cfc476447cfe564b83a45e8bb7da2774963b00d12161112270b7 app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx
这里我们使用了 crater-harbor
的镜像仓库,然而由于之前的故障,crater-harbor
的服务也不可用。而上述镜像依赖混乱的问题,之前我们就有所意识,
并因此将一些系统的核心组件在 harbor
、crater-harbor
、gpu-harbor
都进行了上传。
由于 crater-harbor
、gpu-harbor
都出现了异常,我转向了由其他团队维护的 harbor
,发现了我们团队成员上传的 Ingress 镜像,但是是 v1.12.0
版本。
当时我并没有多想,因为这是由团队成员上传的,也是为了解决这种场景而做的上传,因此我对 Ingress 的镜像进行了替换。
但 Ingress Controller v1.12.0 似乎引入了一系列 Break Changes,有不少社区的相关 Issues 也反馈了这些问题:
修复方式
因此,在修复了 crater-harbor
镜像仓库后,我们对 Ingress Controller 进行了回滚:
helm rollback ingress-nginx 2 -n ingress-nginx
回滚后,Ingress 转发正常,Crater 平台可以正常访问。
结语
本次故障给同学们的科研工作带来了极大不便,在此,我们向受影响的同学们致以最诚挚的歉意。
事件也暴露出我们在系统架构设计、组件依赖管理及应急响应机制等方面存在诸多不足。未来将从以下方面持续优化:
- 完善组件依赖:严格规范镜像仓库使用,核心组件镜像实现多仓库冗余备份;
- 强化 Pod 节点亲和性配置,避免关键服务集中部署在同一机房或节点,从架构层面降低单点故障风险。
- 确保 Webhook 等关键功能仅作用于必要范围
- 妥善升级 Kubernetes 集群、Ingress Controller 版本、Ingress 配置
- 做好和新同学的交接,避免单点等待情况
我们深知稳定的服务是支持科研工作的重要基础,本次故障是教训,也是动力。 团队将以此次事件为契机,全面提升系统稳定性与可靠性,用实际行动兑现对用户的承诺。 感谢同学们在故障期间的理解与包容,也欢迎大家继续监督我们的改进工作,共同推动 Crater 平台不断完善。
Edit on GitHub