容器里跑 nvidia-smi,报 Failed to initialize NVIDIA driver,或者干脆看不到任何卡——这是在 openEuler 上接 GPU 最常见的第一个坑。宿主机 nvidia-smi 明明正常,进了容器就没了。问题不在驱动本身,而在于把 GPU 设备、驱动库映射进容器这一层:nvidia-container-toolkit。openEuler 不是 NVIDIA 官方一级支持的发行版,仓库得借用 CentOS 8 的,这一步没走对,容器就看不到卡。
下面是我们在一台双 3060 的机器上,从最小化安装的 openEuler 一路把 GPU 接进 Docker 的完整记录,命令逐条贴出,踩过的坑也标出来。
openEuler 这边值得一提的两点,和 GPU 关系不大但影响稳定性:内存 RAS 做得比较实,内核/关键进程可以用高可靠内存,发生内存多 bit 故障时能杀掉受影响进程而不是整机复位;它也带一套在线巡检和 CVE 批量修复的运维工具。对长期跑 GPU 训练、不希望一条内存错误掀翻整机的场景,这两点是我们选它的实际理由。
环境
CPU:I9-10980XE
主板:MSI X299-PRO
内存:32G x2
GPU:GIGABYTE 3060 x2
OS:openEuler 22.03 (LTS-SP1)
安装方式:最小化安装
最小化安装意味着编译驱动需要的工具链都得自己补。
装依赖
dnf install kernel-devel dkms make -y
yum install bzip2-devel gmp-devel.x86_64 mpfr-devel.x86_64 libmpc-devel.x86_64 libSM-devel.x86_64 libxml2-devel -y
kernel-devel 和 dkms 是关键:装 dkms 的意义在于内核升级后驱动能自动重编,否则每次升内核都要手动重装驱动。注意 kernel-devel 的版本要和当前运行内核对得上,否则 DKMS 编译会失败。
装 NVIDIA 驱动
第一步,先把挡路的东西关掉:开源的 nouveau 驱动和 IPv6。 nouveau 会占着显卡,不禁掉 NVIDIA 驱动起不来。编辑 /etc/grub2.cfg 或 /etc/grub2-efi.cfg——具体是哪个取决于 BIOS 的引导模式(Legacy 还是 UEFI),在内核行末尾加上禁用参数:
echo 'Loading openEuler (5.10.0-136.17.0.93.oe2203sp1.x86_64) 22.03 (LTS-SP1)'
linuxefi /vmlinuz-5.10.0-136.17.0.93.oe2203sp1.x86_64 root=UUID=54a9e953-0a9e-45dc-9206-179453b0f341 ro cgroup_disable=files apparmor=0 ipv6.disable=1 rd.driver.blacklist=nouveau nouveau.modeset=0 crashkernel=512M
其中 rd.driver.blacklist=nouveau nouveau.modeset=0 是禁用 nouveau 的两个关键参数,改完重启生效。(上一篇讲过:如果你在别处抄了 nomodeset,这里要特别小心——nomodeset 会连 NVIDIA 驱动一起挡掉,这台机器上不能加。)
第二步,跑官方 .run 安装包。 静默安装、自动接受协议、不检测 X Window、装 DKMS 动态内核模块:
sh NVIDIA-.run -q -a -s --dkms --no-x-check
如果下载的是带 32/64bit 库的全量驱动,可以再加 --no-install-compat32-libs 跳过 32bit 库——纯跑容器/计算用不到 32bit 库。装完 nvidia-smi 应该能在宿主机看到两张卡。
装 Docker 和 nvidia-container-toolkit
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install docker-ce-19.03.8 docker-ce-cli-19.03.8 containerd.io
这里 Docker 借用的是 CentOS 的仓库,装的是指定的 19.03.8 版本。
关键的坑在 toolkit:openEuler 目前只能用 CentOS 8 的 nvidia-container-toolkit 仓库。 直接找 openEuler 的源是没有的,必须指到 centos8:
curl -s -L https://nvidia.github.io/nvidia-docker/centos8/nvidia-docker.repo | sudo tee /etc/yum.repos.d/nvidia-container-toolkit.repo
yum install -y nvidia-container-toolkit
装完之后,容器里才有能看到 GPU 的那一层。
给容器指定 GPU
验证整条链路是否通,直接在容器里跑 nvidia-smi:
docker run -it --gpus='"device=1"' 镜像 nvidia-smi
--gpus='"device=1"' 把第 2 张卡(编号从 0 开始)单独给这个容器。要给多张就列出来,比如 --gpus='"device=0,1,2.."'。
能在容器里看到指定的那张卡、型号和显存都对,说明驱动、Docker、toolkit 这三层全通了。如果到这一步容器里还是空的,九成是 toolkit 那步的 CentOS 8 仓库没配对,回去检查 /etc/yum.repos.d/nvidia-container-toolkit.repo 指向的是不是 centos8。
