KVM创建windows虚拟机,并设置显卡直通

查看宿主机环境是否支持虚拟化

lscpu | grep -E 'vmx|svm'

如果返回值中又vmx或者svm证明是可以使用宿主机进行虚拟化的

升级内核

如果操作系统是centos7.9以下的建议升级

yum update && yum upgrade

安装虚拟化组件

yum install qemu-kvm qemu-img virt-manager libvirt libvirt-python virt-manager libvirt-client virt-install virt-viewer -y

安装完成后设置虚拟机接口管理组件启动和开机自启

systemctl start libvirtd
systemctl enable libvirtd

关闭selinux

sed -i 's/SELinux=enforcing/SELinux=disabled/' /etc/selinux/config
setenforce 0

关闭防火墙

systemctl stop firewalld
systemctl disable firewalld

配置GPU直通

配置主板支持虚拟化

BIOS打开VT-D和AMD-V

在宿主机中启用iommu

iommu是GPU虚拟机直通的核心,负责把主板上的设备分组,分成一个一个group,每个group都可以单独的启用或者停用,在没启用iommu之前,宿主系统会占用全部的硬件。在启用iommu之后,宿主系统可以有选择的预留一些硬件资源,把这些硬件资源分配给虚拟机

方法一:

编辑/etc/default/grub文件将intel_iommu=on通过将参数附加到文件中内核行的内核行,在内核中激活 Intel VT-d

GRUB_CMDLINE_LINUX_DEFAULT="... intel_iommu=on ..."
或
GRUB_CMDLINE_LINUX="... intel_iommu=on ..."
重新生成内核
grub2-mkconfig -o /boot/grub2/grub.cfg
重启机器
reboot
验证是否生效
[root@centos ~]# cat /proc/cmdline | grep iommu
BOOT_IMAGE=/vmlinuz-3.10.0-1160.el7.x86_64 root=UUID=46d5848a-0580-47cc-8fcc-da333a56c88f ro intel_iommu=on crashkernel=auto rhgb quiet
[root@centos ~]# dmesg |grep -e DMAR -e IOMMU
[    0.000000] ACPI: DMAR 0000000069af6000 00348 (v01 ALASKA   A M I  00000001 INTL 20091013)
[    0.000000] DMAR: IOMMU enabled
[    0.182453] DMAR: Host address width 46

可以看到两个命令输出intel_iommu=onIOMMU enabled则代表已经生效,系统现在支持 PCI 直通

  • 注意:如果使用方法一失败,则代表启动时候并没有使用/boot/grub2/grub.cfg,可以使用方法二
方法二:
查询系统grub.cfg文件
[root@centos ~]# find / -name "grub.cfg"
/boot/efi/EFI/centos/grub.cfg
/boot/grub2/grub.cfg

可以看到还有/boot/efi/EFI/centos/grub.cfg配置文件

打开iommu

对照/boot/grub2/grub.cfgintel_iommu=on添加到/boot/efi/EFI/centos/grub.cfg相应位置

[root@centos ~]# cat /boot/efi/EFI/centos/grub.cfg | grep intel_iommu=on
        linux16 /vmlinuz-3.10.0-1160.el7.x86_64 root=UUID=46d5848a-0580-47cc-8fcc-da333a56c88f ro intel_iommu=on crashkernel=auto rhgb quiet
        linux16 /vmlinuz-0-rescue-705f25d4411e49888f865cd230e1105f root=UUID=46d5848a-0580-47cc-8fcc-da333a56c88f ro intel_iommu=on crashkernel=auto rhgb quiet

按照上方格式添加即可,我这里只有关键两行需要更新,有的系统可能有三行需要更新,仅供参考

重启验证

参考方法一

在宿主机中预留iommu group

iommu group是硬件实现上的分组。在Linux的实现中,只认得各个在总线上的硬件,并挨个挨个的启动起来,我们要做的就是阻止Linux内核在启动时初始化某些组里的硬件

这里有一点需要非常注意的是,如果我们需要预留某个iommu组,我们必须完整的预留iommu组里的所有硬件。 如果我们的预留是不完整的,当我们把iommu组分配给虚拟机后,宿主系统会直接IO总线冲突,连重启的机会都没有

加载内核模块vfio-pci
[root@centos ~]# lspci -nn | grep -i nvidia
4f:00.0 3D controller [0302]: NVIDIA Corporation Device [10de:2235] (rev a1)
50:00.0 3D controller [0302]: NVIDIA Corporation Device [10de:2235] (rev a1)
53:00.0 3D controller [0302]: NVIDIA Corporation Device [10de:2235] (rev a1)
57:00.0 3D controller [0302]: NVIDIA Corporation Device [10de:2235] (rev a1)
9c:00.0 3D controller [0302]: NVIDIA Corporation Device [10de:2235] (rev a1)
9d:00.0 3D controller [0302]: NVIDIA Corporation Device [10de:2235] (rev a1)
a0:00.0 3D controller [0302]: NVIDIA Corporation Device [10de:2235] (rev a1)
a4:00.0 3D controller [0302]: NVIDIA Corporation Device [10de:2235] (rev a1)

可以看到我有八张显卡,因为我只需要直通一张显卡到虚拟机中,所以这里需要记住两个id,4f:00.0和10de:2235

找出iommu group中的所有设备

先找出设备所在的的iommu group

[root@centos ~]# dmesg | grep iommu | grep 4f:00.0
[    3.573885] iommu: Adding device 0000:4f:00.0 to group 28

可以看到要预留的iommu group是28

这里再次强调,一个iommu group可能带有很多设备,我们只能按照iommu group为单位分配设备给虚拟机

[root@centos ~]# dmesg | grep -e "iommu" | grep -w 28
[    3.573885] iommu: Adding device 0000:4f:00.0 to group 28

可以看到我这个分组就一个设备,记录左边的值4f:00.0 把这个设备给预留掉

[root@centos ~]# lspci -nn | grep 4f:00.0
4f:00.0 3D controller [0302]: NVIDIA Corporation Device [10de:2235] (rev a1)

此时确定我们要预留设备id为10de:2235 如果有多个设备,请逗号分隔

在系统中预留设备

创建文件vfio.conf
[root@centos ~]# cat /etc/modprobe.d/vfio.conf
options vfio-pci ids=10de:2235
创建文件vfio-pci.conf
[root@centos ~]# cat  /etc/modules-load.d/vfio-pci.conf
vfio-pci
重启系统
reboot
验证是否加载成功
[root@centos ~]# dmesg | grep -i vfio
[   32.353304] VFIO - User Level meta-driver version: 0.3
[   32.543346] vfio_pci: add [10de:2235[ffff:ffff]] class 0x000000/00000000
...

调整网络

配置内核IP转发和过滤器
sysctl -a | grep "\.rp_filter"

rp_filter = 值替换成0 ,然后追加到/etc/sysctl.conf配置文件里 ,同时再加上IP转发和过滤器

[root@centos ~]# cat /etc/sysctl.conf
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.bond0.rp_filter = 0
net.ipv4.conf.bond0/1098.rp_filter = 0
net.ipv4.conf.bond0/1168.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.ens31f0.rp_filter = 0
net.ipv4.conf.ens31f1.rp_filter = 0
net.ipv4.conf.ens42f0.rp_filter = 0
net.ipv4.conf.ens42f1.rp_filter = 0
net.ipv4.conf.lo.rp_filter = 0
net.ipv4.conf.usb0.rp_filter = 0

net.ipv4.ip_forward = 0
net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0
net.bridge.bridge-nf-call-arptables = 0
重新加载kernel参数
sysctl -p
创建网桥br0

因为创建起来的虚拟机想和宿主机在同一网段中,所以这里我的网络模式选择桥接,接下来需要创建一个网桥设备

[root@centos ~]# cat /etc/sysconfig/network-scripts/ifcfg-br0
TYPE=Bridge
BOOTPROTO=none
DEFROUTE=yes
PEERDNS=yes
PEERROUTES=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=no
NAME=br0
DEVICE=br0
ONBOOT=yes
IPADDR=10.1.98.12
PREFIX=23
GATEWAY=10.1.98.1
DNS1=10.1.98.1
DNS2=114.114.114.114
修改bond0.1098网卡

这个网桥设备是接管宿主机物理网卡的流量,其实就是将物理网卡的IP信息配置在网桥上,在把物理网卡绑定到这个网桥上,接下来修改物理网卡信息(不同机器网卡名不同,根据实际情况修改)

[root@centos ~]# cat /etc/sysconfig/network-scripts/ifcfg-bond0.1098
DEVICE=bond0.1098
VLAN=yes
ONBOOT=yes
BOOTPROTO=static
IPADDR=10.1.98.12
PREFIX=23
GATEWAY=10.1.98.1
DNS1=114.114.114.114
BRIDGE=br0
重启网络
systemctl restart network
查看网桥状态
[root@centos ~]# brctl show
bridge name     bridge id               STP enabled     interfaces
br0             8000.e8ebd301c394       no              bond0.1098
                                                        vnet0
docker0         8000.02425eb774a7       no
virbr0          8000.5254003c6a11       yes             virbr0-nic

可以看见刚刚创建的br0上有个接口是bond0.1098网卡

  • vnet0是启动虚拟机后出现的接口,连接虚拟机和网桥
  • virbr0网桥是kvm安装后自动创建的用于默认的nat网络

下载virtio驱动

因为kvm安装windows采用的是virtio的形式,主要提供是磁盘和网卡驱动,下载地址:传送门

下载virtio-win-0.1.126_amd64.vfd

创建磁盘

qcow2格式的磁盘也能够动态的分配磁盘空间,只不过,通过virt-manager的图形化界面创建的磁盘默认就是立即分配所有磁盘空间的,如果想要创建一个动态分配磁盘空间的磁盘,需要使用命令提前创建好对应的磁盘,创建磁盘命令如下

qemu-img create -f qcow2 windows-root.qcow2 50G

想要在宿主机中查看这个磁盘最大能够占用多少空间,可以使用qemu-img info命令查看,如下

[root@centos disk]# qemu-img info windows-root.qcow2
image: windows-root.qcow2
file format: qcow2
virtual size: 50G (53687091200 bytes)
disk size: 196K
cluster_size: 65536
Format specific information:
    compat: 1.1
    lazy refcounts: false
    refcount bits: 16
    corrupt: false

创建虚拟机

使用命令创建虚拟机,virt-install命令可以直接在命令行创建虚拟机,iso镜像文件请自行下载,示例如下

virt-install \
--name WindowsTest \
--memory 4096 \
--vcpus sockets=2,cores=2,threads=2 \
--cdrom=/mnt/data/kvm/iso/windows_10_1909_x64_dvd.iso \
--os-type=windows \
--os-variant=auto \
--disk /mnt/data/kvm/disk/windows-root.qcow2,bus=virtio,size=100 \
--disk /mnt/data/kvm/iso/virtio-win-0.1.126_amd64.vfd,device=floppy \
--network bridge=br0,model=virtio \
--host-device 4f:00.0 \
--features kvm_hidden=on \
--graphics vnc,password=123,listen=::,port=5910 \
--hvm \
--virt-type kvm

上述virt-install命令各个参数含义如下
–name=WindowsTest 表示为创建的虚拟机命名为WindowsTest
–vcpus=2 表示设置虚拟机cpu有2个核心
–memory=4096 表示设置内存为4G

--cdrom 表示使用本地iso镜像安装虚拟机
–disk 表示指定虚拟机的磁盘镜像的路径

--graphics vnc 登录方式为vnc,创建过程vnc远程配置即可

--host-device 显卡的id,建议按组全部添加

--features kvm_hidden=on //阻止nvidia驱动发现虚拟机

备注:

  • 分配给虚拟机的vCPU个数由sockets、cores、threads三个参数的乘积来控制,sockets指代CPU插槽数目,cores指代每个插槽芯片的核心数,threads指代那个核心的超线程,如上所示创建的虚拟机共有8个逻辑cpu
  • listen指代的是虚拟机的VNC监听接口,默认是localhost,0:0:0:0指带所有的IPv4接口,::指代所有接口,包括IPv4和IPv6

安装虚拟机

使用vnc来继续完成系统的安装,刚刚创建机器已经指定vnc的端口和密码,ip就是宿主机的,连接上就可进入安装界面了

img

安装过程中会遇到看不见磁盘的情况是因为没有加载virtio驱动的原因,这时候就轮到virtio-win-0.1.126_amd64.vfd起作用,virtio驱动是以软盘的形式加载的,这样可以避免虚拟机启动时找不到系统盘镜像

img

选择“加载驱动”,“浏览”,找到“软盘驱动器”,点开后选择 “Win10”确定,会发现有两个驱动,一个是Ethernet网卡,一个SCSI磁盘,操作两次驱动加载完成后,磁盘就出现了,继续安装即可

img
img
img

加载完驱动就可以看到系统已经识别到磁盘了

img

后续正常安装即可进入系统,后续配置IP,因为我是桥接模式,正常dhcp默认就会分配和宿主机同网段的IP地址,但是我的网络比较特殊,需要自己配置,就需要找宿主机同一网段未使用的IP地址配置windows中,这里不在详细说明,配置完成后打开远程即可通过IP进行远程连接了

如需要将软盘卸载掉,删除以下内容(编辑前先将虚拟机关机)

[root@centos ~]# cat /etc/libvirt/qemu/WindowsTest.xml
...
    <disk type='file' device='floppy'>
      <driver name='qemu' type='raw'/>
      <source file='/mnt/data/kvm/iso/virtio-win-0.1.126_amd64.vfd'/>
      <target dev='fda' bus='fdc'/>
      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
    </disk>
...

常用命令

查看所有已经创建的虚拟机

virsh list --all

查看虚拟机的概览信息

virsh dominfo kvm1

查看虚拟机详细信息在/etc/libvirt/qemu

[root@centos ~]# cd /etc/libvirt/qemu/
[root@centos qemu]# ls
cirros-test.xml  networks  kvm1.xml

从上述信息中可以看出,此目录中,有一个以kvm1虚拟机名为前缀的xml文件,这个kvm1.xml中存放的就是kvm1虚拟机的详细配置

上面只是配置的存放位置,不可以用vim直接修改,如果想修改的话需要执行如下命令即可

virsh edit kvm1

如果只是想要查看配置文件的内容,不进行任何修改,其实也没有必要使用virsh edit命令,也不用进入/etc/libvirt/qemu/目录查看对应的配置文件,直接使用virsh dumpxml命令,加上虚拟机名,即可直接将配置文件的内容输出到终端中

virsh dumpxml kvm1

在通过KVM创建虚拟机时,如果没有指定磁盘镜像,那么磁盘镜像默认存放在/var/lib/libvirt/images/目录中,磁盘镜像名以虚拟机名为前缀,以qcow2为后缀,qcow2是KVM默认使用的磁盘镜像格式,它既是虚拟机的磁盘,又是虚拟机的镜像,我们可以通过qcow2文件快速的实现虚拟机的迁移

[root@centos ~]# ll -h /var/lib/libvirt/images/kvm1.qcow2
-rw------- 1 qemu qemu 21G Oct  9 13:03 /var/lib/libvirt/images/kvm1.qcow2

虚拟机关机

virsh shutdown --domain WindowsTest

虚拟机开机

virsh start --domain WindowsTest

虚拟机挂起

virsh suspend --domain WindowsTest

虚拟机删除

virsh undefine --domain WindowsTest

参考网站

https://blog.51cto.com/huanghai/4749617

https://www.jianshu.com/p/035287ba9acb

https://mechanical-consciousness.com/2020/03/20/kvm-gpu-passthrough.html

https://blog.acesheep.com/index.php/archives/720/

https://blog.51cto.com/join12/1009512

https://cloud.tencent.com/developer/article/1004342

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容