1. 现象描述

集群中 Slurm 表现异常:

  • sbatch 正常提交任务,但作业很快失败(FAILED/CANCELLED)

  • 计算节点上 slurmd 服务启动后很快退出

  • systemd 日志仅显示:

    Started Slurm node daemon.
    slurmd.service: Main process exited, code=exited, status=1/FAILURE
    slurmd.service: Failed with result 'exit-code'.

这类输出并不能直接说明根因,需要进一步深入 slurmd 前台日志与 GPU/驱动状态。


2. 快速定位:前台启动 slurmd 暴露真实错误

在故障节点执行:

slurmd -Dvvv

输出关键错误:

slurmd: error: Waiting for gres.conf file /dev/nvidia0

这句话非常关键,含义是:

  • Slurm 的 GPU 资源(GRES)配置中,指定了 GPU 设备文件(例如 File=/dev/nvidia0
  • slurmd 启动时会等待该设备节点出现
  • 但系统里 /dev/nvidia0 不存在,于是 slurmd 阻塞等待;systemd 侧可能因超时/退出表现为 status=1/FAILURE

同时验证 GPU 驱动:

nvidia-smi

报错:

NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver.

进一步确认硬件存在:

lspci | grep -i nv

可见 RTX 4090(AD102)设备在 PCIe 上存在,问题集中在 驱动没有正确加载


3. 根因分析:Kernel 升级导致 NVIDIA 内核模块不匹配

/boot 下看到两版内核:

  • vmlinuz-4.18.0-425.3.1.el8.x86_64(旧)
  • vmlinuz-4.18.0-553.89.1.el8_10.x86_64(新,近期更新)

Kernel 升级后,如果 NVIDIA 驱动是 runfile 方式安装.run),或者 DKMS/akmods 未成功重编译,那么会出现典型现象:

  • nvidia 内核模块无法为新内核构建/加载
  • /dev/nvidia0 不会生成
  • nvidia-smi 无法通讯
  • Slurm 配置了 GPU GRES(gres.conf 指向 /dev/nvidia0) → slurmd 启动卡住 → 作业秒失败

4. 驱动编译失败证据:MPOL_PREFERRED_MANY 宏冲突(UVM 编译不过)

尝试用 NVIDIA-Linux-x86_64-535.86.05.run 为新内核编译模块时,失败点出现在 nvidia-uvm

关键报错片段:

uvm_linux.h:150:32: error: expected identifier before numeric constant
#define MPOL_PREFERRED_MANY 5
include/uapi/linux/mempolicy.h:25:2: note: in expansion of macro 'MPOL_PREFERRED_MANY'
  MPOL_PREFERRED_MANY,

解释一下这类报错的本质:

  • 新内核头文件中 MPOL_PREFERRED_MANY 已作为枚举/符号存在
  • 535.86.05 的 UVM 代码又 #define MPOL_PREFERRED_MANY 5,导致名称冲突
  • 因此 nvidia-uvm 模块无法构建 → CUDA/UVM 不可用 → 驱动链不完整

结论:这个组合(EL8_10 新内核 + 535.86.05 runfile)在该环境下无法顺利构建 UVM 模块


5. 解决方案(按“恢复速度”排序)

方案 A:最快恢复业务(回滚到旧内核启动)

适用场景:希望立即恢复 GPU/Slurm 正常运行,后续再处理升级。

1)查看 grub 条目并设置旧内核为默认启动:

grubby --info=ALL | egrep "index=|kernel="
grubby --set-default /boot/vmlinuz-4.18.0-425.3.1.el8.x86_64
reboot

2)重启后验证:

uname -r
nvidia-smi
ls -l /dev/nvidia0
systemctl restart slurmd

只要驱动恢复,slurmd 就不会再卡在 /dev/nvidia0


方案 B:根治(升级驱动到支持新内核的版本,并采用 DKMS 机制)

适用场景:希望以后内核升级也不容易再“炸 GPU”。

思路:不要继续用老的 .run 驱动硬怼新内核,而是使用 官方仓库 + DKMS 的方式,让驱动自动为新内核编译模块。

1)卸载 runfile 驱动(避免混装):

/usr/bin/nvidia-uninstall || sh NVIDIA-Linux-x86_64-535.86.05.run --uninstall

2)切换到 DKMS 驱动路线(示例为 rhel8 系):

dnf -y install dnf-plugins-core
dnf config-manager --add-repo https://developer.download.nvidia.com/compute/cuda/repos/rhel8/x86_64/cuda-rhel8.repo
dnf clean all

dnf -y module reset nvidia-driver
dnf -y module enable nvidia-driver:latest-dkms
dnf -y module install nvidia-driver:latest-dkms
reboot

3)重启后验证:

uname -r
nvidia-smi
ls -l /dev/nvidia0
systemctl restart slurmd

方案 C:Slurm 临时止血(先让 CPU 作业跑起来)

适用场景:GPU 暂时不可用,但希望 slurmd 不要因为 GRES 阻塞启动。

处理方式:临时移除/注释 gres.conf 中对 /dev/nvidia0 的强依赖,或把该节点的 Gres=gpu:*slurm.conf 中移除。

常见修改点:

  • /etc/slurm/gres.conf 中类似:

    Name=gpu File=/dev/nvidia0

    临时注释掉

然后重启:

systemctl restart slurmd

这样该节点将以 CPU-only 方式可用,等 GPU 修好再恢复 GRES 配置即可。


6. 验证闭环:确认 Slurm 与 GPU 都恢复

GPU 恢复的标志:

nvidia-smi
ls -l /dev/nvidia0
lsmod | grep -E '^nvidia'

Slurm 恢复的标志:

systemctl status slurmd -l
scontrol show node <nodename> | egrep -i "State|Reason|Gres"

如果 Reason 不再包含 SlurmdDown,且节点状态从 DOWN/DRAIN 回到 IDLE/ALLOCATED,则闭环完成。


7. 经验总结与预防建议

  1. 内核升级 = 驱动重建
    • 任何一次 EL 内核升级,都要确认 NVIDIA 模块是否同步重编译、nvidia-smi 是否正常。
  2. 尽量使用 DKMS/仓库方式管理驱动
    • runfile 安装在“内核频繁升级”的场景下维护成本高,容易出现“升级完内核 GPU 全挂”。
  3. Slurm GPU 节点要考虑“驱动掉线”的降级策略
    • 如果不希望 GPU 掉了导致 slurmd 启动失败,可以对 GRES 配置与节点分区做更稳妥的隔离(例如 GPU-only 分区、节点状态自动 drain 等)。