驱动升级和自愈

INFO

本页仅适用于在 NPUOperatorCtl 实例上启用了 Driver 的情况。如果你设置 spec.driver.enabled=false(预装驱动模式),operator 不会接触主机驱动,下面两个流程都不会运行——驱动版本以及任何芯片恢复重启,都应通过安装 .run 包时所使用的流程进行管理。

从 v1.2.4 开始,NPU Operator 会端到端地管理每个 NPU 节点上的驱动生命周期。本页介绍它暴露的两个基于状态驱动的流程:

  • 驱动升级——在整个集群范围内滚动发布新驱动版本。
  • 芯片自愈——自动恢复运行时发生卡死的节点上的芯片。

这两个流程都会经过相同的节点重启路径。Ascend 芯片无法容忍对正在运行的驱动执行 rmmod——尝试原地替换驱动会使芯片进入不可恢复的 dev_num=0 状态。因此,operator 始终会从全新启动中加载新模块,而不是在运行中的 kernel 内重新加载它们。

驱动升级

WARNING

在开始驱动升级之前,请停止所有 NPU 工作负载。 升级会按顺序重启每个 NPU 节点,且并不设计为对正在运行的训练任务或推理服务透明。在补丁 spec.driver.version 之前,请将所有申请 NPU 的 Deployment / StatefulSet / training job 缩容到 0,清空正在处理中的请求,并持久化任何模型 checkpoint。滚动完成后再恢复这些工作负载——有关如何判断完成,请参见 步骤 4

升级过程分为四个有序步骤:准备集群、触发版本提升、批准每个节点的重启,以及验证新驱动。不要在步骤 1 完成之前就开始触发——这是导致滚动卡住的最常见原因。

步骤 1:触发前准备

在修改 spec.driver.version 之前,必须先完成两件事。两者都是必需的;任意一项缺失都会导致升级卡住。

1.1 升级前检查清单

  1. 集群镜像仓库中已存在适用于每种 NPU 节点规格的新驱动镜像。 对每个 (chip, kernel, OS) 组合,重复使用 安装步骤 1.1 中的 skopeo copy 步骤:

    # On a machine with internet access:
    NEW_VERSION=25.5.0
    
    for COMBO in 910b-6.6.0-145.0.4.135-oe2403sp3 310p-6.6.0-145.0.4.135-oe2403sp3; do
      skopeo copy --all \
        docker://docker.io/alaudadockerhub/ascend-driver:${NEW_VERSION}-$COMBO \
        docker://<your-cluster-registry>/mlops/ascend-driver:${NEW_VERSION}-$COMBO
    done

    如果源 Docker Hub 仓库中没有任何 tag 与你节点的 kernel 匹配,请联系 客户支持——请参见 安装说明中关于缺失 tag 的说明

  2. 已更新 ImageWhiteList,将新的 tag 包含进去:

    kubectl edit imagewhitelist ascend-driver -n cpaas-system
    # add each new tag under spec.repoList

1.2 停止 NPU 工作负载

在继续之前,请将所有申请 NPU 的 Deployment / StatefulSet / training job 缩容到 0。滚动完成后再恢复它们——请参见 步骤 4

# Examples — scale every NPU-using workload to zero
kubectl scale -n serving inferenceservice/my-model --replicas=0
kubectl scale -n training statefulset/llama-trainer --replicas=0

步骤 2:触发升级

编辑你的 NPUOperatorCtl 实例(创建于 安装步骤 5.3 末尾),并在一次保存中更新两个字段:

  • spec.driver.version —— 新的驱动版本(例如 25.5.0)。
  • spec.driver.upgradePolicy.autoUpgrade —— 保持默认值 false,以便手动批准每个节点重启;设置为 true 则由 operator 自动滚动整个集群。自动模式仅建议用于裸金属集群上的常规版本升级。

通过平台 UI(推荐):

  1. 管理员 > Marketplace > OperatorHub > 已安装的 Operators > Alauda Build of NPU Operator
  2. 打开 NPUOperatorCtl 选项卡并点击该实例(默认名称 npuoperatorctl-sample)。
  3. 编辑 YAML,修改这两个字段,然后保存

通过 kubectl

NEW_VERSION=25.5.0

kubectl -n npu-operator patch npuoperatorctl npuoperatorctl-sample --type=merge \
  -p "{\"spec\":{\"driver\":{\"version\":\"${NEW_VERSION}\",\"upgradePolicy\":{\"autoUpgrade\":false}}}}"

(如果安装命名空间或实例名称不同,请将 npu-operator 替换为你的安装命名空间,将 npuoperatorctl-sample 替换为你的实例名称。)

步骤 3:批准每个节点重启

如果你在步骤 2 中设置了 autoUpgrade: true,请跳过此步骤——operator 会自动重启每个节点。

在手动模式下,operator 会等待管理员先为每个 NPU 节点添加 npu.openfuyao.com/approve-reboot=true 注解,然后才会重启该节点。该注解可以在任何时候设置——包括在步骤 2 之前——并且每次重启只会被 operator 消费一次。最简单的方式是一次性提前批准所有 NPU 节点:

kubectl get nodes -l openfuyao.com/npu.present -o name \
  | xargs -I{} kubectl annotate {} npu.openfuyao.com/approve-reboot=true --overwrite

或者按任意顺序一次批准一个节点:

kubectl annotate node ${nodeName} npu.openfuyao.com/approve-reboot=true

步骤 4:验证新驱动已生效

当每个节点的 DRIVER-UPGRADE-STATE 值为空时,滚动即完成。先检查节点标签:

kubectl get nodes -l openfuyao.com/npu.present \
  -o custom-columns=NAME:.metadata.name,DRIVER-UPGRADE-STATE:.metadata.labels.npu\.openfuyao\.com/driver-upgrade-state

然后确认每个 driver pod 都在运行新镜像:

kubectl get pod -n npu-operator -l app=npu-driver-daemonset \
  -o jsonpath='{range .items[*]}{.spec.nodeName}{"\t"}{.spec.containers[0].image}{"\n"}{end}'

最后,在每个 NPU 节点主机上运行 npu-smi(或者通过平台的 node-debug / SSH 流程进入节点),并确认主机报告的是新版本:

LD_LIBRARY_PATH=/var/lib/Ascend/driver/lib64/driver:/var/lib/Ascend/driver/lib64/common \
  /var/lib/Ascend/driver/tools/npu-smi info | head -2

现在你可以恢复在步骤 1.2 中停止的 NPU 工作负载了。

芯片自愈

CAUTION

实验性功能。 芯片自愈在 v1.2.4 中以技术预览形式提供,默认禁用。在生产环境启用之前,请先在 staging 环境中验证,并将 autoRecover 保持为 false,直到你已确认其在你的硬件配置上的行为。

某些 Ascend 部署场景——最典型的是在带 PCI passthrough 的 VM 中运行 910B——有时会使芯片进入一种状态:kernel modules 已加载,但驱动本身报告 dev_num=0 并拒绝 DCMI 调用。从 userspace 看,这像是一台“健康”的主机(所有 /dev/davinciN 都存在,模块已加载),但每次 npu-smi info 都会返回错误。唯一的恢复方式是重启节点。

v1.2.4 会自动检测这种情况:

  • driver pod 运行一个 health-watch 循环,每 60 秒使用 npu-smi info 探测每个 NPU。
  • 连续失败三次后(约 3 分钟),该循环会判定发生了运行时卡死:它会删除 driver-ready 标记(因此 validator pod 会看到 NotReady,device plugin 也会立即将芯片报告为 Unhealthy),并为 rebooter 写入一个 recovery 标记。
  • rebooter pod 会在下一轮 30 秒轮询周期中观察到该标记。

自动恢复与手动恢复

此时的行为由 spec.driver.recoveryPolicy.autoRecover 控制(与 autoUpgrade 无关):

autoRecover检测到卡死后的行为
false(默认)rebooter 发送一个 RebootRequired Event(reason=recovery),并等待管理员为该节点添加注解。
true在满足 uptime guard 和集群级锁之后,rebooter 重启该节点。

启用自动恢复后,芯片会在无需 operator 介入的情况下完成自愈——通常是 3 分钟检测时间加上几分钟重启时间。关闭后,驱动升级时使用的同一个 approve-reboot 注解也会授权恢复性重启。

一个典型的恢复配置如下:

spec:
  driver:
    recoveryPolicy:
      autoRecover: true   # rebooter reboots automatically on detected wedge

手动恢复演练

如果 autoRecover: false 且 health-watch 循环已经检测到卡死:

  1. 找出受影响的节点并读取标记原因:

    kubectl get nodes -l npu.openfuyao.com/reboot-required=true
    kubectl get events -A --field-selector reason=RebootRequired --sort-by=.lastTimestamp | tail

    对于自愈,Event 消息中会包含 reason=recovery。(驱动升级使用 reason=upgrade。)

  2. 在方便的时候批准重启:

    kubectl annotate node ${nodeName} npu.openfuyao.com/approve-reboot=true
  3. rebooter 会重启该节点;在全新启动后,driver pod 会干净地加载模块,validator pod 会重新确认就绪状态。

误报抑制

如果芯片在 rebooter 执行前自行恢复,health-watch 循环会清除其自身标记,因此节点不会被不必要地重启。