Ubuntu 24.04 + KVM/QEMU + Libvirt + GPU Passthrough
KVM/QEMU:Linux 原生虚拟化引擎,性能接近裸机
libvirt + virt-manager:管理虚拟机
VFIO PCI Passthrough:实现每个 VM 独占 1 张 4090 显卡
🧱 宿主机前提条件检查(Ubuntu 24.04)
1. CPU 支持虚拟化 + IOMMU
lscpu | grep Virtualization
2. 开启 IOMMU(AMD-Vi)
编辑 /etc/default/grub: GRUB_CMDLINE_LINUX_DEFAULT="quiet amd_iommu=on iommu=pt"
sudo update-grub
sudo reboot
3. 检查 IOMMU 是否生效
dmesg | grep -i iommu 应包含:AMD-Vi: IOMMU enabled
🧰 安装虚拟化工具(KVM + Libvirt + Virt-Manager)
sudo apt update
sudo apt install -y qemu-kvm libvirt-daemon-system virt-manager bridge-utils ovmf
sudo systemctl enable libvirtd
sudo systemctl start libvirtd
验证是否支持 KVM:kvm-ok
🧠 查看并绑定 GPU 设备
1. 列出所有 GPU: lspci -nn | grep -i nvidia
输出类似:0b:00.0 VGA compatible controller [0300]: NVIDIA Corporation AD102 [GeForce RTX 4090] [10de:2684]
0b:00.1 Audio device [0403]: NVIDIA Corporation [10de:228b]
记录所有 GPU 的 [10de:2684] [10de:228b]
2. 使用 vfio-pci 绑定设备 根据自己的修改
编辑 /etc/modprobe.d/vfio.conf:options vfio-pci ids=10de:2684,10de:228b
禁用宿主机加载 NVIDIA 驱动:echo -e "blacklist nouveau\nblacklist nvidia\nblacklist nvidiafb\nblacklist rivafb" | sudo tee /etc/modprobe.d/blacklist-nvidia.conf
更新 initramfs:sudo update-initramfs -u
sudo reboot
🔁 重启后验证设备是否绑定 VFIO:lspci -nnk | grep -A 3 NVIDIA
应该显示:Kernel driver in use: vfio-pci
🧱 创建虚拟机并配置 GPU Passthrough
使用 virt-manager 创建虚拟机(GUI 工具)或命令行:
使用 GUI
1. 打开:virt-manager
2. 创建新虚拟机 → 使用 ISO 安装(Ubuntu/CentOS)
3. 分配:
• CPU 核心数(自行配置)
• 内存(自行配置)
• 磁盘(独立 qcow2 文件)
4. 在「添加硬件」中:
• 添加 GPU PCI 设备(选择你绑定的某一张 4090)
💡 QEMU 配置文件修改(高级)
VM 的配置文件位置:/etc/libvirt/qemu/<vm-name>.xml
在 <devices> 内添加 GPU 显卡 passthrough 设备:
<hostdev mode='subsystem' type='pci' managed='yes'>
<source>
<address domain='0x0000' bus='0x0b' slot='0x00' function='0x0'/>
</source>
</hostdev>
如果你也要直通 GPU 的音频子设备,则添加第二块:
<hostdev mode='subsystem' type='pci' managed='yes'>
<source>
<address domain='0x0000' bus='0x0b' slot='0x00' function='0x1'/>
</source>
</hostdev>
重载并启动虚拟机:
virsh define /etc/libvirt/qemu/<vm-name>.xml
virsh start <vm-name>
🎯 虚拟机内部部署 GPU 驱动 + CUDA
1. 登录 VM 后安装 NVIDIA 驱动
2. 确认 GPU 可用:nvidia-smi
如果要每台 VM 独立联网,可用 bridge-utils 配置桥接 vmbr0:
# /etc/netplan/01-netcfg.yaml 示例
network:
version: 2
renderer: networkd
ethernets:
eno1:
dhcp4: no
bridges:
br0:
interfaces: [eno1]
dhcp4: yes
然后用 virsh 或 virt-manager 把虚拟机网络绑定到 br0。
gpu-vm-setup/
├── 00-init-dependencies.sh # 安装依赖并启用 KVM + VFIO
├── 01-bind-gpus-vfio.sh # 识别并绑定 8 张 4090 到 vfio-pci
├── 02-create-vm-template.sh # 创建 base 虚拟机模板(带 GPU 驱动)
├── 03-create-vms.sh # 从模板批量创建 8 个 GPU VM
├── ubuntu-22.04.iso # 虚拟机系统镜像(或 cloud-init)
└── vm-disk/ # 每个 VM 的磁盘存储目录
#00-init-dependencies.sh
#!/bin/bash
set -e
echo "[*] 安装 KVM/Libvirt 等虚拟化工具..."
sudo apt update
sudo apt install -y qemu-kvm libvirt-daemon-system virt-manager bridge-utils ovmf
echo "[*] 启用 IOMMU 支持..."
sudo sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="/GRUB_CMDLINE_LINUX_DEFAULT="amd_iommu=on iommu=pt /' /etc/default/grub
sudo update-grub
echo "[*] 加载 VFIO 模块..."
cat <<EOF | sudo tee /etc/modules-load.d/vfio.conf
vfio
vfio_iommu_type1
vfio_pci
vfio_virqfd
EOF
echo "[*] 黑名单 NVIDIA 驱动..."
cat <<EOF | sudo tee /etc/modprobe.d/blacklist-nvidia.conf
blacklist nouveau
blacklist nvidia
blacklist nvidiafb
blacklist rivafb
EOF
echo "[*] 设置完成,请重启后执行下一步:01-bind-gpus-vfio.sh"
📜 01-bind-gpus-vfio.sh
#!/bin/bash
set -e
echo "[*] 识别所有 RTX 4090 设备..."
lspci -nn | grep -i 'NVIDIA.*4090' > /tmp/gpu.list
DEVICE_IDS=$(lspci -nn | grep -i 'NVIDIA.*4090' | awk -F '[' '{print $3}' | cut -d ']' -f1 | sort -u | paste -sd,)
echo "[*] 绑定 GPU IDs 到 vfio-pci: $DEVICE_IDS"
echo "options vfio-pci ids=$DEVICE_IDS" | sudo tee /etc/modprobe.d/vfio-pci.conf
echo "[*] 更新 initramfs..."
sudo update-initramfs -u
echo "[*] 完成绑定。请重启并验证 lspci 是否显示 vfio-pci 绑定。"
📜 02-create-vm-template.sh
手动安装一台虚拟机(例如 Ubuntu 22.04),安装 NVIDIA 驱动和 CUDA 工具链。然后使用如下命令导出模板:
#!/bin/bash
# 手动安装完成 base-4090-vm 后执行
virsh shutdown base-4090-vm
sleep 10
virsh snapshot-create-as --domain base-4090-vm --name clean --description "Clean base image"
📜 03-create-vms.sh(批量创建)
#!/bin/bash
set -e
VM_PREFIX="gpuvm"
BASE_DISK="/var/lib/libvirt/images/base-4090.qcow2"
BRIDGE_IF="br0"
# GPU PCI地址列表(需提前根据 lspci 获取)
GPU_IDS=(
"0000:0b:00.0" # GPU 0
"0000:13:00.0" # GPU 1
"0000:1b:00.0" # ...
"0000:23:00.0"
"0000:2b:00.0"
"0000:33:00.0"
"0000:3b:00.0"
"0000:43:00.0"
)
for i in $(seq 0 7); do
VM_NAME="${VM_PREFIX}${i}"
VM_DISK="/var/lib/libvirt/images/${VM_NAME}.qcow2"
echo "[*] 创建磁盘镜像: $VM_DISK"
cp "$BASE_DISK" "$VM_DISK"
echo "[*] 定义虚拟机: $VM_NAME"
virt-install \
--name "$VM_NAME" \
--ram 65536 \
--vcpus 12 \
--cpu host \
--os-variant ubuntu22.04 \
--hvm \
--virt-type kvm \
--graphics none \
--disk path="$VM_DISK",format=qcow2 \
--network bridge=$BRIDGE_IF,model=virtio \
--import \
--noautoconsole \
--boot uefi \
--host-device ${GPU_IDS[$i]}
done