openstack 配置GPU直通(pci_passthrough)

参考:OpenStack下利用透传技术(passthrough)对GPU实现虚拟化

参考:centos 7.3下为虚拟机透传GPU

bios配置确认

首先要确定主板和CPU都支持虚拟化技术,在BIOS将VT-d、VT-x设置成enable。

以Intel为例,需要将下面两项设置为enable:

VT: Intel Virtualization Technology
VT-d: Intel VT for Directed I/O

操作系统配置

开启iommu

使用如下命令确认是否支持iommu

cat /proc/cmdline | grep iommu

如果没有输出,说明不支持iommu,需要手动开启。编辑/etc/default/grub,在GRUB_CMDLINE_LINUX中添加intel_iommu=on配置项:

GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="intel_iommu=on crashkernel=auto rhgb quiet"
GRUB_DISABLE_RECOVERY="true"

更新grub,并重启设备:

grub2-mkconfig -o /boot/grub2/grub.cfg
shutdown -r now

重启以后如下确认是否正常:

#使用下面命令
dmesg | grep -i iommu
#如果输出类似下面的内容,说明正确
[    0.000000] Command line: BOOT_IMAGE=/boot/vmlinuz-3.10.0-862.6.3.el7.x86_64 root=UUID=4e83b2b5-5ff1-4b1b-af0f-3f6a7f8275ea ro intel_iommu=on crashkernel=auto rhgb quiet
[    0.000000] Kernel command line: BOOT_IMAGE=/boot/vmlinuz-3.10.0-862.6.3.el7.x86_64 root=UUID=4e83b2b5-5ff1-4b1b-af0f-3f6a7f8275ea ro intel_iommu=on crashkernel=auto rhgb quiet
[    0.000000] DMAR: IOMMU enabled
[    0.257808] DMAR-IR: IOAPIC id 3 under DRHD base  0xfbffc000 IOMMU 0
[    0.257810] DMAR-IR: IOAPIC id 1 under DRHD base  0xd7ffc000 IOMMU 1
[    0.257812] DMAR-IR: IOAPIC id 2 under DRHD base  0xd7ffc000 IOMMU 1

虚拟化支持确认

egrep -c '(vmx|svm)' /proc/cpuinfo

如果输入非0,则说明支持

配置vfio

检查当前显卡设备信息

[root@ostack-228-26 ~]# lspci -nn | grep NVID
06:00.0 VGA compatible controller [0300]: NVIDIA Corporation Device [10de:1e04] (rev a1)
06:00.1 Audio device [0403]: NVIDIA Corporation Device [10de:10f7] (rev a1)
06:00.2 USB controller [0c03]: NVIDIA Corporation Device [10de:1ad6] (rev a1)
06:00.3 Serial bus controller [0c80]: NVIDIA Corporation Device [10de:1ad7] (rev a1)
83:00.0 VGA compatible controller [0300]: NVIDIA Corporation Device [10de:1e04] (rev a1)
83:00.1 Audio device [0403]: NVIDIA Corporation Device [10de:10f7] (rev a1)
83:00.2 USB controller [0c03]: NVIDIA Corporation Device [10de:1ad6] (rev a1)
83:00.3 Serial bus controller [0c80]: NVIDIA Corporation Device [10de:1ad7] (rev a1)

可以看到,其实我的这台设备上有两个个vga设备(就是我们服务器上的2080),这两个pci设备一共有4个硬件:VGA、Audio、USB、Serial bus

确认驱动

由于我们的物理服务器操作系统,并没有安装NVIDIA显卡驱动,所以我们会发现如下信息。其中USB设备使用了xhci_hcd驱动,这个驱动是服务器自带的。

lspci -vv -s 06:00.0 | grep driver 
lspci -vv -s 06:00.1 | grep driver 
lspci -vv -s 06:00.2 | grep driver 
	Kernel driver in use: xhci_hcd
lspci -vv -s 06:00.3 | grep driver

如果我们安装了NVIDIA驱动的话, 可能会获得如下输出:

lspci -vv -s 06:00.0 | grep driver 
	Kernel driver in use: nvidia
lspci -vv -s 06:00.1 | grep driver 
	Kernel driver in use: snd_hda_intel
lspci -vv -s 06:00.2 | grep driver 
	Kernel driver in use: xhci_hcd
lspci -vv -s 06:00.3 | grep driver 

配置vfio

因为我们想要把VGA设备透传到虚拟机中,首先我们需要将设备从物理机上分离(可能分离的 说法并不准确,暂且这么认为),实现的方法是将设备使用的默认驱动禁用,然后将设备加入到vfio模块,让设备使用vfio驱动。

在上面,我们已经查到了,理论上 ,由于我们并没有装NVIDIA驱动,我们只需要将xhci_hcd禁用即可,但是为了以防万一,我们可以将其他nvidia驱动也加到禁止名单。

这里我们将GPU带的4个设备的驱动都配置成vfio的一个原因是:默认情况下,统一pci端口的不同设备,会被分配到同一个iommu组,同一组的设备,只能同时被分配到一个虚拟机使用。假设,我们只讲VGA设备分离,其他三个不分离的话,会导致创建虚拟机的时候报错如下错误:Please ensure all devices within the iommu_group are bound to their vfio bus driver.。这时候有2中解决办法:

  • 将同一iommu组的所有设备都直通给同一个虚拟机(本章的方案)
  • 将同一pci端口的不同设备分到不通的iommu组(等待探索)

禁用默认显卡

为了保证设备不被宿主机使用,我们建议将上面查到的两个驱动禁用,编辑/etc/modprobe.d/blacklist.conf,添加如下配置(似乎并不需要此步骤):

blacklist xhci_hcd
blacklist nvidia
blacklist snd_hda_intel
#下面是网上看到的,有可能不需要
blacklist nvidiafb

配置系统加载模块

配置加载vfio-pci模块,编辑/etc/modules-load.d/vfio-pci.conf,添加如下内容:

vfio_pci
#下面的内容也是参考网上的配置,有可能不需要
pci_stub
vfio
vfio_iommu_type1
kvm
kvm_intel

配置vfio加载的设备

配置使用vfio驱动的设备(这里的设备就是上面我们查到的设备的)编辑/etc/modprobe.d/vfio.conf,添加如下配置:

# GTX 2080Ti and its audio controller
options vfio-pci ids=10de:1e04,10de:10f7,10de:1ad6,10de:1ad7

重新生成内核并重启

重新生成内核文件之前,我们先备份已有的:

mv /boot/initramfs-$(uname -r).img /boot/initramfs-$(uname -r)-nouveau.img

重新生成:

dracut /boot/initramfs-$(uname -r).img $(uname -r)

重启设备:

shutdown -r now

确认

查看启动信息,确认vfio模块是否加载

dmesg | grep -i vfio
[    6.755346] VFIO - User Level meta-driver version: 0.3
[    6.803197] vfio_pci: add [10de:1b06[ffff:ffff]] class 0x000000/00000000
[    6.803306] vfio_pci: add [10de:10ef[ffff:ffff]] class 0x000000/00000000

重启以后,我们查看设备使用的驱动,都显示vfio说明正确

lspci -vv -s 06:00.0 | grep driver
	Kernel driver in use: vfio-pci
lspci -vv -s 06:00.1 | grep driver
	Kernel driver in use: vfio-pci
lspci -vv -s 06:00.2 | grep driver
	Kernel driver in use: xhci_hcd
lspci -vv -s 06:00.3 | grep driver
	Kernel driver in use: vfio-pci

openstack配置

控制节点配置

主要配置2个块,filter_scheduler和pci

[filter_scheduler]
available_filters = nova.scheduler.filters.all_filters
#主要在末尾添加:PciPassthroughFilter
enabled_filters = RetryFilter,AvailabilityZoneFilter,ComputeFilter,ComputeCapabilitiesFilter,RamFilter,CoreFilter,ImagePropertiesFilter,ServerGroupAntiAffinityFilter,ServerGroupAffinityFilter,PciPassthroughFilter
[pci]
#alias是能够直通设备的信息,多个设备多条记录,我们希望GPU上的4个设备都直通到虚拟机,所以将4个设备信息都写上
alias = {"name":"nv2080vga","product_id":"1e04","vendor_id":"10de","device_type":"type-PCI"}
alias = {"name":"nv2080aud","product_id":"10f7","vendor_id":"10de","device_type":"type-PCI"}
alias = {"name":"nv2080usb","product_id":"1ad6","vendor_id":"10de","device_type":"type-PCI"}
alias = {"name":"nv2080bus","product_id":"1ad7","vendor_id":"10de","device_type":"type-PCI"}

配置完成以后,重启nova 相关服务(nova-api和nova-scheduler:

systemctl restart openstack-nova-api.service openstack-nova-scheduler.service

配置计算节点

计算节点,主要配置pci部分

[pci]
#alias可以配置多条,对应多个设备
alias = {"name":"nv2080vga","product_id":"1e04","vendor_id":"10de","device_type":"type-PCI"}
alias = {"name":"nv2080aud","product_id":"10f7","vendor_id":"10de","device_type":"type-PCI"}
alias = {"name":"nv2080usb","product_id":"1ad6","vendor_id":"10de","device_type":"type-PCI"}
alias = {"name":"nv2080bus","product_id":"1ad7","vendor_id":"10de","device_type":"type-PCI"}
#passthrough_whitelist配置该计算节点可用于直通的设备
passthrough_whitelist = [{ "vendor_id": "10de", "product_id": "1e04" },
			             { "vendor_id": "10de", "product_id": "10f7" },
                         { "vendor_id": "10de", "product_id": "1ad6" },
                         { "vendor_id": "10de", "product_id": "1ad7" }]

重启计算服务:

ystemctl restart openstack-nova-compute

创建带有显卡直通信息的flavor

openstack flavor create --public --ram 2048 --disk 20 --vcpus 2 m1.large

openstack flavor set m1.large --property pci_passthrough:alias='nv2080vga:2,nv2080aud:2,nv2080usb:2,nv2080bus:2'
  • pci_passthrough:alias是固定格式,标识用alias方筛选pci设备
  • nv2080vga:2标识2块名为 nv2080vga的设备,多个设备英文逗号隔开

    以上步骤可以dashboard上操作

隐藏虚拟机的hypervisor id

因为NIVIDIA显卡的驱动会检测是否跑在虚拟机里,如果在虚拟机里驱动就会出错,所以我们需要对显卡驱动隐藏hypervisor id。在OpenStack的Pile版本中的Glance 镜像引入了img_hide_hypervisor_id=true的property,所以可以对镜像执行如下的命令隐藏hupervisor id:

openstack image set [IMG-UUID] --property img_hide_hypervisor_id=true

通过此镜像安装的instance就会隐藏hypervisor id。

可以通过下边的命令查看hypervisor id是否隐藏:

cpuid | grep hypervisor_id
hypervisor_id = "KVMKVMKVM   "
hypervisor_id = "KVMKVMKVM   "

上边的显示结果说明没有隐藏,下边的显示结果说明已经隐藏:

cpuid | grep hypervisor_id
hypervisor_id = "  @  @    "
hypervisor_id = "  @  @    "

创建实例

这时候,我们使用上面的flavor和image来创建虚拟机就可以了

猜你喜欢

转载自blog.csdn.net/zxycyj1989/article/details/103995482