KVM 和 QEMU 关系及显卡直通
KVM
KVM (Kernel-based Virtual Machine, 即内核级虚拟机) 是一个开源的系统虚拟化模块, 基于 Linux 内核的调度器进行管理, 相对于 Xen, 它的核心代码较少。KVM 已成为学术界主流的虚拟机监控器 (VMM) 之一。KVM 包含一个为处理器提供底层虚拟化支持的可加载核心模块 kvm.ko
(Intel 使用 kvm-intel.ko
, AMD 使用 kvm-amd.ko
)。此外, KVM 还需要一个修改过的 QEMU 软件 (qemu-kvm
) 来提供虚拟机的上层控制和界面。
KVM 的虚拟化要求硬件支持, 如 Intel 的 VT 技术或 AMD 的 SVM 技术, 因此它是基于硬件的完全虚拟化方案。KVM 允许在多个虚拟机中运行与主机系统相同的镜像, 例如 Windows 和 macOS, 每个虚拟机都会拥有独立的虚拟硬件资源, 如网卡、硬盘和图形适配器等。
KVM 和 QEMU 的关系
QEMU 是一个独立的虚拟化解决方案, 从某种角度来说, 它并不依赖 KVM。而 KVM 是另一套虚拟化解决方案, 实际上它仅提供对处理器 (如 Intel VT 或 AMD SVM) 的虚拟化特性支持。KVM 本身不包含设备虚拟化及用户空间的虚拟机管理工具, 因此它借用了 QEMU 的代码, 并与 KVM 配合使用, 形成了完整的虚拟化解决方案: KVM + QEMU
通过 VFIO、KVM 和 QEMU 实现 GPU 直通
我一直希望使用 CentOS 7 作为主要的操作系统, 但又想使用 Nvidia 显卡玩游戏, 就需要一个 Windows 系统。
可以通过 VFIO (Virtual Function I/O) 、KVM 和 QEMU 这三种开源技术实现 GPU 的直通。这种方法可以让虚拟机使用主机上的显卡, 从而达到接近原生性能的效果。具体来说, 通过 VFIO 技术, 能够将物理显卡从主机系统中 “直通” 给虚拟机, 使得虚拟机能够直接访问该显卡, 运行图形密集型应用或游戏。
准备工作
硬件
- CPU Intel i7-8700K 需要支持 VT-d (Intel Virtualization Technology for Directed I/O) 以及VT-x
- 内存 40G RAM (目前是 8G + 48G)
- 显卡 ASUS ROG-STRIX-RTX2080TI-O11G-GAMING 虚拟机使用 (显卡需要 UEFI 支持) 新显卡都支持, 可以在 这里查询
- 主板 ASUS Strix Z370-F
软件
- CentOS 7.6
- KVM 套件
- qemu-kvm 需要 2.9.0 以上版本
- Windows 10 1809 版本 (RTX 显卡需要最新的 win 10)
软件配置
- 从内核中禁用 nouveau 驱动
- PCI 直通 (VFIO/IOMMU)
- KVM 网桥
qemu-kvm: could not open disk image ' ': Permission denied
权限问题- 虚拟机 CPU 分配 (虚拟物理核心和虚拟线程的设置)
- 下载 VFIO 驱动程序
- 虚拟机中 N 卡驱动 43 错误代码 (N 卡检测到在虚拟机中运行会出现这个错误)
- 添加物理磁盘到虚拟机
配置流程
- 检查硬件是否满足要求
- 准备系统环境 安装 KVM 套件
- 检查是否正确加载 kvm 模块
- 禁用 nouveau 驱动
- 开启 IOMMU 支持
- 设置 vfio-pci 设备 (IOMMU)
- 设置网桥
- 更新 qemu-kvm 到 2.9.0 以上版本
- 分配虚拟机磁盘
- 配置 qemu-kvm 权限
- 安装虚拟机
- 设置虚拟机 CPU 核心
- 分配鼠标键盘给虚拟机
- 虚拟机 win VFIO 驱动程序安装
- 给虚拟机添加显卡
- 解决显卡 43 错误代码
- 给虚拟机添加物理磁盘
1. 检查硬件是否满足要求
验证 CPU 是否支持 KVM
如果结果中有 vmx
(Intel VT 虚拟化技术) 或 svm
(SVM 安全虚拟化技术的 AMD 处理器, 也可以叫 AMD-V) 字样, 就说明 CPU 的支持的。如果没配置过可以在 BIOS 中启用。如果还没有任何的输出, 说明你的 cpu 不支持, 将无法使用 KVM 虚拟机。
egrep '(vmx|svm)' /proc/cpuinfo
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm arat epb pln pts dtherm tpr_shadow vnmi flexpriority ept vpid fsgsbase smep erms xsaveopt
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm arat epb pln pts dtherm tpr_shadow vnmi flexpriority ept vpid fsgsbase smep erms xsaveopt
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm arat epb pln pts dtherm tpr_shadow vnmi flexpriority ept vpid fsgsbase smep erms xsaveopt
2. 准备系统环境 安装 KVM 套件
安装基础工具
yum install net-tools vim wget kernel-devel epel-release
yum update
yum install htop
安装 KVM 套件
yum install virt-manager qemu-img qemu-kvm qemu-kvm-tools libvirt virt-install bridge-utils
添加 virtio-win 源并安装 virtio-win
wget https://fedorapeople.org/groups/virt/virtio-win/virtio-win.repo -O /etc/yum.repos.d/virtio-win.repo
yum install virtio-win
kvm 相关安装包及其作用
qemu-kvm 主要的 KVM 程序包
python-virtinst 创建虚拟机所需要的命令行工具和程序库
virt-manager GUI 虚拟机管理工具
virt-top 虚拟机统计命令
virt-viewer GUI 连接程序, 连接到已配置好的虚拟机
libvirt C 语言工具包, 提供 libvirt 服务
libvirt-client 虚拟客户机提供的 C 语言工具包
virt-install 基于 libvirt 服务的虚拟机创建命令
bridge-utils 创建和管理桥接设备的工具
3. 检查是否正确加载 kvm 模块
一共会输出三条, 三条都必须满足
[root@corehadoop31 ~]# lsmod |grep kvm
kvm_intel 170181 3
kvm 554609 1 kvm_intel
irqbypass 13503 1 kvm
4. 禁用 nouveau 驱动
CentOS 7 文件路径在 /usr/lib/modprobe.d/dist-blacklist.conf
和 /lib/modprobe.d/dist-blacklist.conf
是同一个文件, 修改其中一个即可。
其他路径如 /etc/modprobe.d/blacklist.conf
也可以使用, 下面是禁用相关驱动的命令
echo "blacklist radeon" >> /etc/modprobe.d/blacklist.conf
echo "blacklist nouveau" >> /etc/modprobe.d/blacklist.conf
echo "blacklist nvidia" >> /etc/modprobe.d/blacklist.conf
本段文章教程 两篇文章结合使用
centos 7禁用nouveau及安装NVIDIA显卡驱动
CentOS中禁用nouveau驱动
在配置文件中禁用 nouveau
编辑文件禁用 nouveau
vim /usr/lib/modprobe.d/dist-blacklist.conf
在文件最后添加以下内容
blacklist nouveau
options nouveau modeset=0
备份并重建 initramfs 镜像
# 备份镜像
mv /boot/initramfs-$(uname -r).img /boot/initramfs-$(uname -r).img.bak
# 重建镜像
dracut -v /boot/initramfs-$(uname -r).img $(uname -r)
重启并检查是否禁用成功
reboot
# 重启之后检查是否禁用成功, 应该返回空
lsmod | grep nouveau
扩展阅读
禁用 Nvidia 的 libGL 驱动。Using integrated graphics card for display and Nvidia card for GPU
注释掉 /etc/ld.so.conf.d/nvidia.conf
文件中的内容
# /etc/ld.so.conf.d/nvidia.conf provided by http://elrepo.org
/usr/lib64/nvidia
/usr/lib64/vdpau
/usr/lib/nvidia
/usr/lib/vdpau
5. 开启 IOMMU 支持
CentOS7 minimal kvm iommu 辅助虚拟化 vt-x (用于pci透传)
根据 CPU 类型, 启用 IOMMU 支持:
- Intel CPU:
intel_iommu=on
- AMD CPU:
amd_iommu=on
方法一
我用方法一失败了, 很多文章都是方法一
编辑 GRUB 配置文件
vim /etc/default/grub
将 GRUB_CMDLINE_LINUX_DEFAULT
或 GRUB_CMDLINE_LINUX
中添加 intel_iommu=on
GRUB_CMDLINE_LINUX_DEFAULT="... intel_iommu=on ..."
或
GRUB_CMDLINE_LINUX="... intel_iommu=on ..."
更新 GRUB 配置
grub2-mkconfig -o /boot/grub2/grub.cfg
重启系统
reboot
验证是否成功启用 IOMMU
cat /proc/cmdline | grep intel_iommu=on
查看系统日志, 确认 IOMMU 是否启用
dmesg | grep -E "DMAR|IOMMU"
如果方法一 失败, 应该是启动的时候并没有使用 /boot/grub2/grub.cfg
, 可以用方法二
方法二
查找 grub.cfg 文件
find / -name "grub.cfg"
发现还有 /boot/efi/EFI/centos/grub.cfg
这个文件, 继续执行以下操作。
编辑该 grub.cfg 文件
vim /boot/efi/EFI/centos/grub.cfg
对照 /boot/grub2/grub.cfg
把 intel_iommu=on
添加到相应位置
文件里 linuxefi
出现了 3 次, 在每个 linuxefi
行添加 intel_iommu=on
, 然后保存退出
重启系统并验证配置是否生效
6. 设置 vfio-pci 设备 (IOMMU)
配置 VFIO-PCI
查找设备的 PCI 信息
lspci -nn | grep -i nvidia
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation TU102 [GeForce RTX 2080 Ti Rev. A] [10de:1e07] (rev a1)
01:00.1 Audio device [0403]: NVIDIA Corporation Device [10de:10f7] (rev a1)
01:00.2 USB controller [0c03]: NVIDIA Corporation Device [10de:1ad6] (rev a1)
01:00.3 Serial bus controller [0c80]: NVIDIA Corporation Device [10de:1ad7] (rev a1)
配置 VFIO 设备
编辑 vim /etc/modprobe.d/vfio.conf
文件, 添加以下内容 (根据你的设备的 vendor-ID 和 device-ID)
# create new: for [ids=***], specify [vendor-ID:device-ID] 没有 ACS 的需要把整组都放入
options vfio-pci ids=10de:1e07,10de:10f7,10de:1ad6,10de:1ad7
创建配置文件以加载 VFIO 模块
echo 'vfio-pci' > /etc/modules-load.d/vfio-pci.conf
重启系统
reboot
验证 VFIO 是否成功加载
使用 dmesg
查看日志, 确认 VFIO 设备是否已加载
dmesg | grep -i vfio
>># dmesg | grep -i vfio
[ 1.423654] VFIO - User Level meta-driver version: 0.3
[ 1.435816] vfio_pci: add [10de:1e07[ffff:ffff]] class 0x000000/00000000
[ 1.447858] vfio_pci: add [10de:10f7[ffff:ffff]] class 0x000000/00000000
扩展阅读!!! 注意事项
Pci passthrough #Verify IOMMU isolation
验证 IOMMU 是否正确隔离
要让 PCI passthrough 正常工作, 确保每个 PCI 设备都在独立的 IOMMU 组内。使用以下命令查看 IOMMU 组信息
find /sys/kernel/iommu_groups/ -type l
/sys/kernel/iommu_groups/0/devices/0000:00:00.0
/sys/kernel/iommu_groups/1/devices/0000:00:01.0
/sys/kernel/iommu_groups/1/devices/0000:01:00.0
/sys/kernel/iommu_groups/1/devices/0000:01:00.1
/sys/kernel/iommu_groups/2/devices/0000:00:02.0
/sys/kernel/iommu_groups/3/devices/0000:00:16.0
/sys/kernel/iommu_groups/4/devices/0000:00:1a.0
/sys/kernel/iommu_groups/5/devices/0000:00:1b.0
/sys/kernel/iommu_groups/6/devices/0000:00:1c.0
/sys/kernel/iommu_groups/7/devices/0000:00:1c.5
/sys/kernel/iommu_groups/8/devices/0000:00:1c.6
/sys/kernel/iommu_groups/9/devices/0000:00:1c.7
/sys/kernel/iommu_groups/9/devices/0000:05:00.0
/sys/kernel/iommu_groups/10/devices/0000:00:1d.0
/sys/kernel/iommu_groups/11/devices/0000:00:1f.0
/sys/kernel/iommu_groups/11/devices/0000:00:1f.2
/sys/kernel/iommu_groups/11/devices/0000:00:1f.3
/sys/kernel/iommu_groups/12/devices/0000:02:00.0
/sys/kernel/iommu_groups/12/devices/0000:02:00.1
/sys/kernel/iommu_groups/13/devices/0000:03:00.0
/sys/kernel/iommu_groups/14/devices/0000:04:00.0
IOMMU 支持 ACS
要确保 PCI 设备能正常进行 passthrough, 每个设备需要提供专用的 IOMMU 组。为此, 你的处理器必须支持 ACS (Access Control Services)
支持 ACS 的处理器 (Xeon、Core 系列)
- Intel Xeon 处理器 (E3、E5 系列) 大多支持 ACS, 但某些型号 (如 Xeon E3-1200) 不支持。
- Intel Core 处理器: 只有一些型号支持 ACS, 常见的支持型号包括
Haswell-E (LGA2011-v3)
i7-5960X (8-core, 3/3.5GHz)
i7-5930K (6-core, 3.2/3.8GHz)
i7-5820K (6-core, 3.3/3.6GHz)
Ivy Bridge-E (LGA2011)
i7-4960X (6-core, 3.6/4GHz)
i7-4930K (6-core, 3.4/3.6GHz)
i7-4820K (4-core, 3.7/3.9GHz)
Sandy Bridge-E (LGA2011)
i7-3960X (6-core, 3.3/3.9GHz)
i7-3970X (6-core, 3.5/4GHz)
i7-3930K (6-core, 3.2/3.8GHz)
i7-3820 (4-core, 3.6/3.8GHz)
7. 设置网桥
Bridge 模式配置
Bridge 模式即虚拟网桥, 允许虚拟机与宿主机和网络中的其他设备进行通信, 使虚拟机获得独立的 IP 地址。
桥接网络 (也叫物理设备共享) 被用作把一个物理设备复制到一台虚拟机。网桥多用作高级设置, 特别是主机多个网络接口的情况。
┌─────────────────────────┐ ┌─────────────────┐
│ HOST │ │Virtual Machine 1│
│ ┌──────┐ ┌───────┐ │ │ ┌──────┐ │
│ │ br0 │──┬───│ vnet0 │─│─ ─ ─ │ │ br0 │ │
│ └──────┘ │ └───────┘ │ │ └──────┘ │
│ │ │ │ └─────────────────┘
│ │ │ ┌───────┐ │ ┌─────────────────┐
│ ┌──────┐ └───│ vnet1 │─│─ │Virtual Machine 2│
│ │ eno0 │ └───────┘ │ │ │ ┌──────┐ │
│ └──────┘ │ ─ ─ │ │ br0 │ │
│ ┌──────┐ │ │ └──────┘ │
│ │ eno1 │ │ └─────────────────┘
│ └──────┘ │
└─────────────────────────┘
修改网卡配置文件
修改前一定要备份!!!
你需要修改宿主机的物理网卡配置文件, 通常位于 /etc/sysconfig/network-scripts/
目录下, 如 ifcfg-eno1
宿主机的物理网卡配置文件
# cat ifcfg-eno1
TYPE="Ethernet"
PROXY_METHOD="none"
BROWSER_ONLY="no"
BOOTPROTO="dhcp"
DEFROUTE="yes"
IPV4_FAILURE_FATAL="no"
IPV6INIT="yes"
IPV6_AUTOCONF="yes"
IPV6_DEFROUTE="yes"
IPV6_FAILURE_FATAL="no"
IPV6_ADDR_GEN_MODE="stable-privacy"
NAME="eno1"
UUID="242b3d4d-37a5-4f46-b072-55554c185ecf"
DEVICE="eno1"
ONBOOT="yes"
ZONE=nas
BRIDGE="br0" # 指定桥接网卡的名称
配置桥接网卡
在同一目录下创建或修改桥接网卡配置文件 ifcfg-br0
。确保配置宿主机的 IP 和路由器的网关
# cat ifcfg-br0
BOOTPROTO=static
DEFROUTE=yes
PEERDNS=yes
PEERROUTES=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_PEERDNS=yes
IPV6_PEERROUTES=yes
IPV6_FAILURE_FATAL=no
NAME=br0
UUID=242b3d4d-37a5-4f46-b072-55554c185ecf
DEVICE=br0
ONBOOT=yes
IPV6_PRIVACY=rfc3041
TYPE=bridge # 将制定为桥接类型
IPADDR=192.168.188.133 # 设置IP地址
PREFIX=24 # 设置子网掩码
GATEWAY=192.168.188.1 # 设置网关
激活网卡和桥接网卡
使用 ifup
激活网卡
ifup eno1 # 激活物理网卡
ifup br0 # 激活桥接网卡
重启网络服务
两种重启网络的方法
systemctl restart network.service
service network restart
检查网桥配置
使用 brctl show
命令检查网桥设置
brctl show
bridge name bridge id STP enabled interfaces
br0 8000.3863bb44cf6c no vnet0
virbr0 8000.525400193f0f yes virbr0-nic
8. 更新 qemu-kvm 到 2.9.0 以上版本
Update QEMU: CentOS 7 : KVM : GPU Passthrough : Server World
查看当前 QEMU 版本
[root@dlp ~]# /usr/libexec/qemu-kvm -version
QEMU emulator version 1.5.3 (qemu-kvm-1.5.3-141.el7_4.6), Copyright (c) 2003-2008 Fabrice Bellard
安装 QEMU EV 版本
[root@dlp ~]# yum -y install centos-release-qemu-ev
禁用默认的 QEMU 仓库
# disable usually
[root@dlp ~]# sed -i -e "s/enabled=1/enabled=0/g" /etc/yum.repos.d/CentOS-QEMU-EV.repo
安装 qemu-kvm-ev 包
# for this installing, [qemu-kvm] package is replaced to [qemu-kvm-ev] package
[root@dlp ~]# yum --enablerepo=centos-qemu-ev -y install qemu-kvm-ev
重启 libvirtd 服务
[root@dlp ~]# systemctl restart libvirtd
确认 QEMU 版本更新成功
[root@dlp ~]# /usr/libexec/qemu-kvm -version
QEMU emulator version 2.9.0(qemu-kvm-ev-2.9.0-16.el7_4.13.1)
Copyright (c) 2003-2017 Fabrice Bellard and the QEMU Project developers
验证支持的机器列表
查看是否包含 q35
# verify q35 is included like follows
[root@dlp ~]# /usr/libexec/qemu-kvm -machine help
Supported machines are:
pc RHEL 7.4.0 PC (i440FX + PIIX, 1996) (alias of pc-i440fx-rhel7.4.0)
pc-i440fx-rhel7.4.0 RHEL 7.4.0 PC (i440FX + PIIX, 1996) (default)
pc-i440fx-rhel7.3.0 RHEL 7.3.0 PC (i440FX + PIIX, 1996)
pc-i440fx-rhel7.2.0 RHEL 7.2.0 PC (i440FX + PIIX, 1996)
pc-i440fx-rhel7.1.0 RHEL 7.1.0 PC (i440FX + PIIX, 1996)
pc-i440fx-rhel7.0.0 RHEL 7.0.0 PC (i440FX + PIIX, 1996)
rhel6.6.0 RHEL 6.6.0 PC
rhel6.5.0 RHEL 6.5.0 PC
rhel6.4.0 RHEL 6.4.0 PC
rhel6.3.0 RHEL 6.3.0 PC
rhel6.2.0 RHEL 6.2.0 PC
rhel6.1.0 RHEL 6.1.0 PC
rhel6.0.0 RHEL 6.0.0 PC
q35 RHEL-7.4.0 PC (Q35 + ICH9, 2009) (alias of pc-q35-rhel7.4.0)
pc-q35-rhel7.4.0 RHEL-7.4.0 PC (Q35 + ICH9, 2009)
pc-q35-rhel7.3.0 RHEL-7.3.0 PC (Q35 + ICH9, 2009)
none empty machine
9. 分配虚拟机磁盘
创建虚拟磁盘
指定磁盘格式为 raw
, 50G 为虚拟大小, 并不实际占用物理空间。
qemu-img create -f raw /root/kvm/win10.raw 50G
查看磁盘信息
qemu-img info /root/kvm/win10.raw
image: /root/kvm/win10.raw
file format: raw
virtual size: 50G (53687091200 bytes)
disk size: 0
virtual size
是虚拟磁盘的总大小disk size
表示实际已占用的空间
10. 配置 qemu-kvm 权限
在使用 QEMU-KVM 时, 可能会遇到 qemu-kvm: could not open disk image ' ': Permission denied
的错误。由于 libvirtd 对权限管理较严格, 可以通过以下两种方法解决此问题。
qemu-kvm: could not open disk image ’ ‘: Permission denied
方法一: 修改 QEMU 配置文件
我使用方法一, 但不推荐
注意: 这种方法可能会带来安全隐患, 不推荐用于生产环境。
编辑 /etc/libvirt/qemu.conf
文件, 将 user
和 group
设置为 root
用户
# The user for QEMU processes run by the system instance. It can be
# specified as a user name or as a user id. The qemu driver will try to
# parse this value first as a name and then, if the name doesn't exist,
# as a user id.
#
# Since a sequence of digits is a valid user name, a leading plus sign
# can be used to ensure that a user id will not be interpreted as a user
# name.
#
# Some examples of valid values are:
#
# user = "qemu" # A user named "qemu"
# user = "+0" # Super user (uid=0)
# user = "100" # A user named "100" or a user with uid=100
#
user = "root"
# The group for QEMU processes run by the system instance. It can be
# specified in a similar way to user.
group = "root"
# Whether libvirt should dynamically change file ownership
# to match the configured user/group above. Defaults to 1.
# Set to 0 to disable file ownership changes.
#dynamic_ownership = 1
重启 libvirtd
服务
[root@dev1 ~]# service libvirtd restart
Stopping libvirtd daemon: [ OK ]
Starting libvirtd daemon: [ OK ]
方法二: 设置 ACL 权限
使用 getfacl
检查文件夹当前的 ACL 权限
murlock@asus:~/kubernet $ sudo getfacl -e /home/murlock
getfacl: Removing leading '/' from absolute path names
# file: home/murlock
# owner: murlock
# group: murlock
user::rwx
user:libvirt-qemu:--x # effective:---
group::--- # effective:---
mask::---
other::---
为 libvirt-qemu
用户添加执行权限
murlock@asus:~/kubernet $ sudo setfacl -m u:libvirt-qemu:rx /home/murlock
验证权限设置是否生效
应看到类似以下内容 user:libvirt-qemu:r-x
murlock@asus:~/kubernet $ sudo getfacl -e /home/murlock
getfacl: Removing leading '/' from absolute path names
# file: home/murlock
# owner: murlock
# group: murlock
user::rwx
user:libvirt-qemu:r-x # effective:r-x
group::--- # effective:---
mask::r-x
other::---
11. 安装虚拟机
虚拟机先创建一个可以正常运行的之后再为它添加 PCI 直通设备
特别需要注意的参数 --machine q35
和 --features kvm_hidden=on
, 这有助于更好地支持 PCI 直通。
virt-install \
--name Win10 \
--memory 16384 \
--cpu host \
--vcpus 8 \
--disk path=/root/kvm/win10.raw \
--network bridge=br0,model='e1000' \
--cdrom=/root/kvm/win10.iso \
--boot cdrom \
--virt-type kvm \
--vnc \
--vncport=5902 \
--vnclisten=0.0.0.0 \
--os-type=windows \
--features kvm_hidden=on \
--machine q35
参数含义
--name Win10
: 虚拟机名称为Win10
--memory 16384
: 分配 16 GB 内存--cpu host
: 使用宿主机的 CPU 配置--vcpus 8
: 分配 8 个虚拟 CPU (八路)--disk path=/root/kvm/win10.raw
: 指定虚拟机磁盘文件--network bridge=br0,model='e1000'
: 网络桥接方式,br0
为桥接网络接口--cdrom=/root/kvm/win10.iso
: 指定安装光盘镜像 (Windows 10 安装 ISO)--boot cdrom
: 启动虚拟机时从光盘启动--virt-type kvm
: 使用 KVM 虚拟化--vnc
: 启用 VNC 连接--vncport=5902
: 指定 VNC 端口为 5902--vnclisten=0.0.0.0
: 允许任何主机连接 VNC--os-type=windows
: 操作系统类型为 Windows--features kvm_hidden=on
: 隐藏 KVM 特征, 防止被虚拟机探测--machine q35
: 使用q35
架构来更好支持 PCI 直通
临时开放 VNC 端口
临时开放 VNC 端口 5902, 以便通过 VNC 客户端连接虚拟机
firewall-cmd --add-port=5902/tcp
安装操作系统
创建虚拟机后, 可以通过 VNC 客户端 (例如 VNC Viewer) 连接到 192.168.x.xxx:5902
来开始安装 Windows 10
virsh 基础命令
virsh list --all # 查看所有运行和没有运行的虚拟机
virsh list # 查看在运行的虚拟机
virsh dumpxml vm-name # 查看kvm虚拟机配置文件
virsh start vm-name # 启动kvm虚拟机
virsh shutdown vm-name # 正常关机
virsh destroy vm-name # 非正常关机, 强制关闭虚拟机 (相当于物理机直接拔掉电源)
virsh undefine vm-name # 删除vm的配置文件
ls /etc/libvirt/qemu
# 查看删除结果, Centos-6.6的配置文件被删除, 但磁盘文件不会被删除
virsh define file-name.xml # 根据配置文件定义虚拟机
virsh suspend vm-name # 挂起, 终止
virsh resumed vm-name # 恢复被挂起的虚拟机
virsh autostart vm-name # 开机自启动vm
virsh console <虚拟机名称> # 连接虚拟机
virsh start centos72 # 虚拟机开启 (启动)
virsh reboot centos72 # 虚拟机重新启动
virsh shutdown centos72 # 虚拟机关机
virsh destroy centos72 # 强制关机 (强制断电)
virsh suspend centos72 # 暂停 (挂起) KVM 虚拟机
virsh resume centos72 # 恢复被挂起的 KVM 虚拟机
virsh undefine centos72 # 该方法只删除配置文件, 磁盘文件未删除
virsh autostart centos72 # 随物理机启动而启动 (开机启动)
virsh autostart --disable centos72 # 取消标记为自动开始 (取消开机启动)
12. 设置虚拟机 CPU 核心
Why does my Windows 7 VM running under Linux’ KVM not use all the virtual processors?
在使用 KVM 创建虚拟机时, 默认的 CPU 核心配置可能不完全满足需求, 特别是对于多核虚拟机。
KVM 默认将 vcpus
设置为多路单核单线程的方式, 上一个步骤的 --vcpus 8
含义为分配 8 个虚拟 CPU (8 个处理器, 每个处理器单核单线程), 但我们预期的是单路四核心双线程或者是单路八核心单线程
而普通版本系统最多支持双路 CPU 的配置, 多于的 CPU 识别不出来。就算识别出来了, 在多任务调度上 8 个处理器也没有 8 核心的效率高
修改 CPU 拓扑结构, 设置为单路处理器 8 核心单线程, 这样可以解决问题
查看主机的 CPU 拓扑结构
在 libvirt 0.8.3 以上, 通过 virsh capabilities
命令, 可以查看主机 CPU 拓扑结构。
virsh capabilities | grep topology
这将列出主机的 CPU 核心和线程拓扑。例如
<topology sockets='1' cores='8' threads='1'/>
这些数字指的是处理器数 (sockets)、每个处理器核心数 (cores) 和每核心线程数 (threads)。
修改虚拟机的 CPU 配置
要让虚拟机使用更多的 CPU 核心和线程, 可以修改虚拟机的 XML 配置文件。以下是如何修改虚拟机 CPU 配置的方法。
打开虚拟机的 XML 文件, 路径为 /etc/libvirt/qemu/
下的虚拟机配置文件 (例如: Win10.xml
), 修改 vcpu
和 cpu
部分。
<vcpu placement='static'>8</vcpu>
<cpu mode='host-model' check='partial'>
<model fallback='allow'/>
<topology sockets='1' cores='8' threads='1'/>
</cpu>
vcpu
: 设置虚拟 CPU 数量为 8topology sockets='1' cores='8' threads='1'
: 设置虚拟机使用 1 个处理器, 每个处理器有 8 个核心, 且每个核心为单线程
直通模式
我使用此方法
如果你需要使用 CPU 直通模式, 可以配置为
<cpu mode='host-passthrough'>
<topology sockets='1' cores='4' threads='2'/>
<feature policy='disable' name='hypervisor'/>
</cpu>
应用配置
修改完 XML 文件后, 使用以下命令重新定义虚拟机配置
virsh define Win10.xml
这会使新的 CPU 配置生效
13. 分配鼠标键盘给虚拟机
Adding USB Device Pass-through
在 KVM 中, 可以通过 USB 设备直通 (USB pass-through) 将鼠标、键盘等设备分配给虚拟机。此操作通常需要使用 USB 2.0 或更低版本的协议。
获取设备的供应商 ID 和产品 ID
首先, 使用 lsusb
命令列出所有的 USB 设备, 并找到鼠标和键盘对应的供应商 ID 和产品 ID。例如
$ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 005 Device 012: ID 0a5c:2110 Broadcom Corp. Bluetooth Controller
Bus 005 Device 003: ID 0483:2016 SGS Thomson Microelectronics Fingerprint Reader
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
如果想要选择 Broadcom 公司提供的蓝牙控制器, 供应商 ID 为 0a5c
, 产品 ID 为 2110
添加 USB 设备直通
有两种方式可以将 USB 设备添加到虚拟机中: 动态添加 (Hot Add) 和 静态添加 (Static Add)
动态添加
首先, 创建一个只包含设备信息的 XML 文件, 内容如下
<hostdev mode='subsystem' type='usb' managed='yes'>
<source>
<vendor id='0x0a5c'/>
<product id='0x2110'/>
</source>
</hostdev>
然后, 通过 virsh
命令动态添加设备到虚拟机中
virsh attach-device <guestname> <our-device-xml-file>
要分离设备, 可以使用以下命令
# work with it in the guest
virsh detach-device <guestname> <our-device-xml-file>
静态添加
将设备信息直接写入虚拟机的 XML 配置文件中。打开虚拟机的 XML 文件 (例如: Win10.xml
), 并在 <devices>
部分中添加 USB 设备
<domain type='kvm'>
<name>Win10</name>
...
<devices>
...
<hostdev mode='subsystem' type='usb' managed='yes'>
<source>
<vendor id='0x046d'/>
<product id='0xc534'/>
</source>
<address type='usb' bus='0' port='2'/>
</hostdev>
</devices>
</domain>
修改完成后, 重新定义虚拟机配置以使更改生效 virsh define Win10.xml
注意事项
- USB 设备直通时, 确保设备的协议版本是 USB 2.0 或更低
- 在虚拟机配置中使用
hostdev
元素时, 设备 ID 必须正确无误
14. 虚拟机 win VFIO 驱动程序安装
在虚拟机里下载驱动程序并安装
https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso
之前用 yum install virtio-win
下载的文件在 /usr/share/virtio-win/
15. 给虚拟机添加显卡
为了给虚拟机添加显卡, 可以使用 PCI 直通 (PCI Passthrough) 技术, 将主机的显卡设备直通到虚拟机
获取显卡的 PCI 设备 ID
首先, 使用 lspci -nn
命令查找系统中所有的 PCI 设备, 筛选出显卡相关信息
lspci -nn | grep -i nvidia
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation TU102 [GeForce RTX 2080 Ti Rev. A] [10de:1e07] (rev a1)
01:00.1 Audio device [0403]: NVIDIA Corporation Device [10de:10f7] (rev a1)
01:00.2 USB controller [0c03]: NVIDIA Corporation Device [10de:1ad6] (rev a1)
01:00.3 Serial bus controller [0c80]: NVIDIA Corporation Device [10de:1ad7] (rev a1)
这里列出的 PCI 设备序号 01:00.0
01:00.1
01:00.2
01:00.3
修改虚拟机的 XML 配置文件
在虚拟机的 XML 配置文件中添加显卡直通配置, 首先找到虚拟机的 XML 配置文件, 路径通常在 /etc/libvirt/qemu/
01:00.0
这里需要对应配置文件的 <source>
节点里面 <address domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
<hostdev>
里面是直通一个 PCI 设备, 例如我这里有 4 个需要穿透到里面, 就要有 4 个<hostdev>
<hostdev mode='subsystem' type='pci' managed='yes'>
<driver name='vfio'/>
<source>
<address domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
</source>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</hostdev>
完整的显卡和相关设备直通配置
<domain type='kvm'>
<name>Win10</name>
...
<devices>
...
<hostdev mode='subsystem' type='pci' managed='yes'>
<driver name='vfio'/>
<source>
<address domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
</source>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</hostdev>
<hostdev mode='subsystem' type='pci' managed='yes'>
<driver name='vfio'/>
<source>
<address domain='0x0000' bus='0x01' slot='0x00' function='0x1'/>
</source>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
</hostdev>
<hostdev mode='subsystem' type='pci' managed='yes'>
<driver name='vfio'/>
<source>
<address domain='0x0000' bus='0x01' slot='0x00' function='0x2'/>
</source>
<address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
</hostdev>
<hostdev mode='subsystem' type='pci' managed='yes'>
<driver name='vfio'/>
<source>
<address domain='0x0000' bus='0x01' slot='0x00' function='0x3'/>
</source>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
</hostdev>
</devices>
</domain>
修改完需要重新定义虚拟机 virsh define Win10.xml
启动虚拟机
虚拟机现在应该已经能够使用物理显卡。将显示器视频输出线连接到独立显卡
可以通过安装相应的驱动程序 (例如 NVIDIA 驱动程序) 来在虚拟机内使用显卡。
virsh start Win10
16. 解决显卡 43 错误代码
Fighting error 43 – how to use Nvidia GPU in a virtual machine.
在安装了 NVIDIA 显卡驱动后, 如果在 Windows 设备管理器中看到 错误代码 43, 这是因为从 NVIDIA 驱动程序版本 337.88 开始, NVIDIA 会检测虚拟机管理程序 (如 KVM) 并禁用驱动, 导致该错误。
为了解决这个问题, 可以通过修改虚拟机的 XML 配置文件来隐藏虚拟化特性, 使其不被 NVIDIA 驱动检测到
修改 <domain>
标签
修改虚拟机 XML 配置, 路径通常在 /etc/libvirt/qemu/
找到第一行
<domain type='kvm'>
改为
<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
启用隐藏 KVM
找到 <features>
标签, 添加 <kvm><hidden state='on'/></kvm>
来隐藏 KVM 特性
<features>
...
<kvm>
<hidden state='on'/>
</kvm>
</features>
修改 CPU 配置
在 <devices>
标签的末尾, 添加以下 qemu:commandline
配置, 以禁用虚拟化扩展并隐藏虚拟机特征
</devices>
<qemu:commandline>
<qemu:arg value='-cpu'/>
<qemu:arg value='host,hv_time,kvm=off,hv_vendor_id=null'/>
</qemu:commandline>
</domain>
这些设置对我有用 kira~(’· w < ` )
修改完需要重新定义虚拟机 virsh define Win10.xml
17. 给虚拟机添加物理磁盘
2012/10/14: Adding a Physical Disk to a Guest with Libvirt / KVM
通过手动修改虚拟机的 XML 配置文件, 可以将物理磁盘添加到虚拟机中。virt-manager
本身无法直接将物理磁盘添加到虚拟机, 但通过编辑 XML 文件, 你可以实现这一功能。
在 <devices>
标签中添加磁盘配置
/etc/libvirt/qemu/<your-vm>.xml
在编辑器中打开
在 XML 配置文件中的 <devices>
标签下, 添加 <disk>
配置, 指定要添加的物理磁盘路径。
<devices>
...
<disk type='block' device='disk'>
<driver name='qemu' type='raw'/>
<source dev='/dev/md/storage'/>
<target dev='vdb' bus='virtio'/>
<address type='pci' domain='0x0000' bus='0x04' slot='0x00' function='0x0'/>
</disk>
...
</devices>
<source dev='/dev/md/storage'/>
: 这里指定了物理磁盘的设备路径,/dev/md/storage
是一个示例路径, 你需要根据实际的磁盘路径进行调整<target dev='vdb' bus='virtio'/>
: 这是虚拟机中的虚拟磁盘名称 (vdb
), 并指定了使用virtio
总线进行连接。这是推荐的方式, 以提高磁盘性能<address type='pci' domain='0x0000' bus='0x04' slot='0x00' function='0x0'/>
: 为磁盘指定一个 PCI 地址, 这通常用于管理多个磁盘的设备。我的配置文件加入了这部分
修改完需要重新定义虚拟机 virsh define Win10.xml
本文参考文献
KVM : GPU Passthrough ★★★★★
VGA Passthrough on virtual machines in CentOS 7 ★★★★★
centos 7禁用nouveau及安装NVIDIA显卡驱动 ★★★★★
CentOS7 minimal kvm iommu 辅助虚拟化 vt-x (用于pci透传) ★★★★★
配置宿主机网络 Bridge模式配置 ★★★★★
Why does my Windows 7 VM running under Linux’ KVM not use all the virtual processors? ★★★★★
Fighting error 43 - how to use Nvidia GPU in a virtual machine. ★★★★★
Adding_USB_Device_Pass-through ★★★★★
Adding a Physical Disk to a Guest with Libvirt / KVM ★★★★★
Ubuntu 18.04 - KVM/QEMU Windows 10 GPU Passthrough ★★★★☆
CentOS7.2上用KVM安装虚拟机windows10踩过的坑 ★★★★☆
vga-passthrough/3_BASIC_SETUP.md ★★★☆☆
“Error 43: Driver failed to load” on Nvidia GPUs passed to Windows VMs ★★☆☆☆
Centos7.4安装kvm虚拟机(使用virt-manager管理) ★☆☆☆☆
未使用到的资料 SR-IOV 直通设置 万兆网卡
16.2. PCI DEVICE ASSIGNMENT WITH SR-IOV DEVICES
Frequently Asked Questions for SR-IOV on Intel® Ethernet Server Adapters
QEMU’s new -nic command line option
10G NIC performance: VFIO vs virtio - KVM
libvirt: Domain XML format KVM xml 格式
CentOS 7でKVM + libvirt + Open vSwitchな仮想化環境のつくり方
KVM Virtualization 10gbe virtual ethernet