Loading Search...
Crater
Incidents

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 主要有来自三个镜像仓库的依赖:

仓库说明
harborACT 实验室最早的镜像仓库,由其他团队维护,机房是独立的
crater-harborCrater 团队在测试环境搭建的镜像仓库,配置了 Harbor Proxy,可以拉取 docker.io 等公共镜像
gpu-harborCrater 团队在生产环境搭建的镜像仓库,主要供用户使用,上传深度学习镜像

因此,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 的服务也不可用。而上述镜像依赖混乱的问题,之前我们就有所意识, 并因此将一些系统的核心组件在 harborcrater-harborgpu-harbor 都进行了上传。

由于 crater-harborgpu-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 平台可以正常访问。

结语

本次故障给同学们的科研工作带来了极大不便,在此,我们向受影响的同学们致以最诚挚的歉意。

事件也暴露出我们在系统架构设计、组件依赖管理及应急响应机制等方面存在诸多不足。未来将从以下方面持续优化:

  1. 完善组件依赖:严格规范镜像仓库使用,核心组件镜像实现多仓库冗余备份;
  2. 强化 Pod 节点亲和性配置,避免关键服务集中部署在同一机房或节点,从架构层面降低单点故障风险。
  3. 确保 Webhook 等关键功能仅作用于必要范围
  4. 妥善升级 Kubernetes 集群、Ingress Controller 版本、Ingress 配置
  5. 做好和新同学的交接,避免单点等待情况

我们深知稳定的服务是支持科研工作的重要基础,本次故障是教训,也是动力。 团队将以此次事件为契机,全面提升系统稳定性与可靠性,用实际行动兑现对用户的承诺。 感谢同学们在故障期间的理解与包容,也欢迎大家继续监督我们的改进工作,共同推动 Crater 平台不断完善。

Edit on GitHub