折腾PVE那些事——vGPU驱动

小介绍

vGPU是NVIDIA推出的显卡虚拟化方案,能将一张显卡拆分成多个虚拟显卡并分配给虚拟机。(官方把这个叫什么GPU的算力原子化,什么技术革命云云,然后告诉你所以要付一大笔钱)。这样有很多好处,比如一张很强的卡可以拆出多个单元每个用来进行不太复杂的计算,比如云游戏多开,GPU算力出租等。所需要的只是一组驱动。
这个专有驱动,通常我们叫它Grid或者vGPU驱动。这个驱动是成套的,需要host驱动装在物理机上,client装在虚拟机上。host驱动将卡支持拆分和将虚拟设备分配给虚拟机,client驱动能将这个虚拟设备进行利用。
但是NVIDIA表示这是企业解决方案,个人无法通过官方渠道购买这些驱动的授权。需要你作为企业直接和NVIDIA沟通,然后洽谈费用。个人玩家很少有这个条件吧,所以可以考虑走点歪门邪道。

背景

看到TeslaP4这张卡待在机箱里面不干事有点难受,直通给某个虚拟机又感觉没必要,我只是想让每个机器都能有显示画面的图形加速,不要总是cpu渲染弄得卡卡的。
然后我就全网找驱动,给nvidia发邮件然后被嘲讽了(都可以,但是要先给钱)。找了不少教程,但是驱动都比较老了,大部分是适配PVE 7.X的host驱动,不降级安装不上。于是在淘宝上花钱买了驱动代安装服务,并且完整记录下安装过程,从对方的私有网盘中捞走了各种版本和平台的驱动,可以免费提供给看到这个教程的朋友们。

准备

机子,这之前捣鼓了不少。
一张可以安装vGPU的显卡,这里是一张Tesla P4的HHHL小刀卡。
PVE 系统,这里的版本是8.3 如果之前有Nvidia驱动,需要卸载干净
一台待安装的虚拟机,这里是Windows10
NVIDIA KVM host 驱动,选择对应的版本
NVIDIA Client驱动,选择对应的版本
FastAPI Docker搭建的奇妙授权服务器,用来骗NVIDIA我们是付了钱的高贵企业用户
patch补丁,用于修补授权问题

开始折腾

前置检查

检查适配配置单,只有在清单里面的卡能够使用vGPU驱动。如果不在清单里面可以找找不同版本驱动的说明书。如果都没有就可以放弃了。

卸载其它相关驱动

确保PVE主机中的NVIDIA驱动已经卸载完毕。

apt purge nvidia*
apt autoremove

卸载nouveau所有外围软件并禁用nouveau内核模块,这是NVIDIA驱动安装的老敌人了。同时可以考虑允许不安全中断。此处请注意一下不安全中断,这个可以在设备初始化等故障时帮助你排除错误,但是它并不安全。

apt remove nouveau
echo  "blacklist nouveau" >>/etc/modprobe.d/disable-nouveau.conf
echo  "options nouveau modeset=0" >>/etc/modprobe.d/disable-nouveau.conf

# 允许不安全中断,因为并不总是需要而且比较不安全。如果你要用,可以把它取消注释
# echo "options vfio_iommu_type1 allow_unsafe_interrupts=1" >/etc/modprobe.d/iommu_unsafe_interrupts.conf

# 少数机型(其实多发于Windows)会在访问MSRs的时候出现Code 43错误,添加它能忽略错误防止崩溃
echo "options kvm ignore_msrs=1" > /etc/modprobe.d/kvm.conf

顺带更新一下initramfs

sudo update-initramfs -u
reboot

最后检查一下是否卸载干净。使用lsomd检查NVIDIA驱动,应该不存在或者仅有nvidiafb初始驱动。而且使用lspci确定显卡在硬件上可以检测到。

lsmod | grep nvidia
lspci | grep -i nvidia

开启IOMMU

开启PVE的IOMMU,intel和AMD的CPU需要不同的配置。首先你需要在 PVE物理机 启动阶段进入BIOS/UEFI ,在那里面打开IOMMU的硬件支持。不同机型的打开方式不一样,此处不再赘述。
然后需要加载VFIO模块,PVE才能把虚拟设备做分配。
写入或者创建一个 /etc/modules

vfio
vfio_iommu_type1
vfio_pci
vfio_virqfd

编辑 /etc/default/grub 并添加如下内容。

# intel_cpu
GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on"

# amd_cpu
GRUB_CMDLINE_LINUX_DEFAULT="quiet amd_iommu=on"

再次更新initramfs和GRUB并重启主机

update-initramfs -u
update-grub
reboot

保险起见,在重启之后验证一下

# 检查IOMMU是否初始化成功
dmesg | grep -e DMAR -e IOMMU

# 查看IOMMU的group是否包含了显卡
find /sys/kernel/iommu_groups/ -type l

安装驱动

NVIDIA的驱动是根据内核模块编译的,如果内核后续有更新还得每次手动编译,不然更新之后全失效了。还好有动态内核模块支持,由于内核源码树不包含NVIDIA(Linus不喜欢NVIDIA),使用dkms可以把NVIDIA注册到管理系统中,这样每次安装新的内核时可以触发dkms来再次针对新内核编译一次,而且自动安装到内核模块的目录下。
还有需要把PVE的头也安装进来,有的时候没有头PVE也能正常运行,但是安装NVIIDA驱动时不行。

apt install dkms build-essential pve-headers pve-headers-`uname -r` dkms jq uuid-runtime aria2 -y

安装mdevctl

curl http://ftp.br.debian.org/debian/pool/main/m/mdevctl/mdevctl_0.81-1_all.deb -o /tmp/mdevctl.deb && dpkg -i /tmp/mdevctl.deb

好的,接下来需要针对平台来找找你需要什么样的驱动了。我可以给你一张表供你参考。
以下表格基于 PVE、Debian、Linux 内核以及常见的 NVIDIA vGPU (GRID) 驱动版本关系,并结合了一些社区实践经验:

PVE 版本 Debian 版本 大致默认/常见内核范围 [^1] 可能适用的 NVIDIA vGPU Host Driver 分支 [^2] [^3] GRID 版本 [^4] 注意事项与建议
PVE 8.x Debian 12 (Bookworm) 6.2, 6.5, … (持续更新) 525.x, 535.x, 550.x(需要较新分支支持新内核) 15.x, 16.x, 17.x Bookworm 内核较新 (6.x+)。强烈依赖 DKMS 和可能的内核补丁。新驱动分支(如 535, 550)对新内核支持更好,但 vGPU Unlock 补丁需要跟上。检查你使用的 Unlock 工具支持哪个驱动版本。
PVE 7.x Debian 11 (Bullseye) 5.11, 5.13,5.15(LTS, 常见), 5.19, 6.2 (后期可选) 470.x(LTSB, 兼容性好,支持到 5.15 左右较稳定),510.x, 525.x(支持较新卡和功能,对 5.15+ 内核可能需特定版本或补丁) 13.x, 14.x, 15.x PVE 7 生命周期长,内核跨度大。5.15 内核是中期主力,兼容性信息较多。若使用较新内核(如 PVE 7.4 默认的 5.15 或手动升级的更高版本),需确认驱动和补丁支持。470 分支是较稳妥的选择,但可能不支持最新 GPU。
PVE 6.x(已 EOL) Debian 10 (Buster) 5.0, 5.3,5.4(LTS, 常见) 440.x, 450.x, 460.x, 470.x(早期版本如 440/450 对 5.4 内核支持良好) 10.x, 11.x, 12.x, 13.x PVE 6 已停止支持,不建议新部署。5.4 内核是其生命周期中的主力。较旧的驱动分支(440-470)适用,具体看你的显卡型号和补丁需求。

重要注解和说明:

[^1]: 内核版本: PVE 在其生命周期内会不断更新内核版本。表格中列出的是该 PVE 大版本发布时或在其生命周期内常见的内核版本范围。强烈建议在你的 PVE 主机上运行 uname -r 来确认你当前实际使用的内核版本。安装驱动时必须针对这个确切的版本(或使用 DKMS 自动编译)。
[^2]: NVIDIA vGPU Host Driver 分支: 这只是可能适用的驱动分支 (Branch),例如 535.x 代表 535.104.05, 535.113.01 等等。具体哪个精确版本能用,很大程度上取决于你使用的内核详细版本。

可以来我的小云盘下载你需要的驱动(链接占位符)

wget "https://cfdisk.xidian.one/NVIDIA/vGPU/NVIDIA/17.0/NVIDIA-Linux-x86_64-550.54.10-vgpu-kvm-patched-kernel6.8-OA5500.run"
chmod +x NVIDIA-Linux-x86_64-550.54.10-vgpu-kvm-patched-kernel6.8-OA5500.run
./NVIDIA-Linux-x86_64-550.54.10-vgpu-kvm-patched-kernel6.8-OA5500.run -m=kernel
reboot

驱动授权

驱动授权分为两部分,首先你需要使用一个补丁,让加载nvidia-vgpud和nvidia-vgpu-mgr之前注入一个动态链接库文件。从而实现对激活函数的劫持,把它导向我们的私有激活服务器。

mkdir /etc/systemd/system/{nvidia-vgpud.service.d,nvidia-vgpu-mgr.service.d}
echo -e "[Service]\nEnvironment=LD_PRELOAD=/opt/vgpu_unlock-rs/target/release/libvgpu_unlock_rs.so" > /etc/systemd/system/nvidia-vgpud.service.d/vgpu_unlock.conf
echo -e "[Service]\nEnvironment=LD_PRELOAD=/opt/vgpu_unlock-rs/target/release/libvgpu_unlock_rs.so" > /etc/systemd/system/nvidia-vgpu-mgr.service.d/vgpu_unlock.conf
systemctl daemon-reload

mkdir -p /opt/vgpu_unlock-rs/target/release
cd /opt/vgpu_unlock-rs/target/release
wget -O libvgpu_unlock_rs.so https://cfdisk.xidian.one/NVIDIA/vGPU/NVIDIA/17.0/libvgpu_unlock_rs_only_17.0.so

然后便是私有激活授权服务器端,我们用一个LXC容器最为方便。它会从HTTP响应驱动的激活申请。

cd /var/lib/vz/dump/
aria2c -s 8 -x 8 -j 10 'https://cfdisk.xidian.one/Proxmox/LXC/FASTAPI-DLS/vzdump-lxc-888-2024_10_20-01_12_57.tar.zst'
pct restore 888 /var/lib/vz/dump/vzdump-lxc-888-2024_10_20-01_12_57.tar.zst --storage local-lvm

接下来需要登录进LXC容器中,执行指令使用docker启动激活容器:

docker run \
    --restart always \
    --name fastapi-dls \
    -d -e DLS_URL=10.10.10.99 \
    -e DLS_PORT=443 \
    -p 443:443 \
    ncc/fastapi-dls

这里的URL是docker网络内部的URL,需要设置符合你本地的IP需要你到这个容器的Network选项中设置IP。后续Client驱动面板中填写它就好了。

检查和使用

检查设备中确实能识别到插上去的卡。使用lspci看看。然后进web控制台看看“添加pci设备”中是否有这个选项。
注意,只有q35机型的设备可以使用PCIE设备,i1440f只能使用PCI设备。所以如果你想给虚拟机分配内容,你需要用q35机型,UEFI启动。
成功后在给每个设备添加pci时选中显卡,后面会有拆分选项,可以选择拆成什么样的卡,包括A/B/C/Q。给大家一张表,这是根据NVIDIA官方手册整理的:
NVIDIA vGPU Profile 类型对比

特性 A-Profile (Virtual Applications) B-Profile (Virtual PC) Q-Profile (RTX Virtual Workstation) [^5] C-Profile (Virtual Compute Server) [^6]
主要目标用户/场景 应用虚拟化 (如 Citrix XenApp, VMware Horizon Apps), 轻量级会话 标准 VDI 知识工作者 (Office, Web, 多媒体) 专业图形设计师, 工程师 (CAD/CAM/CAE, DCC), 高端 VDI HPC, AI/ML/DL, 数据科学 (无图形输出需求)
图形 API 支持 (DirectX, OpenGL) 有限支持/基本兼容性 (侧重应用流传输) 是 (主流性能) 是 (高性能, 专业特性) 否 (无显示输出能力)
CUDA / OpenCL 计算支持 通常否[^7] 是 (高性能) 是 (最高性能, 优化计算)
主要优势 高密度用户共享 (针对应用), 成本效益 平衡的图形性能和用户密度 (标准 VDI) 专业级图形性能和特性, ISV 认证 (官方), 大显存 纯计算性能, 最大化利用 GPU 计算资源
典型 Framebuffer (显存) 分配 较小或共享 中等 (如 512MB – 4GB+) 较大 (如 1GB – 24GB+, 取决于物理卡和 Profile) 非常大 (可分配大部分或全部物理显存)
性能等级 基础 主流/商业级 高端/工作站级 计算密集型
官方所需许可证类型 (NVIDIA AI Enterprise 或旧版) NVIDIA Virtual Applications (vApps) NVIDIA Virtual PC (vPC) NVIDIA RTX Virtual Workstation (vWS) NVIDIA Virtual Compute Server (vCS)
常见 Profile 命名示例 (以 Tesla P4 为例) (P4 通常不主推 A 类型) TESLA_P4-1B,TESLA_P4-2B TESLA_P4-1Q,TESLA_P4-2Q,TESLA_P4-4Q TESLA_P4-8C(使用全部显存作为计算)
备注 适合大量用户仅运行特定应用 最适合普通用户的桌面虚拟化加速需求 需要高保真图形和专业软件兼容性 无法连接显示器, 纯粹的后端计算

注解:

[^5]: Q-Profile 以前被称为 Quadro vDWS (Quadro Virtual Data Center Workstation),现在品牌统一为 RTX vWS。它旨在提供与物理 Quadro/RTX 工作站显卡相当的功能和性能。
[^6]: C-Profile 是专门为计算任务设计的,它不提供任何图形输出能力。分配了 C-Profile 的虚拟机无法直接驱动显示器,即使你尝试连接。它的所有 GPU 资源都用于 CUDA/OpenCL 计算。
[^7]: 虽然 B-Profile 主要面向图形,但部分较新的驱动和硬件组合在特定情况下可能允许非常有限的 CUDA 功能,但这并非其设计目标,性能也远不如 Q 或 C Profile。一般认为 B-Profile 不支持 CUDA。

以上面的表格为参考,给虚拟机分配一张虚拟卡,进入虚拟机,下载并安装client驱动。
不出意外会弹出无法验证驱动有效性的弹窗,此时把内网中授权服务器docker的ip放进去。并从授权服务器下载token文件放进虚拟机本地驱动文件夹。
使用它检查是否安装正常:

nvidia-smi --query-gpu=gpu_name --format=csv

Token放置位置为 C:\Program Files\NVIDIA Corporation\vGPU Licensing\ClientConfigToken\ ,需要你手动创建 ClientConfigToken

此时应该会成功。如果此时出现无法识别显卡的错误,有一个邪门小妙招。可以在host中使用不匹配的profile替代自动识别,比如我这里把TeslaP4的profile替换了,让机子误以为这是一个RTX A6000,并且可以分配24G显存(谨慎尝试!我没试过,不知道会发生什么事情!)。此时就不会爆出无法识别的异常了。

参考链接

readthedocs 超详细的PVE vGPU安装配置教程
国光PVE环境搭建教程-vGPU教程
佛西博客 vGPU_unlock的原理和作用
docker-hub collinwebdesigns fastapi-dls 下载量最多的授权服务器镜像

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注