请注意,此教程大部分步骤可能已经过时,仅供参考
运行 Linux 虚拟机可能会遇到一些关于显卡的问题: qemu/vmware/virtualbox 的虚拟显卡无法正常运行一些渲染程序和游戏。这些软件要想正常运行,解决方法只有物理显卡直通和显卡虚拟化。显卡有限的情况下,想要每个虚拟机都分配一个物理显卡是不现实的,对于显卡虚拟化,非专业显卡无法开启显卡虚拟化, Linux 下也并没有像微软 Hyper-V + GPU-PV 之类的黑科技。
vgpu-unlock 是解锁 NVIDIA 消费级显卡虚拟化功能的 Linux 补丁,目前已经支持以下架构的大多数显卡,对应相同架构的计算卡。
- Maxwell 1代架构,支持大多数的GTX 700系显卡(对应Tesla M10)
- Maxwell 2代架构,支持大多数的GTX 900系显卡(对应Tesla M60)
- Pascal架构,支持大多数的GTX 1000系显卡(对应Tesla P40)
- Turing架构,支持大多数的GTX 1600系和RTX 2000系显卡(对应Quadro RTX 6000)
注意: vgpu-unlock 暂时不支持Ampere(RTX 3000系)架构及以上显卡
准备
vgpu_unlock 默认仅支持 ≥5.10 (5.11~5.13版本的内核需要额外补丁)版本内核,而 VGPU-Community-Drivers 项目似乎支持更高版本的内核,但为了兼容性最好用小于5.10的内核。
本文使用的环境如下:
- Debian 11 (Bullseye) on Linux 5.10.0
- Intel Core i3-10100F
- NVIDIA GeForce GTX 1050 2G
下载和安装相关的工具和依赖
apt update && apt upgrade -y
apt install -y git build-essential dkms unzip python3-pip mdevctl jq -y
pip3 install frida --break-system-packages
vGPU-Unlock-patcher 是 vgpu_unlock 注入 nvidia 驱动的一个解决方案:
git clone https://github.com/VGPU-Community-Drivers/vGPU-Unlock-patcher.git -b 525.105 --recursive
vgpu_unlock-rs 是设置 vGPU 配置的工具:
git clone https://github.com/mbilker/vgpu_unlock-rs.git
开启 IOMMU
编辑 /etc/default/grub
,添加下面的参数开启 IOMMU :
# Intel 处理器写入以下内容
GRUB_CMDLINE_LINUX_DEFAULT="intel_iommu=on"
# AMD 处理器写入以下内容
GRUB_CMDLINE_LINUX_DEFAULT="amd_iommu=on"
然后使用 update-grub
更新系统引导并重启。
禁用开源驱动
在安装驱动之前需要禁用 nouveau 驱动,否则 vGPU 驱动将会报错无法安装:
echo "blacklist nouveau" >> /etc/modprobe.d/disable-nouveau.conf
echo "options nouveau modeset=0" >> /etc/modprobe.d/disable-nouveau.conf
使用 update-initramfs -u
更新 initrd 并重启以应用更改。
单N卡用户请注意:在禁用驱动后就无法进入桌面环境,请确保开启 SSH 服务器或者使用 Ctrl+Alt+F2~F6 进入 TTY
加载模块
向 /etc/modules
写入以下内容:
vfio
vfio_iommu_type1
vfio_pci
vfio_virqfd
安装Rust编译环境
因为 Debian 11 软件包源的 Rust 版本太老,直接编译 vgpu_unlock-rs 会报错,所以使用官方的安装方法:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
安装和配置
下载 vGPU-KVM 驱动
官方下载 vGPU 驱动的前提需要用一个非个人邮箱(可以使用自己的域名和未关闭25端口的vps自建邮箱服务端进行注册,亲测可用)注册 NVIDIA 企业账户,申请90天的 vGPU 体验通过后,才会提供 vGPU 宿主机和虚拟机的GRID驱动下载渠道和 vGPU 的使用许可。
此 Github 仓库有本文对应的 NVIDIA GRID 15.2(525.105) 驱动,下载 仓库已删,本人已上传部分版本vGPU驱动到此仓库,随缘更新Linux-KVM
后缀的驱动包。
解压下载下来的驱动包,将解压后的 Host_Drivers
文件夹里面的 NVIDIA-Linux-x86_64-525.105.14-vgpu-kvm.run
移动到 vGPU-Unlock-patcher
下。
下载消费级显卡驱动
由于计算卡本身也没有显示输出接口,因此用的 vGPU 驱动既不支持 DRM (图像输出),也不支持在宿主机上进行OpenGL/CUDA
之类的渲染运算,如果只有NVIDIA显卡的电脑直接安装 vGPU 驱动,将无法正常使用显卡。
针对这个问题,可以通过合并游戏显卡驱动来解决, vGPU-Unlock-patcher 的 patch.sh 脚本也有这个功能。
如果你并不需要上面的功能(比如当云计算/游戏虚拟机平台),可以跳过这个步骤。
wget https://download.nvidia.com/XFree86/Linux-x86_64/525.105.17/NVIDIA-Linux-x86_64-525.105.17.run
同上,将下载的文件移动到 vGPU-Unlock-patcher
下。
需要注意的是,如果使用合并后的驱动,宿主机的GPU本身也将会视为一个vGPU,对于我这个低显存的1050 2G就只能给虚拟机用一个vGPU,多分配会报IO错误,因此下面划分vGPU时就需要谨慎划分。
使用 vGPU-Unlock-patcher 脚本
首先进入 vGPU-Unlock-patcher
目录,输入以下命令:
./patch.sh general-merge
默认不支持 6.x 版本的内核,如果内核版本是 6.1~6.3 ,尝试以下选项
./patch.sh --lk6-patches general-merge
- 实测大多数 6.x 内核无法编译通过,不建议使用
等待命令执行完成,检查当前目录下是否出现 NVIDIA-Linux-x86_64-525.105.17-vgpu-kvm-merge-patched
目录,若有则进入这个目录并输入以下命令安装驱动:
./nvidia-installer --dkms
出现任何选项,选 yes 即可。
如果出现 Installation Error ,通常是 Linux 内核不兼容导致的,可以尝试降级内核或者更换内核。
如果是搭建云虚拟机平台,把上文中的 ./patch.sh general-merge
替换成 ./patch.sh vgpu-kvm
,且对应的文件夹应为 NVIDIA-Linux-x86_64-525.105.17-vgpu-kvm-patched
安装和配置 vgpu_unlock-rs
安装 vgpu_unlock-rs 后就可以通过修改配置文件来自定义默认的vGPU配置。(例如把限制45fps的B类vGPU改到60fps或更高)
进入到 vgpu_unlock-rs
目录后,输入下面命令:
cargo build --release
cp './target/release/libvgpu_unlock_rs.so' /usr/local/lib
为了让 NVIDIA 驱动使用 vgpu_unlock-rs ,这里修改 NVIDIA 驱动的 Systemd 服务文件:
mkdir /etc/systemd/system/nvidia-{vgpu-mgr,vgpud}.service.d
echo '[Service]
Environment=LD_PRELOAD=/usr/local/lib/libvgpu_unlock_rs.so' | tee /etc/systemd/system/nvidia-{vgpu-mgr,vgpud}.service.d/vgpu_unlock-rs.conf > /dev/null
将服务设置为开机运行:
systemctl enable nvidia-{vgpu-mgr,vgpud}.service
设置完成后重启,重启后输入 mdevctl types
,如果输出像下面这样,那么便配置成功了:
...
nvidia-283
Available instances: 0
Device API: vfio-pci
Name: GRID P40-4C
Description: num_heads=1, frl_config=60, framebuffer=4096M, max_resolution=4096x2160, max_instance=6
...
如果没有任何输出,尝试重启两个服务,然后再输入上面的命令。
systemctl restart nvidia-{vgpu-mgr,vgpud}.service
vGPU 类型
NVIDIA的vGPU是靠显存和功能来划分的,例如:
我的 GTX1050 只有 2GB 显存,而对应架构的 Tesla P40 的一个 vGPU 最少也需要 1GB 的显存,也就是说,我的 GTX1050 最多只能划分 1+1 也就是两个 vGPU 。
如果是 GTX1060 6GB ,则可以划分成 1+1+1+1+1+1 总共6个vGPU ,或者 2+2+2 总共3个vGPU ,或者 3+3 总共2个vGPU,但是不能像 1+2+3 这样划分。
更具体的vGPU信息可以在NVIDIA官网的GRID文档,与自己的显卡架构对应的计算卡vGPU支持列表里找到。
执行 mdevctl types
命令后的输出:
0000:01:00.0
nvidia-156
Available instances: 0
Device API: vfio-pci
Name: GRID P40-2B
Description: num_heads=4, frl_config=45, framebuffer=2048M, max_resolution=5120x2880, max_instance=12
nvidia-215
Available instances: 0
Device API: vfio-pci
Name: GRID P40-2B4
Description: num_heads=4, frl_config=45, framebuffer=2048M, max_resolution=5120x2880, max_instance=12
...
0000:01:00.0
是显卡的 PCI 物理地址
nvidia-156
是 vGPU 的类型名
Name: GRID P40-2B
是 nvidia-156
的 vGPU 的虚拟机显示的显卡名
其中, P40-2B 中的 2B 的 2 代表显存容量,这里表示显存为 2G ,而 2B 中的 B 表示的是vGPU功能类型,下面写出了各字母代表的vGPU功能:
vGPU类型 | 支持的操作系统 | 一般的使用场合 | 许可证 | 支持的显示参数 | 备注 |
A | Windows, Linux | Virtual Applications | vApps | 1280x1024,1 display | Good for RDSH |
B | Windows, Linux | Basic PC work | vPC | Up to 5K, 2 displays | 45 FPS max |
C | Linux | Compute server | vCS | Up to 4K, 1 display | CUDA Only |
Q | Windows, Linux | Professional Workstation | vDWS | Up to 8K, 4 displays | CUDA, OpenGL |
看不懂可以直接选Q,Q是专业工作站版本,功能最全。
- 目前已知Q类型vGPU的OpenGL性能非常糟糕,在跑OpenGL软件渲染时甚至会带动桌面一起卡顿,如果需要使用OpenGL可以使用A类型和B类型vGPU,通过修改
/etc/vgpu_unlock/profile_override.toml
配置文件替代Q类型vGPU,可以参考此项目的README。- 同时,A类型vGPU在Linux下不生效,它们只能在Windows上使用。
vGPU 创建
首先用 uuidgen
生成 UUID ,然后选择合适的 vGPU 类型,比如 nvidia-46
:
mdevctl start -u 451dcd1d-d464-49a3-b0c6-3cf2c7c1f8c4 -p 0000:01:00.0 --type nvidia-46
mdevctl define -a -u 451dcd1d-d464-49a3-b0c6-3cf2c7c1f8c4
注意:不要盲目复制粘贴!
创建 Libvirt 虚拟机和测试
安装和配置 Libvirt 虚拟机
安装 Qemu Libvirt 和 Virt-Manager :
apt install libvirt0 virt-manager qemu-system-x86 qemu-kvm qemu-utils libvirt-clients libvirt-daemon-system virtinst -y
设置 libvirt 开机自动启动
systemctl enable --now libvirtd
设置 Libvirt 虚拟机权限(将 $USER 替换为自己的用户名):
sudo usermod -a -G input $USER
sudo usermod -a -G kvm $USER
sudo usermod -a -G libvirt $USER
启动虚拟机 NAT 网络并设置自动启动
virsh net-start default
virsh net-autostart default
虚拟机添加 vGPU
在应用程序菜单里面找到虚拟系统管理器并打开,创建虚拟机最后一步时选择在安装前自定义配置,
左下角添加硬件,在弹出的左侧列表里找到 MDEV Host Device ,右边的主机设备就是你生成的 vGPU 设备。
安装 vGPU-GRID 驱动
在前面下载和解压 vGPU-KVM 显卡驱动步骤时,解压出来 Guset_Drivers
的文件夹里的后缀 .exe 文件就是 Windows 的 GRID 驱动。
.deb 和 .rpm 分别是 Debian 系和 Red Hat 系的 GRID 虚拟显卡驱动, .run 是通用的 Linux GRID 虚拟显卡驱动。
可以用下面的命令把文件夹里面的所有驱动打包成 GRID.iso 文件,在虚拟机里用光驱加载运行:
mkisofs -J -l -r -o GRID.iso Guest_Drivers/*
获取GRID驱动授权
前面说过,只有注册 NVIDIA 企业账号并申请90天 vGPU 试用,通过后才可以拿到 vGPU 的驱动和授权服务,否则 GRID 驱动只能用20分钟,超过20分钟后就会限制性能。
那怎么办呢?
Docker Hub 上有一个容器项目 collinwebdesigns/fastapi-dls ,可以伪装成 Nvidia GRID License Server 获取授权,不过需要一个OpenSSL证书,所以这里使用已经封好证书的容器,(此容器已非最新版本,不推荐使用)你也可以根据源码的README来自己创建一个证书。
Docker 安装与 fastapi-dls 部署
使用下面命令安装 docker :
apt install docker -y
首先,打开你的 Windows/Linux 虚拟机,查看虚拟机 NAT 网络的路由地址,我这边是 192.168.122.1,然后我要容器监听 1234 端口,那么docker容器的命令如下:
docker run --name dls -d -e DLS_URL=192.168.122.1 -e DLS_PORT=1234 -p 1234:443 makedie/fastapi-dls
DLS_URL 和 DLS_PORT 告诉 GRID 驱动访问哪个地址和端口获取授权,请确保没有填错。
使用下面的命令设置容器开机自动启动:
docker update --restart=always dls
让虚拟机的 GRID 驱动获取许可
在虚拟机内使用刚才设置的 DLS_URL 和 DLS_PORT 访问容器并下载 Token ,例如 https://192.168.122.1:1234/-/client-token
注意:地址要加上 HTTPS 前缀,否则无法访问
Windows 把下载的 token 文件放进虚拟机的 C:\Program Files\NVIDIA Corporation\vGPU Licensing\ClientConfigToken 文件夹内,然后重启 NvContainerLocalSystem 服务。
Linux 使用 curl --insecure -X GET https://192.168.122.1:1234/-/client-token -o /etc/nvidia/ClientConfigToken/client_configuration_token.tok
或者 wget https://192.168.122.1:1234/-/client-token -O /etc/nvidia/ClientConfigToken/client_configuration_token.tok --no-check-certificate
随后用 systemctl restart nvidia-gridd
重启服务
然后用 nvidia-smi -q
查看 License Status ,如果为 Licensed 则已成功获取许可。
结尾
虽然 vgpu_unlock 对绝大多数消费级显卡(包括超入门级的 GTX1050 和“亮机”级的 MX150/GT1030 )都提供了支持,但 NVIDIA vGPU 仍然有一些限制,例如:
- vGPU 无法输出画面,本地只能通过像 parsec 和 moonlight 之类的串流远程桌面软件才能完全正常使用即时渲染的应用(比如游戏和3D渲染软件)
- 也许是驱动兼容性问题,直通 vGPU 的Windows虚拟机无法开启Hyper-V虚拟化,但仍然可以使用VMware Workstation Pro和VirtualBox等虚拟化软件进行套娃
由于笔者没有条件测试,所以无法得知 vGPU 驱动和消费级 GPU 驱动合并的 merge 驱动对核显+独显的笔记本设备的兼容性。
实测笔记本(环境是ArchLinux 自编译内核,版本5.15-xanmod HD530核显+GTX1050Ti独显)对合并的GRID驱动兼容性良好,可以正常使用 Bumblebee 来切换显卡。
TIPS
- 建议全程挂代理
- 请尽量不要更新内核,建议将内核软件包设置为手动升级
Comments 1 条评论
博主 libvf
libvf.io直接解决了
你这何必那么折腾呢