CentOS Stream 9安装NVIDIA驱动与CUDA Toolkit完整指南

发布时间:2026/10/2 7:42:09
CentOS Stream 9安装NVIDIA驱动与CUDA Toolkit完整指南 这个周末我又双叒叕给一台CentOS Stream 9工作站装NVIDIA驱动了。说实话装过Ubuntu的人第一次摸CentOS Stream 9的N卡驱动十有八九会懵Ubuntu那种几条apt命令装好的体验在这里完全不存在你需要面对的是内核头文件、nouveau、Secure Boot和DKMS这一整套东西任何一个环节没处理干净后面就是无穷无尽的报错和重启。这篇文章就是把我从裸机到nvcc -V跑通的完整流程、踩掉的坑、以及每个步骤背后的原因从头到尾记录下来给同样要在CentOS Stream 9上装nvidia驱动和cuda-toolkit的人一个可以直接照抄的参考。1. 开工前必须想清楚的三件事版本、内核、安全启动装N卡驱动不是打开官网下载一个.run文件双击就完事。在CentOS Stream 9这种滚动更新模型下装之前不把三件事想清楚后面基本注定要返工。1.1 先锁定CUDA版本再倒推驱动版本很多人的第一反应是装最新驱动结果后面装CUDA Toolkit时发现驱动版本和CUDA版本对不上要么降级驱动要么装一个和需求不匹配的CUDA版本非常被动。这里有个NVIDIA官方一直强调的基本对应关系CUDA Toolkit每个版本都要求驱动版本不低于某个阈值更高版本的驱动能向下兼容多个CUDA版本。举个例子CUDA 12.x要求驱动不低于545系列具体看小版本而535系列的驱动最多只能配合CUDA 12.2以下使用。如果你跑的是PyTorch、TensorFlow建议先查官方支持矩阵确认你要用的CUDA版本再反过来定驱动版本而不是先装个最新的驱动再说。我这次的选择是CUDA 12.4 550系列驱动。原因很简单12.4是当前生态兼容面最广的版本之一主流深度学习框架都跟得很紧550系列驱动对多卡通信、DDP的支持也足够稳定而且后续如果要升级到CUDA 12.6、12.8550系列驱动依然在兼容范围内留出了余量。1.2 内核头文件必须和当前内核版本严格对齐驱动编译不是凭空编译的它要针对当前运行的内核生成内核模块。CentOS Stream 9默认内核是5.14系列但系统更新后/usr/src/kernels/下面可能会躺着好几个版本的内核头文件。如果你吭哧吭哧装完驱动发现nvidia-smi报Failed to initialize NVML: Driver/library version mismatch十有八九是内核头文件版本和当前内核没对齐。这属于老生常谈但每次总有人踩因为CentOS Stream 9的滚动更新太容易把系统里的kernel和kernel-devel版本搞成不一致了。我后来养成了一个习惯装依赖前先看uname -r然后确保 kernel-devel、kernel-headers 的版本与之一一对应。1.3 Secure Boot装前不处理装后悔断肠这一点特别容易被忽略尤其是新买的工作站和品牌机。新版主板默认开启Secure BootLinux内核模块如果没经过签名机制授权系统直接拒绝加载或者加载后模块验证失败。NVIDIA闭源驱动不提供现成的签名模块所以你在Secure Boot开启的状态下装好驱动重启后大概率发现驱动根本没加载要么黑屏要么卡在登录界面循环。处理方案有两个一是进BIOS关掉Secure Boot个人开发机、测试机的常规做法二是走完整的模块签名流程生成Machine Owner Key给NVIDIA驱动模块签上密钥适合有安全合规要求的服务器环境。我这次因为机器是个人开发用的测试工作站直接关了省心。生产环境不建议这么干但也不能不处理就硬装。2. 基础环境准备禁用Nouveau并装齐编译工具链前置条件想清楚后动手前要把系统环境收拾干净。这一步骤决定了后续驱动安装会不会在半路翻车。2.1 先确认GPU型号和内核版本无论你之前是什么状态先用三条命令确认硬件和内核lspci | grep -i nvidia uname -r gcc --versionlspci能看到显卡型号比如我这边显示的是NVIDIA GA102 [GeForce RTX 3080]。这套流程对Ampere、Ada Lovelace以及更早的架构都适用如果你手里的是特别老的卡比如GTX 700系列甚至更早那就得注意了新版驱动已经不再支持需要去NVIDIA官网翻legacy版本安装逻辑虽然一致但版本选择思路完全不同。uname -r输出的就是当前内核版本记下来后面很多地方都要对照它。gcc --version则用来确认系统里已经有可用的C编译器没有的话后面编译内核模块会直接报错尽早暴露问题比装到一半暴露要好。2.2 禁用Nouveau一步都不能省CentOS Stream 9默认没有预装NVIDIA闭源驱动但内核自带的nouveau开源驱动是存在的。nouveau虽然能点亮桌面但在计算场景下性能和稳定性都不行而且它一旦加载NVIDIA官方驱动模块就无法绑定GPU二者只能选一个共存。禁用nouveau的正确姿势sudo tee /etc/modprobe.d/blacklist-nouveau.conf EOF blacklist nouveau options nouveau modeset0 EOF sudo dracut --force然后编辑/etc/default/grub在GRUB_CMDLINE_LINUX这一行末尾加上rd.driver.blacklistnouveau再重新生成GRUB配置。这里要注意引导方式是BIOS还是UEFI路径不一样# BIOS引导 sudo grub2-mkconfig -o /boot/grub2/grub.cfg # UEFI引导 sudo grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg这里有个很多人会漏掉的点写完blacklist文件后执行dracut --force是必须的。因为CentOS Stream 9的initramfs里如果已经包含了nouveau模块光写blacklist文件不重建initramfs重启后nouveau照样会被加载。我第一次装的时候就是漏了这步结果nvidia-smi一直提示找不到设备查了半天才发现nouveau还在内核里。2.3 装齐编译工具链和内核开发包驱动安装过程中需要调用系统编译器生成内核模块所以gcc、make、kernel-devel这些都是硬依赖sudo dnf install -y gcc make kernel-devel kernel-headers elfutils-libelf-devel dkmskernel-devel提供内核源码树DKMS则负责在内核升级时自动重新编译驱动模块。CentOS Stream 9的基础源里就有dkms不需要额外添加EPEL这点比老版本方便。装完以后务必验证一下内核头文件版本与当前内核匹配ls /usr/src/kernels/$(uname -r)如果这个目录不存在说明kernel-devel版本不对或者没装上。出现这种情况优先用精确指定版本的方式再装一次sudo dnf install -y kernel-devel-$(uname -r)。之所以反复强调匹配是因为CentOS Stream 9的滚动更新很容易出现系统里跑着5.14.0-362这个内核头文件却是上一版5.14.0-284。这种情况驱动装得再对模块编译出来也加载不到当前内核上排错的时候会非常头大。3. 驱动安装路线选择为什么我最后选了CUDA官方仓库CentOS Stream 9上装NVIDIA驱动有几种常见方式NVIDIA官方runfile、RPM Fusion的非自由仓库、以及NVIDIA CUDA仓库。我这次三种都实际试了一遍最后长期使用的是CUDA官方仓库下面把三者的差异和选择逻辑讲清楚。3.1 三条路线的优缺点对比为了让你少走弯路我把三者的本质区别先讲透路线安装方式优点缺点NVIDIA runfile下载NVIDIA-Linux-x86_64-xxx.run后手动执行版本选择自由、不依赖第三方仓库每次内核升级都要手动重装需要在init 3文本模式下关闭图形界面残留进程会导致安装失败RPM Fusion akmod-nvidiadnf install akmod-nvidia集成DKMS内核升级自动重建模块仓库更新节奏滞后于NVIDIA官方新驱动对CentOS Stream 9的适配有时会慢半拍NVIDIA CUDA仓库配置cuda-rhel9.repo后dnf module install驱动版本和CUDA版本由官方一并维护组合不打架支持parallel-install多个CUDA版本仓库体积大首次拉包时间稍长很多教程推荐runfile因为看起来最官方。但我个人在CentOS Stream 9上更推荐CUDA仓库原因有两个一是它通过dnf module管理nvidia-driver能直接搞定驱动和CUDA之间的版本匹配问题二是后续升级只用dnf update不需要每次都进文本模式重装对于长期跑训练的工作站来说省心太多了。runfile方式在内核更新之后如果不手动重装一次驱动就处于半残状态这对生产机来说是无法接受的。3.2 配置CUDA仓库并安装驱动具体操作如下sudo dnf config-manager --add-repo https://developer.download.nvidia.com/compute/cuda/repos/rhel9/x86_64/cuda-rhel9.repo sudo dnf clean all sudo dnf -y module install nvidia-driver:latest-dkms注意这里的nvidia-driver:latest-dkms是module流它包含驱动本体和DKMS钩子。安装完成后重启再用nvidia-smi确认驱动和CUDA driver版本。对于纯计算节点我个人建议装完驱动后直接把默认运行级别切到multi-usersudo systemctl set-default multi-user.target sudo reboot如果之后想切回图形界面再执行systemctl set-default graphical.target重启即可。对一台要做深度学习或科学计算的主机来说长期保持在multi-user下反而是最稳的既避免了Xorg和NVIDIA驱动的兼容性冲突也减少了一大块内存占用。3.3 验证内核模块是否正常加载重启后跑lsmod | grep nvidia nvidia-smi如果lsmod能看到 nvidia 开头的几个模块nvidia-smi能输出GPU温度、显存、驱动版本说明驱动层已经OK。常见的nvidia-smi报错如No devices were found原因基本集中在三种nouveau没有禁干净、内核头文件不匹配、Secure Boot拦截了模块加载。如果模块确实没有被加载去看/var/log/messages或执行dmesg | tail -50重点搜索nvidia和module verification failed关键字。我之前遇到过module verification failed: signature not found的报错那就是Secure Boot没关导致的进BIOS关掉再重启就好了。你也可以先用mokutil --sb-state查看Secure Boot的状态省得盲猜。4. CUDA Toolkit安装与环境变量配置驱动层搞定后CUDA Toolkit的安装反而简单了因为我们已经走了CUDA官方仓库仓库里包含各种版本的cuda包不用再单独去官网下载runfile。4.1 安装指定大版本的CUDA我这里是CUDA 12.4sudo dnf -y install cuda-toolkit-12-4这里要说明一下如果之前没有单独装驱动也可以直接执行sudo dnf -y install cuda-12-4这个metapackage会连带把驱动和toolkit一起装上。我这次因为已经在3.2节用module方式装好了驱动所以只需要装toolkit部分避免重复拉取驱动包。仓库方式安装还有一个巨大的好处可以同时安装多个CUDA大版本。比如我需要跑的某个旧框架依赖CUDA 11.8可以再执行sudo dnf -y install cuda-toolkit-11-8两个版本共存后面通过切换PATH环境变量来决定用哪一套。这一点是runfile方式非常难做到的runfile装完一套再装第二套很容易把/usr/local/cuda软链接搞乱。而仓库安装包的目录都是干净的/usr/local/cuda-12.4、/usr/local/cuda-11.8互不冲突。安装完成后会有一个/usr/local/cuda软链接指向最新版本。如果你需要固定到某个版本手动调整软链接sudo rm -f /usr/local/cuda sudo ln -s /usr/local/cuda-12.4 /usr/local/cuda4.2 配置环境变量PATH和LD_LIBRARY_PATH这一步看似简单但很多人装完nvcc -V跑不出来十有八九是环境变量没配或者没source。我把配置写到/etc/profile.d/cuda.sh这样所有用户登录后都能直接用export PATH/usr/local/cuda/bin:$PATH export LD_LIBRARY_PATH/usr/local/cuda/lib64:$LD_LIBRARY_PATH保存后执行source /etc/profile.d/cuda.sh或者重新登录终端。注意CUDA 12.x版本的lib64目录里有一堆libcuda.so.1等运行时链接库。某些程序会直接依赖libcuda.so这个不带版本号的软链接如果启动时报缺少共享库可以先看下/usr/local/cuda/lib64/里的软链接是否齐全。用仓库安装的话这个问题很少见但如果是手动拷贝CUDA目录或者卸载不干净导致的问题这个方向值得排查一遍。4.3 编译运行官方样例验证环境变量配好还不算完真正验证CUDA编译器能不能用最好的办法是编译官方samples里的deviceQuerysudo dnf -y install gcc-c cp -r /usr/local/cuda/samples ~/cuda-samples cd ~/cuda-samples/1_Utilities/deviceQuery make ./deviceQuery输出末尾如果看到Result PASS说明驱动、CUDA Toolkit、编译器链路全部正常。顺手再跑一下bandwidthTestcd ~/cuda-samples/1_Utilities/bandwidthTest make ./bandwidthTest这个工具主要测显存带宽跑出来的数值一般会接近官方标称值。如果带宽明显偏低先怀疑GPU是否降频、PCIe链路是否跑在低速档位用nvidia-smi -q -d PERFORMANCE或lspci -vv | grep LnkSta查一下当前链路状态。这些都属于装好之后才可能暴露的硬件层面问题早发现早处理。5. 实测验证与典型报错排查面板装完不是终点能不能持续稳定使用才是重点。这一节我把自己实测中遇到过的几个典型报错和排查思路整理出来每一个都是实打实踩过的坑。5.1 Driver/library version mismatch 的真相这是N卡驱动最出名的神坑。症状是nvidia-smi报Failed to initialize NVML: Driver/library version mismatch而dmesg里能看到nvidia模块已经加载。这个问题的本质是内核里加载的nvidia内核模块版本和/usr/lib64下运行时库libnvidia-ml.so的版本不一致。常见诱因是之前用runfile方式装过旧驱动后来又用dnf装了新驱动但旧的内核模块还挂在内存里另一种情况是GPU进程没退干净驱动无法正常卸载。排查和解决# 看看当前驱动版本 cat /proc/drivers/nvidia/version # 查找占用GPU设备的进程 sudo fuser -v /dev/nvidia* # 强制卸载nvidia模块再重新加载 sudo rmmod nvidia_drm nvidia_modeset nvidia_uvm nvidia sudo modprobe nvidia如果在rmmod时报Module nvidia is in use说明还有进程占用找到对应的PID杀掉再执行。这一招对多数mismatch问题都管用。如果rmmod还是卸不干净最好的办法就是彻底重启开发机上重启一次五分钟比在模块状态里折腾一小时划算。5.2 DKMS模块与内核升级的配合仓库方式安装的nvidia-driver:latest-dkms自带DKMS内核升级后模块会自动重建理论上不用操心。但DKMS自动重建有一个前提新内核对应的kernel-devel包已经装好。所以CentOS Stream 9升级内核后我建议按这个顺序操作sudo dnf update -y sudo dnf install -y kernel-devel-$(uname -r)然后重启重启后系统会跑一遍DKMS的rebuild流程。如果重启后发现驱动没加载检查一下dkms status输出里应该能看到类似nvidia/550.xx, 5.14.0-xxx, x86_64: installed的记录。如果状态不是installed而是failed去/var/lib/dkms/nvidia/xxx/build/make.log看编译日志十有八九是gcc版本换新导致的编译报错或者是新内核头文件缺了某个include。这里有个小技巧升级内核前先把开发包装好再重启比重启后发现驱动没了再补包要稳得多。5.3 nvcc找不到的诡异局面还有一种特别气人的情况驱动正常、nvidia-smi正常但nvcc -V提示command not found。这种一般是CUDA的bin目录没进PATH。如果你已经写了/etc/profile.d/cuda.sh但还没生效多半是当前shell没重新source。这里有个小细节容易被忽略bash的命令哈希缓存。有时候PATH里明明已经有了nvcc但因为之前出现过一次command not foundbash把失败结果缓存了导致再次执行依然提示找不到。解决方法是执行hash -r清一下缓存或者直接新开一个终端。这个不起眼的小问题卡过我十分钟写出来给后来人排个雷。6. 迭代维护内核升级与驱动重装的经验总结装好一次不算完CentOS Stream 9是滚动更新模型内核更新频繁驱动跟上内核节奏才是长期稳定使用的关键最后这部分说说维护层面的经验。6.1 我的一套日常更新顺序现在我自己固定的更新顺序是先更新系统但先不重启sudo dnf update -y检查是否有新版内核rpm -q kernel | tail -3如果有新内核确认对应的kernel-devel同步装上sudo dnf install -y kernel-devel-$(uname -r)重启进新内核重启后查dkms status确保nvidia模块状态是installed跑一次nvidia-smi确认驱动还在这套顺序执行下来我几乎没有遇到过内核升级后驱动失效的问题。反而容易踩坑的是update之后没装对应kernel-devel重启后DKMS编译失败驱动直接变成空白。所以我在第3步上从不偷懒新内核只要确认更新对应的devel包一定是同时装的。6.2 什么时候需要手动清理旧CUDA版本仓库方式安装的多个CUDA版本并存时/usr/local下会有多个cuda目录。长期不动的话/usr/local/cuda这个软链接始终指向最新版本而老版本占用的磁盘空间也不少。我每隔两三个大版本会清理一次不再用的老版本sudo dnf remove cuda-toolkit-11-8 sudo rm -rf /usr/local/cuda-11.8清理前先确认没有项目依赖这个版本。最稳妥的做法是先改环境变量指向新版本重新编译几个核心项目跑通验证再回来删旧版本。有些人图省事直接删目录结果dnf metadata里还留着记录下次update又给你装回来反而更麻烦。6.3 日志与版本记录的习惯很多人忽略了对驱动和CUDA版本做记录。我建议装完驱动后把下面这些信息记到一个文件里驱动版本、CUDA版本、内核版本、安装方式、当天踩过的坑和解决方式。等到半年后系统出了奇怪问题回头翻这份记录比去论坛查半天帖子高效得多。另外再分享一个细节NVIDIA驱动包在系统里的痕迹不只在/usr/lib64还有/usr/share/doc/nvidia-driver、/etc/X11/xorg.conf.d/下的配置文件。手动折腾驱动时这些位置容易留下旧配置最彻底的清理方式是dnf remove *nvidia*之后手动检查这些目录。保留太多的残留配置文件是换了新版本驱动后出现莫名其妙兼容问题的主要源头之一。在我自己的CentOS Stream 9工作站上这套组合已经稳定跑了半年多中间经历了三轮内核更新驱动模块全靠DKMS自动重建一次都没有在升级后掉链子。希望这篇记录也能帮你少走几天弯路一次把驱动和CUDA Toolkit都装利索。