VM 的配置存储在 /etc/libvirt/qemu/ 中的 XML 文件中,如下所示
<domain type='kvm'>
<name>sles15</name>
<uuid>ab953e2f-9d16-4955-bb43-1178230ee625</uuid>
<memory unit='KiB'>2097152</memory>
<currentMemory unit='KiB'>2097152</currentMemory>
<vcpu placement='static'>2</vcpu>
<os>
<type arch='x86_64' machine='pc-q35-2.0'>hvm</type>
</os>
<features>...</features>
<cpu mode='custom' match='exact' check='partial'>
<model fallback='allow'>Skylake-Client-IBRS</model>
</cpu>
<clock>...</clock>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<pm>
<suspend-to-mem enabled='no'/>
<suspend-to-disk enabled='no'/>
</pm>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<disk type='file' device='disk'>...</disk>
</devices>
...
</domain>要编辑 VM Guest 的配置,请检查它是否处于离线状态
>sudovirsh list --inactive
如果您的 VM Guest 在此列表中,您可以安全地编辑其配置
>sudovirsh edit NAME_OF_VM_GUEST
在保存更改之前,virsh 会根据 RelaxNG 模式验证您的输入。
使用 virt-install 工具安装时,VM Guest 的机器类型默认为 pc-q35。机器类型存储在 VM Guest 的配置文件中的 type 元素中
<type arch='x86_64' machine='pc-q35-2.3'>hvm</type>
例如,以下过程演示如何将此值更改为机器类型 q35。值 q35 是一种 Intel* 芯片组,包括 PCIe,支持最多 12 个 USB 端口,并支持 SATA 和 IOMMU。
检查您的 VM Guest 是否处于非活动状态
>sudovirsh list --inactiveId Name State ---------------------------------------------------- - sles15 shut off
编辑此 VM Guest 的配置
>sudovirsh edit sles15
将 machine 属性的值替换为 pc-q35-2.0
<type arch='x86_64' machine='pc-q35-2.0'>hvm</type>
重新启动 VM Guest
>sudovirsh start sles15
检查机器类型是否已更改。登录到 VM Guest 并运行以下命令
>sudodmidecode | grep ProductProduct Name: Standard PC (Q35 + ICH9, 2009)
每当主机系统上的 QEMU 版本升级(例如,将 VM 主机服务器升级到新的服务包时),请升级 VM Guest 的机器类型到最新可用版本。要检查,请在 VM 主机服务器上使用命令 qemu-system-x86_64 -M help。
默认机器类型 pc-i440fx,例如,会定期更新。如果您的 VM Guest 仍然使用机器类型 pc-i440fx-1.X,我们强烈建议更新到 pc-i440fx-2.X。这可以利用机器定义中的最新更新和更正,并确保更好的未来兼容性。
libvirt 自动启用默认的一组超visor 功能,在大多数情况下都足够了,但也允许根据需要启用和禁用功能。例如,Xen 默认情况下不支持启用 PCI 直通。必须使用 passthrough 设置启用它。可以使用 virsh 配置超visor 功能。查找 VM Guest 配置文件的 <features> 元素,并根据需要调整其功能。继续使用 Xen 直通示例
>sudovirsh edit sle15sp1 <features> <xen> <passthrough/> </xen> </features>
保存您的更改并重新启动 VM Guest。
有关更多信息,请参阅 libvirt 手册的 域 XML 格式 中的 超visor 功能 部分,网址为 https://libvirt.org/formatdomain.html#elementsFeatures。
可以使用 virsh 配置许多呈现给 VM Guest 的虚拟 CPU 的方面。可以更改分配给 VM Guest 的当前和最大 CPU 数量,以及 CPU 的型号和功能集。以下子部分介绍了如何更改 VM Guest 的常见 CPU 设置。
分配的 CPU 数量存储在 /etc/libvirt/qemu/ 中的 VM Guest 的 XML 配置文件中的 vcpu 元素中
<vcpu placement='static'>1</vcpu>
在此示例中,VM Guest 仅分配了一个 CPU。以下过程演示如何更改 VM Guest 的分配 CPU 数量
检查您的 VM Guest 是否处于非活动状态
>sudovirsh list --inactiveId Name State ---------------------------------------------------- - sles15 shut off
编辑现有 VM Guest 的配置
>sudovirsh edit sles15
更改分配的 CPU 数量
<vcpu placement='static'>2</vcpu>
重新启动 VM Guest
>sudovirsh start sles15
检查 VM 中的 CPU 数量是否已更改。
>sudovirsh vcpuinfo sled15VCPU: 0 CPU: N/A State: N/A CPU time N/A CPU Affinity: yy VCPU: 1 CPU: N/A State: N/A CPU time N/A CPU Affinity: yy
您也可以在 VM Guest 运行时更改 CPU 数量。CPU 可以热插拔,直到在 VM Guest 启动时配置的最大数量为止。同样,它们可以热拔,直到达到下限 1 为止。以下示例演示如何将活动 CPU 计数从 2 更改为预定义的最多 4 个。
检查当前的实时 vcpu 计数
>sudovirsh vcpucount sles15 | grep livemaximum live 4 current live 2
将当前或活动的 CPU 数量更改为 4
>sudovirsh setvcpus sles15 --count 4 --live
检查当前的实时 vcpu 计数现在为 4
>sudovirsh vcpucount sles15 | grep livemaximum live 4 current live 4
使用 KVM,可以定义具有超过 255 个 CPU 的 VM Guest。但是,需要额外的配置才能启动和运行 VM Guest。需要调整 ioapic 功能,并且需要将 IOMMU 设备添加到 VM Guest。
<domain> <vcpu placement='static'>288</vcpu> <features> <ioapic driver='qemu'/> </features> <devices> <iommu model='intel'> <driver intremap='on' eim='on'/> </iommu> </devices> </domain>
暴露给 VM Guest 的 CPU 型号通常会影响其中运行的工作负载。默认 CPU 型号源自一种称为 host-model 的 CPU 模式。
<cpu mode='host-model'/>
使用 CPU 模式 host-model 启动 VM Guest 时,libvirt 会将其主机 CPU 的模型复制到 VM Guest 定义中。复制到 VM Guest 定义的主机 CPU 模型和功能可以在 virsh capabilities 的输出中观察到。
另一个有趣的 CPU 模式是 host-passthrough。
<cpu mode='host-passthrough'/>
使用 CPU 模式 host-passthrough 启动 VM Guest 时,它将呈现与 VM 主机服务器 CPU 完全相同的 CPU。当 VM Guest 工作负载需要 libvirt 简化的 host-model CPU 中不可用的 CPU 功能时,这可能很有用。host-passthrough CPU 模式的缺点是降低了迁移灵活性。具有 host-passthrough CPU 模式的 VM Guest 只能迁移到具有相同硬件的 VM 主机服务器。
在使用 host-passthrough CPU 模式时,仍然可以禁用不需要的功能。以下配置将 VM Guest 呈现与主机 CPU 完全相同的 CPU,但禁用了 vmx 功能。
<cpu mode='host-passthrough'> <feature policy='disable' name='vmx'/> </cpu>
custom CPU 模式是另一种常用的模式,用于定义可以在不同主机之间迁移的标准化 CPU,例如在包含 Nehalem、IvyBridge 和 SandyBridge CPU 的集群中,可以将 VM Guest 配置为具有 Nehalem CPU 模型。
<cpu mode='custom' match='exact'> <model fallback='allow'>Nehalem</model> <feature policy='require' name='vme'/> <feature policy='require' name='ds'/> <feature policy='require' name='acpi'/> <feature policy='require' name='ss'/> <feature policy='require' name='ht'/> <feature policy='require' name='tm'/> <feature policy='require' name='pbe'/> <feature policy='require' name='dtes64'/> <feature policy='require' name='monitor'/> <feature policy='require' name='ds_cpl'/> <feature policy='require' name='vmx'/> <feature policy='require' name='est'/> <feature policy='require' name='tm2'/> <feature policy='require' name='xtpr'/> <feature policy='require' name='pdcm'/> <feature policy='require' name='dca'/> <feature policy='require' name='rdtscp'/> <feature policy='require' name='invtsc'/> </cpu>
有关 libvirt 的 CPU 模型和拓扑选项的更多信息,请参阅网址为 https://libvirt.org/formatdomain.html#cpu-model-and-topology 的 CPU 模型和拓扑 文档。
分配给 VM Guest 的内存量也可以使用 virsh 进行配置。它存储在 memory 元素中,并定义了 VM Guest 在启动时分配的最大内存量。可选的 currentMemory 元素定义了实际分配给 VM Guest 的内存。 currentMemory 可以小于 memory,从而允许在 VM Guest 运行时增加(或 ballooning)内存。如果省略 currentMemory,则其默认值为与 memory 元素相同的值。
可以通过编辑 VM Guest 配置来调整内存设置,但请注意,更改在下一次启动之前不会生效。以下步骤演示如何将 VM Guest 配置为以 4G 内存启动,但允许稍后扩展到 8G
打开 VM Guest 的 XML 配置文件
>sudovirsh edit sles15
找到 memory 元素并设置为 8G
... <memory unit='KiB'>8388608</memory> ...
如果不存在 currentMemory 元素,请将其添加到 memory 元素下方,或将其值更改为 4G
[...] <memory unit='KiB'>8388608</memory> <currentMemory unit='KiB'>4194304</currentMemory> [...]
可以在 VM Guest 运行时使用 setmem 子命令更改内存分配。以下示例演示如何将内存分配增加到 8G
检查 VM Guest 现有的内存设置
>sudovirsh dominfo sles15 | grep memoryMax memory: 8388608 KiB Used memory: 4194608 KiB
将使用的内存更改为 8G
>sudovirsh setmem sles15 8388608
检查更新后的内存设置
>sudovirsh dominfo sles15 | grep memoryMax memory: 8388608 KiB Used memory: 8388608 KiB
内存需求为 4 TB 或更多的 VM Guest 必须使用 host-passthrough CPU 模式,或者在使用 host-model 或 custom CPU 模式时显式指定虚拟 CPU 地址大小。默认虚拟 CPU 地址大小可能不足以满足 4 TB 或更多的内存配置。以下示例演示如何在将 host-model CPU 模式与虚拟 CPU 地址大小一起使用。
[...] <cpu mode='host-model' check='partial'> <maxphysaddr mode='passthrough'> </cpu> [...]
有关指定虚拟 CPU 地址大小的更多信息,请参阅网址为 https://libvirt.org/formatdomain.html#cpu-model-and-topology 的 CPU 模型和拓扑 文档中的 maxphysaddr 选项。
要使用 virsh 将 PCI 设备分配给 VM Guest,请按照以下步骤操作
识别要分配给 VM Guest 的主机 PCI 设备。在以下示例中,我们将一个 DEC 网卡分配给 guest
>sudolspci -nn[...] 03:07.0 Ethernet controller [0200]: Digital Equipment Corporation DECchip \ 21140 [FasterNet] [1011:0009] (rev 22) [...]
记下设备 ID(在本例中为 03:07.0)。
使用 virsh nodedev-dumpxml ID 收集有关该设备的详细信息。要获取 ID,请将设备 ID(03:07.0)中的冒号和句点替换为下划线。在结果前加上 “pci_0000_”:pci_0000_03_07_0。
>sudovirsh nodedev-dumpxml pci_0000_03_07_0<device> <name>pci_0000_03_07_0</name> <path>/sys/devices/pci0000:00/0000:00:14.4/0000:03:07.0</path> <parent>pci_0000_00_14_4</parent> <driver> <name>tulip</name> </driver> <capability type='pci'> <domain>0</domain> <bus>3</bus> <slot>7</slot> <function>0</function> <product id='0x0009'>DECchip 21140 [FasterNet]</product> <vendor id='0x1011'>Digital Equipment Corporation</vendor> <numa node='0'/> </capability> </device>
记下域、总线和功能的值(请参阅之前 XML 代码中以粗体显示的)。
在将设备附加到 VM Guest 之前,先将其从主机系统分离
>sudovirsh nodedev-detach pci_0000_03_07_0Device pci_0000_03_07_0 detached
当使用不支持 FLR(功能级别复位)或 PM(电源管理)复位的多功能 PCI 设备时,需要将所有功能从 VM 主机服务器分离。出于安全原因,必须重置整个设备。如果其中一个功能仍然由 VM 主机服务器或其他 VM Guest 使用,libvirt 将拒绝分配该设备。
将域、总线、插槽和功能值从十进制转换为十六进制。在我们的例子中,域 = 0,总线 = 3,插槽 = 7,功能 = 0。确保将值按正确的顺序插入
>printf "<address domain='0x%x' bus='0x%x' slot='0x%x' function='0x%x'/>\n" 0 3 7 0
结果如下
<address domain='0x0' bus='0x3' slot='0x7' function='0x0'/>
在你的域上运行 virsh edit,并将以下设备条目添加到 <devices> 部分,使用上一步的结果
<hostdev mode='subsystem' type='pci' managed='yes'>
<source>
<address domain='0x0' bus='0x03' slot='0x07' function='0x0'/>
</source>
</hostdev>managed 与 unmanaged 相比
libvirt 识别两种处理 PCI 设备的方式:它们可以是 managed 或 unmanaged。在 managed 模式下,libvirt 会处理所有断开设备与现有驱动程序的细节(如果需要),重置设备,在启动域之前将其绑定到 vfio-pci 等。当域终止或设备从域中移除时,libvirt 会从 vfio-pci 断开绑定,并在 managed 设备的情况下重新绑定到原始驱动程序。如果设备是 unmanaged,用户必须确保在将其分配给域之前,以及设备不再被域使用后,完成设备的这些管理方面的工作。
在上面的例子中,managed='yes' 选项意味着该设备是 managed。要将设备模式切换为 unmanaged,请在上面的列表中设置 managed='no'。如果你这样做,你需要使用 virsh nodedev-detach 和 virsh nodedev-reattach 命令来处理相关的驱动程序。在启动 VM Guest 之前,你需要通过运行 virsh nodedev-detach pci_0000_03_07_0 从主机上分离该设备。如果 VM Guest 未运行,你可以通过运行 virsh nodedev-reattach pci_0000_03_07_0 使该设备可用于主机。
关闭 VM Guest,如果主机上正在运行 SELinux,请禁用它。
>sudosetsebool -P virt_use_sysfs 1
启动你的 VM Guest,使分配的 PCI 设备可用
>sudovirsh start sles15
在较新的 QEMU 机器类型(pc-i440fx-2.0 或更高版本)上,使用 SLES 11 SP4 KVM guests 时,acpiphp 模块默认情况下不会在 guest 中加载。必须加载此模块才能启用磁盘和网络设备的 hotplugging。要手动加载该模块,请使用命令 modprobe acpiphp。也可以通过将 install acpiphp /bin/true 添加到 /etc/modprobe.conf.local 文件中来自动加载该模块。
使用 QEMU Q35 机器类型的 KVM guests 具有一个 PCI 拓扑,其中包括一个 pcie-root 控制器和七个 pcie-root-port 控制器。 pcie-root 控制器不支持 hotplugging。每个 pcie-root-port 控制器支持 hotplugging 单个 PCIe 设备。PCI 控制器不能进行 hotplugging,因此请相应地进行计划,并添加更多的 pcie-root-port 以 hotplug 超过七个 PCIe 设备。可以添加一个 pcie-to-pci-bridge 控制器以支持 hotplugging 遗留 PCI 设备。有关 QEMU 机器类型之间 PCI 拓扑的更多信息,请参阅 https://libvirt.org/pci-hotplug.html。
为了支持 IBM Z,QEMU 通过允许用户配置额外的属性来扩展 PCI 表示。向 <zpci/> libvirt 规范添加了两个额外的属性——uid 和 fid。 uid 代表用户定义的标识符,而 fid 代表 PCI 功能标识符。这些属性是可选的,如果你没有指定它们,它们将自动生成不冲突的值。
要在你的域规范中包含 zPCI 属性,请使用以下示例定义
<controller type='pci' index='0' model='pci-root'/>
<controller type='pci' index='1' model='pci-bridge'>
<model name='pci-bridge'/>
<target chassisNr='1'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'>
<zpci uid='0x0001' fid='0x00000000'/>
</address>
</controller>
<interface type='bridge'>
<source bridge='virbr0'/>
<model type='virtio'/>
<address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0'>
<zpci uid='0x0007' fid='0x00000003'/>
</address>
</interface>要使用 virsh 将 USB 设备分配给 VM Guest,请按照以下步骤操作
识别要分配给 VM Guest 的主机 USB 设备
>sudolsusb[...] Bus 001 Device 003: ID 0557:2221 ATEN International Co., Ltd Winbond Hermon [...]
记下供应商和产品 ID。在我们的例子中,供应商 ID 是 0557,产品 ID 是 2221。
在你的域上运行 virsh edit,并将以下设备条目添加到 <devices> 部分,使用上一步的值
<hostdev mode='subsystem' type='usb'>
<source startupPolicy='optional'>
<vendor id='0557'/>
<product id='2221'/>
</source>
</hostdev>与其使用 <vendor/> 和 <product/> ID 定义主机设备,不如使用 <address/> 元素,如在 第 14.7 节,“添加 PCI 设备” 中描述的用于主机 PCI 设备的方式。
关闭 VM Guest,如果主机上正在运行 SELinux,请禁用它
>sudosetsebool -P virt_use_sysfs 1
启动你的 VM Guest,使分配的 PCI 设备可用
>sudovirsh start sles15
具有 SR-IOV 功能的 SR-IOV PCIe 设备可以复制其资源,因此它们显示为多个设备。每个这些““伪设备””都可以分配给 VM Guest。
SR-IOV 是由外围组件互连特别兴趣小组 (PCI-SIG) 联盟创建的行业规范。它引入了物理功能 (PF) 和虚拟功能 (VF)。PF 是用于管理和配置设备的完整 PCIe 功能。PF 也可以移动数据。VF 缺乏配置和管理部分——它们只能移动数据和一组缩减的配置功能。由于 VF 没有所有 PCIe 功能,主机操作系统或 Hypervisor 必须支持 SR-IOV 才能访问和初始化 VF。每个设备的 VF 的理论最大数量是 256(因此双端口以太网卡的最高数量将是 512)。在实践中,这个最大值要低得多,因为每个 VF 都会消耗资源。
要使用 SR-IOV,必须满足以下要求
支持硬件虚拟化(AMD-V 或 Intel VT-x)的 AMD64/Intel 64 主机
支持设备分配的芯片组(AMD-Vi 或 Intel VT-d)
libvirt 0.9.10 或更高版本
SR-IOV 驱动程序必须在主机系统上加载和配置
满足在 重要提示:VFIO 和 SR-IOV 的要求 上列出的主机配置要求
分配给 VM Guests 的 VF 的 PCI 地址列表
可以通过运行 lspci 从设备的 PCI 描述符中获取设备是否具有 SR-IOV 功能的信息。支持 SR-IOV 的设备报告类似于以下内容的 capability
Capabilities: [160 v1] Single Root I/O Virtualization (SR-IOV)
在最初设置 VM Guest 时将 SR-IOV 设备添加到 VM Guest 之前,VM Host Server 已经需要按照 第 14.9.2 节,“加载和配置 SR-IOV 主机驱动程序” 中描述的方式进行配置。
要访问和初始化 VF,需要在主机系统上加载 SR-IOV 功能的驱动程序。
在加载驱动程序之前,请确保通过运行 lspci 检测到该卡。以下示例显示了 Intel 82576NS 网络卡的 lspci 输出
>sudo/sbin/lspci | grep 8257601:00.0 Ethernet controller: Intel Corporation 82576NS Gigabit Network Connection (rev 01) 01:00.1 Ethernet controller: Intel Corporation 82576NS Gigabit Network Connection (rev 01) 04:00.0 Ethernet controller: Intel Corporation 82576NS Gigabit Network Connection (rev 01) 04:00.1 Ethernet controller: Intel Corporation 82576NS Gigabit Network Connection (rev 01)
如果未检测到该卡,则 BIOS/EFI 中的硬件虚拟化支持可能未启用。要检查是否启用了硬件虚拟化支持,请查看主机 BIOS 中的设置。
通过运行 lsmod 检查是否已经加载了 SR-IOV 驱动程序。在以下示例中,检查 igb 驱动程序(用于 Intel 82576NS 网络卡)返回一个结果。这意味着该驱动程序已经加载。如果该命令未返回任何内容,则该驱动程序未加载。
>sudo/sbin/lsmod | egrep "^igb "igb 185649 0
如果驱动程序已经加载,请跳过以下步骤。如果尚未加载 SR-IOV 驱动程序,则需要先卸载非 SR-IOV 驱动程序,然后才能加载新的驱动程序。使用 rmmod 卸载驱动程序。以下示例卸载了 Intel 82576NS 网络卡的非 SR-IOV 驱动程序
>sudo/sbin/rmmod igbvf
随后使用 modprobe 命令加载 SR-IOV 驱动程序——VF 参数(max_vfs)是必需的
>sudo/sbin/modprobe igb max_vfs=8
或者,你也可以通过 SYSFS 加载驱动程序
通过列出以太网设备来查找物理 NIC 的 PCI ID
>sudolspci | grep Eth06:00.0 Ethernet controller: Emulex Corporation OneConnect NIC (Skyhawk) (rev 10) 06:00.1 Ethernet controller: Emulex Corporation OneConnect NIC (Skyhawk) (rev 10)
要启用 VF,请将要加载的 VF 的数量回显到 sriov_numvfs 参数
>sudoecho 1 > /sys/bus/pci/devices/0000:06:00.1/sriov_numvfs
验证是否已加载 VF NIC
>sudolspci | grep Eth06:00.0 Ethernet controller: Emulex Corporation OneConnect NIC (Skyhawk) (rev 10) 06:00.1 Ethernet controller: Emulex Corporation OneConnect NIC (Skyhawk) (rev 10) 06:08.0 Ethernet controller: Emulex Corporation OneConnect NIC (Skyhawk) (rev 10)
获取可用的最大 VF 数量
>sudolspci -vvv -s 06:00.1 | grep 'Initial VFs'Initial VFs: 32, Total VFs: 32, Number of VFs: 0, Function Dependency Link: 01
创建一个 /etc/systemd/system/before.service 文件,该文件通过 SYSFS 在启动时加载 VF
[Unit] Before= [Service] Type=oneshot RemainAfterExit=true ExecStart=/bin/bash -c "echo 1 > /sys/bus/pci/devices/0000:06:00.1/sriov_numvfs" # beware, executable is run directly, not through a shell, check the man pages # systemd.service and systemd.unit for full syntax [Install] # target in which to start the service WantedBy=multi-user.target #WantedBy=graphical.target
在启动 VM 之前,需要创建另一个服务文件(after-local.service),指向 /etc/init.d/after.local 脚本,该脚本分离 NIC。否则 VM 将无法启动
[Unit] Description=/etc/init.d/after.local Compatibility After=libvirtd.service Requires=libvirtd.service [Service] Type=oneshot ExecStart=/etc/init.d/after.local RemainAfterExit=true [Install] WantedBy=multi-user.target
将其复制到 /etc/systemd/system。
#! /bin/sh # ... virsh nodedev-detach pci_0000_06_08_0
将其保存为 /etc/init.d/after.local。
重新启动机器并重新运行第一步中的 lspci 命令,检查是否已加载 SR-IOV 驱动程序。如果 SR-IOV 驱动程序已成功加载,你应该会看到有关 VF 的其他行
01:00.0 Ethernet controller: Intel Corporation 82576NS Gigabit Network Connection (rev 01) 01:00.1 Ethernet controller: Intel Corporation 82576NS Gigabit Network Connection (rev 01) 01:10.0 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01) 01:10.1 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01) 01:10.2 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01) [...] 04:00.0 Ethernet controller: Intel Corporation 82576NS Gigabit Network Connection (rev 01) 04:00.1 Ethernet controller: Intel Corporation 82576NS Gigabit Network Connection (rev 01) 04:10.0 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01) 04:10.1 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01) 04:10.2 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01) [...]
当 VM Host Server 上正确设置 SR-IOV 硬件后,你可以将 VF 添加到 VM Guests。为此,你需要先收集特定数据。
以下过程使用示例数据。请使用你的设置中的相应数据替换它。
使用 virsh nodedev-list 命令获取要分配的 VF 的 PCI 地址及其对应的 PF。从 第 14.9.2 节,“加载和配置 SR-IOV 主机驱动程序” 中 lspci 输出中的数值(例如 01:00.0 或 04:00.1)通过添加前缀 pci_0000_ 并将冒号和点替换为下划线进行转换。因此,lspci 列出的 PCI ID 为 04:00.0,则 virsh 列出的 PCI ID 为 pci_0000_04_00_0。以下示例列出了 Intel 82576NS 网络卡的第二个端口的 PCI ID
>sudovirsh nodedev-list | grep 0000_04_pci_0000_04_00_0 pci_0000_04_00_1 pci_0000_04_10_0 pci_0000_04_10_1 pci_0000_04_10_2 pci_0000_04_10_3 pci_0000_04_10_4 pci_0000_04_10_5 pci_0000_04_10_6 pci_0000_04_10_7 pci_0000_04_11_0 pci_0000_04_11_1 pci_0000_04_11_2 pci_0000_04_11_3 pci_0000_04_11_4 pci_0000_04_11_5
前两个条目代表 PF,而其他条目代表 VF。
运行以下 virsh nodedev-dumpxml 命令,获取要添加的 VF 的 PCI ID
>sudovirsh nodedev-dumpxml pci_0000_04_10_0<device> <name>pci_0000_04_10_0</name> <parent>pci_0000_00_02_0</parent> <capability type='pci'> <domain>0</domain> <bus>4</bus> <slot>16</slot> <function>0</function> <product id='0x10ca'>82576 Virtual Function</product> <vendor id='0x8086'>Intel Corporation</vendor> <capability type='phys_function'> <address domain='0x0000' bus='0x04' slot='0x00' function='0x0'/> </capability> </capability> </device>
需要以下数据用于下一步
<domain>0</domain>
<bus>4</bus>
<slot>16</slot>
<function>0</function>
创建一个临时 XML 文件(例如 /tmp/vf-interface.xml),其中包含将 VF 网络设备添加到现有 VM Guest 所需的数据。该文件的最小内容如下所示
<interface type='hostdev'>1 <source> <address type='pci' domain='0' bus='11' slot='16' function='0'2/>2 </source> </interface>
如果设备已经连接到主机,则无法将其连接到 VM Guest。要使其可供 Guest 使用,请先将其从主机分离。
>sudovirsh nodedev-detach pci_0000_04_10_0
将 VF 接口添加到现有的 VM Guest
>sudovirsh attach-device GUEST /tmp/vf-interface.xml --OPTION
GUEST 需要替换为 VM Guest 的域名、ID 或 UUID。--OPTION 可以是以下选项之一
--persistent此选项始终将设备添加到域的持久 XML 中。如果域正在运行,则设备将被热插拔。
--config此选项仅影响持久 XML,即使域正在运行也是如此。设备将在下次启动时出现在 VM Guest 中。
--live此选项仅影响正在运行的域。如果域处于非活动状态,则操作将失败。设备不会持久保存在 XML 中,并在下次启动时在 VM Guest 中可用。
--current此选项影响域的当前状态。如果域处于非活动状态,则设备将添加到持久 XML 中,并在下次启动时可用。如果域处于活动状态,则设备将被热插拔,但不会添加到持久 XML 中。
要分离 VF 接口,请使用 virsh detach-device 命令,该命令也接受上述选项。
如果您像在 第 14.9.3 节,“将 VF 网络设备添加到 VM Guest” 中描述的那样,静态地将 VF 的 PCI 地址定义到 VM Guest 的配置中,那么将此类 Guest 迁移到另一台主机将非常困难。主机必须在 PCI 总线上相同位置具有相同的硬件,或者必须在每次启动之前修改 VM Guest 配置。
另一种方法是创建一个包含 SR-IOV 设备的所有 VF 的设备池的 libvirt 网络。然后,VM Guest 引用此网络,并且每次启动时,都会动态地向其分配单个 VF。当 VM Guest 停止时,VF 将返回到池中,可供其他 Guest 使用。
以下网络定义示例为具有物理功能 (PF) 的 SR-IOV 设备的所有 VF 创建一个池,该物理功能位于主机上的网络接口 eth0
<network>
<name>passthrough</name>
<forward mode='hostdev' managed='yes'>
<pf dev='eth0'/>
</forward>
</network>要在主机上使用此网络,请将上述代码保存到文件,例如 /tmp/passthrough.xml,然后执行以下命令。请记住,将 eth0 替换为您的 SR-IOV 设备的 PF 的实际网络接口名称
>sudovirsh net-define /tmp/passthrough.xml>sudovirsh net-autostart passthrough>sudovirsh net-start passthrough
以下 VM Guest 设备接口定义示例使用来自在 第 14.9.4.1 节,“在 VM 主机服务器上定义 VF 池网络” 中创建的池的 SR-IOV 设备的 VF。 libvirt 会在 Guest 首次启动时自动推导出与该 PF 关联的所有 VF 的列表。
<interface type='network'> <source network='passthrough'> </interface>
在首次启动使用 VF 池网络的 VM Guest 之后,验证关联的 VF 列表。为此,在主机上运行 virsh net-dumpxml passthrough。
<network connections='1'>
<name>passthrough</name>
<uuid>a6a26429-d483-d4ed-3465-4436ac786437</uuid>
<forward mode='hostdev' managed='yes'>
<pf dev='eth0'/>
<address type='pci' domain='0x0000' bus='0x02' slot='0x10' function='0x1'/>
<address type='pci' domain='0x0000' bus='0x02' slot='0x10' function='0x3'/>
<address type='pci' domain='0x0000' bus='0x02' slot='0x10' function='0x5'/>
<address type='pci' domain='0x0000' bus='0x02' slot='0x10' function='0x7'/>
<address type='pci' domain='0x0000' bus='0x02' slot='0x11' function='0x1'/>
<address type='pci' domain='0x0000' bus='0x02' slot='0x11' function='0x3'/>
<address type='pci' domain='0x0000' bus='0x02' slot='0x11' function='0x5'/>
</forward>
</network>虽然 virsh 中没有一种机制可以列出 VM 主机服务器的所有设备,这些设备已经附加到其 VM Guest,但您可以运行以下命令来列出附加到特定 VM Guest 的所有设备
virsh dumpxml VMGUEST_NAME | xpath -e /domain/devices/hostdev
例如
>sudovirsh dumpxml sles12 | -e xpath /domain/devices/hostdev Found 2 nodes: -- NODE -- <hostdev mode="subsystem" type="pci" managed="yes"> <driver name="xen" /> <source> <address domain="0x0000" bus="0x0a" slot="0x10" function="0x1" /> </source> <address type="pci" domain="0x0000" bus="0x00" slot="0x0a" function="0x0" /> </hostdev> -- NODE -- <hostdev mode="subsystem" type="pci" managed="yes"> <driver name="xen" /> <source> <address domain="0x0000" bus="0x0a" slot="0x10" function="0x2" /> </source> <address type="pci" domain="0x0000" bus="0x00" slot="0x0b" function="0x0" /> </hostdev>
<interface type='hostdev'> 附加的 SR-IOV 设备对于通过 <interface type='hostdev'> 附加到 VM 主机服务器的 SR-IOV 设备,您需要使用不同的 XPath 查询
virsh dumpxml VMGUEST_NAME | xpath -e /domain/devices/interface/@type
存储设备在 disk 元素中定义。通常的 disk 元素支持几个属性。以下两个属性是最重要的
type 属性描述虚拟磁盘设备的来源。有效值是 file、block、dir、network 或 volume。
device 属性显示磁盘如何在 VM Guest OS 中公开。例如,可能的值包括 floppy、disk、cdrom 等。
以下子元素是最重要的
driver 包含驱动程序和总线。这些由 VM Guest 用于处理新的磁盘设备。
target 元素包含 VM Guest 中显示的新磁盘的设备名称。它还包含可选的 bus 属性,该属性定义了新磁盘应在其上运行的公交类型。
以下过程显示了如何将存储设备添加到 VM Guest
编辑现有 VM Guest 的配置
>sudovirsh edit sles15
将 disk 元素与属性 type 和 device 放在 disk 元素内
<disk type='file' device='disk'>
指定 driver 元素并使用默认值
<driver name='qemu' type='qcow2'/>
创建磁盘映像作为新虚拟磁盘设备的来源
>sudoqemu-img create -f qcow2 /var/lib/libvirt/images/sles15.qcow2 32G
添加磁盘源的路径
<source file='/var/lib/libvirt/images/sles15.qcow2'/>
定义 VM Guest 中的目标设备名称以及磁盘应在其上运行的公交
<target dev='vda' bus='virtio'/>
重新启动您的 VM
>sudovirsh start sles15
您的新存储设备应在 VM Guest OS 中可用。
libvirt 根据 VM Guest 使用的虚拟设备的类型自动管理控制器。如果 VM Guest 包含 PCI 和 SCSI 设备,则会自动创建和管理 PCI 和 SCSI 控制器。 libvirt 还模拟特定于超visor 的控制器,例如,KVM Guest 的 virtio-serial 控制器或 Xen Guest 的 xenbus 控制器。虽然默认控制器及其配置通常很好,但在某些情况下,可能需要手动调整控制器或其属性。例如,virtio-serial 控制器可能需要更多端口,或者 xenbus 控制器可能需要更多内存或更多虚拟中断。
xenbus 控制器是独一无二的,因为它充当所有 Xen 准虚拟设备的控制器。如果 VM Guest 具有许多磁盘和/或网络设备,则控制器可能需要更多内存。Xen 的 max_grant_frames 属性设置了为每个 VM Guest 分配给 xenbus 控制器的 grant 帧(或共享内存块)的数量。
在大多数情况下,默认值 32 就足够了,但具有大量 I/O 设备和 I/O 密集型工作负载的 VM Guest 可能会因为 grant 帧耗尽而遇到性能问题。 xen-diag 可以检查 dom0 和您的 VM Guest 的当前和最大 max_grant_frames 值。VM Guest 必须正在运行
>sudovirsh list Id Name State -------------------------------- 0 Domain-0 running 3 sle15sp1 running>sudoxen-diag gnttab_query_size 0 domid=0: nr_frames=1, max_nr_frames=256>sudoxen-diag gnttab_query_size 3 domid=3: nr_frames=3, max_nr_frames=32
sle15sp1 guest 仅使用 32 个帧中的三个。如果您遇到性能问题以及指向内存不足的日志条目,请使用 virsh 增加该值。查找 Guest 配置中的 <controller type='xenbus'> 行,并添加 maxGrantFrames 控制元素
>sudovirsh edit sle15sp1 <controller type='xenbus' index='0' maxGrantFrames='40'/>
保存您的更改并重新启动 Guest。现在它应该显示您的更改
>sudoxen-diag gnttab_query_size 3 domid=3: nr_frames=3, max_nr_frames=40
与 maxGrantFrames 类似,xenbus 控制器还支持 maxEventChannels。事件通道类似于准虚拟中断,并且与 grant 帧一起构成准虚拟驱动程序的数据传输机制。它们也用于处理器间中断。具有大量 vCPU 和/或许多准虚拟设备的 VM Guest 可能需要增加默认最大值 1023。maxEventChannels 可以像 maxGrantFrames 一样进行更改
>sudovirsh edit sle15sp1 <controller type='xenbus' index='0' maxGrantFrames='128' maxEventChannels='2047'/>
有关更多信息,请参阅 libvirt Domain XML format 手册的 Controllers 部分,网址为 https://libvirt.org/formatdomain.html#elementsControllers。
在使用虚拟机管理器时,只能定义视频设备模型。分配的 VRAM 量或 2D/3D 加速只能在 XML 配置中更改。
编辑现有 VM Guest 的配置
>sudovirsh edit sles15
更改分配的 VRAM 大小
<video> <model type='vga' vram='65535' heads='1'> ... </model> </video>
通过查看虚拟机管理器中的数量来检查 VM 中的 VRAM 量是否已更改。
本节介绍如何使用 virsh 配置虚拟网络设备的特定方面。
在 https://libvirt.org/formatdomain.html#elementsDriverBackendOptions 中查找有关 libvirt 网络接口规范的更多详细信息。
多队列 virtio-net 功能通过允许 VM Guest 的虚拟 CPU 并行传输数据包来扩展网络性能。有关更多常规信息,请参阅 第 32.3.3 节,“使用多队列 virtio-net 扩展网络性能”。
要为特定的 VM Guest 启用多队列 virtio-net,请按照 第 14.1 节,“编辑 VM 配置” 中描述的方式编辑其 XML 配置,并如下修改其网络接口
<interface type='network'> [...] <model type='virtio'/> <driver name='vhost' queues='NUMBER_OF_QUEUES'/> </interface>
Macvtap 提供 VM Guest 虚拟接口与主机网络接口的直接连接。基于 macvtap 的接口扩展了 VM 主机服务器网络接口,并在同一以太网段上具有自己的 MAC 地址。通常,这用于使 Guest 和 VM 主机服务器都直接显示在连接到 VM 主机服务器的交换机上。
Macvtap 不能与已连接到 Linux 网桥的网络接口一起使用。在尝试创建 macvtap 接口之前,请从网桥中删除该接口。
在使用 macvtap 时,VM Guest 可以与其他的 VM Guest 以及网络上的其他外部主机进行通信。但它无法与运行 VM Guest 的 VM 主机服务器进行通信。这是 macvtap 的定义行为,因为 VM 主机服务器的物理以太网连接到 macvtap 网桥的方式。
libvirt 通过指定接口类型为 direct 来支持基于 macvtap 的虚拟网络接口。例如
<interface type='direct'> <mac address='aa:bb:cc:dd:ee:ff'/> <source dev='eth0' mode='bridge'/> <model type='virtio'/> </interface>
macvtap 设备的运行模式可以通过 mode 属性进行控制。以下列表显示了其可能的值以及每个值的描述
vepa:所有 VM Guest 数据包都发送到外部网桥。如果数据包的目的地是与发送数据包的 VM Host Server 位于同一台服务器上的 VM Guest,则 VEPA 功能的网桥会将数据包发送回 VM Host Server(如今的网桥通常不具备 VEPA 功能)。
bridge:如果数据包的目的地与数据包的来源位于同一 VM Host Server 上,则直接将数据包传递到目标 macvtap 设备。为了实现直接传递,源设备和目标设备都需要处于 bridge 模式。如果其中任何一个处于 vepa 模式,则需要一个 VEPA 功能的网桥。
private:所有数据包都发送到外部网桥,如果它们通过外部路由器或网关发送到同一 VM Host Server 上的目标 VM Guest,并且该设备将它们发送回 VM Host Server,则进行传递。如果源设备或目标设备处于 private 模式,则遵循此过程。
passthrough:一种特殊模式,赋予网络接口更多权限。所有数据包都转发到该接口,允许 virtio VM Guest 更改 MAC 地址或设置混杂模式以桥接该接口或在其之上创建 VLAN 接口。请注意,在 passthrough 模式下,网络接口不可共享。将接口分配给 VM Guest 会将其与 VM Host Server 断开连接。因此,SR-IOV 虚拟功能通常以 passthrough 模式分配给 VM Guest。
内存气球已成为 KVM 的默认选项。该设备显式添加到 VM Guest,因此无需在 VM Guest 的 XML 配置中添加此元素。如果您出于任何原因想在 VM Guest 中禁用内存气球,则需要将 model='none',如下所示
<devices> <memballoon model='none'/> </device>
libvirt 支持双头配置,以在多个监视器上显示 VM Guest 的视频输出。
Xen hypervisor 不支持双头配置。
在虚拟机运行时,验证 VM Guest 中是否安装了 xf86-video-qxl 包
> rpm -q xf86-video-qxl关闭 VM Guest,然后开始编辑其配置 XML,如 第 14.1 节,“编辑 VM 配置” 中所述。
验证虚拟显卡的模型是否为 “qxl”
<video> <model type='qxl' ... />
将显卡模型规范中的 heads 参数从默认值 1 增加到 2,例如
<video> <model type='qxl' ram='65536' vram='65536' vgamem='16384' heads='2' primary='yes'/> <alias name='video0'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> </video>
配置虚拟机使用 Spice 显示而不是 VNC
<graphics type='spice' port='5916' autoport='yes' listen='0.0.0.0'> <listen type='address' address='0.0.0.0'/> </graphics>
启动虚拟机,并使用 virt-viewer 连接到其显示,例如
> virt-viewer --connect qemu+ssh://USER@VM_HOST/system从 VM 列表中,选择您已修改配置的 VM,然后使用 确认。
在 VM Guest 中加载图形子系统 (Xorg) 后,选择 › › 以打开一个新窗口,显示第二个监视器的输出。
IBM Z 机器包含具有有用功能的加密硬件,例如随机数生成、数字签名生成或加密。KVM 允许将这些加密适配器专用于 guest 作为直通设备。这意味着 hypervisor 无法观察 guest 和设备之间的通信。
本节介绍如何将加密适配器和 IBM Z 主机上的域专用于 KVM guest。该过程包括以下基本步骤
屏蔽主机上默认驱动程序中的加密适配器和域。
加载 vfio-ap 驱动程序。
将加密适配器和域分配给 vfio-ap 驱动程序。
配置 guest 以使用加密适配器。
验证主机上是否加载了 vfio_ap 和 vfio_mdev 内核模块
> lsmod | grep vfio_如果其中任何一个未列出,请手动加载它,例如
>sudomodprobe vfio_mdev
在主机上创建一个新的 MDEV 设备,并验证是否已添加它
uuid=$(uuidgen)
$ echo ${uuid} | sudo tee /sys/devices/vfio_ap/matrix/mdev_supported_types/vfio_ap-passthrough/create
dmesg | tail
[...]
[272197.818811] iommu: Adding device 24f952b3-03d1-4df2-9967-0d5f7d63d5f2 to group 0
[272197.818815] vfio_mdev 24f952b3-03d1-4df2-9967-0d5f7d63d5f2: MDEV: group_id = 0标识您打算专用于 KVM guest 的主机逻辑分区上的设备
> ls -l /sys/bus/ap/devices/
[...]
lrwxrwxrwx 1 root root 0 Nov 23 03:29 00.0016 -> ../../../devices/ap/card00/00.0016/
lrwxrwxrwx 1 root root 0 Nov 23 03:29 card00 -> ../../../devices/ap/card00/在此示例中,它是卡 0 队列 16。为了与硬件管理控制台 (HMC) 配置匹配,您需要将 16 十六进制转换为 22 十进制。
屏蔽 zcrypt 使用中的适配器
> lszcrypt
CARD.DOMAIN TYPE MODE STATUS REQUEST_CNT
-------------------------------------------------
00 CEX5C CCA-Coproc online 5
00.0016 CEX5C CCA-Coproc online 5屏蔽适配器
> cat /sys/bus/ap/apmask
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
echo -0x0 | sudo tee /sys/bus/ap/apmask
0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff屏蔽域
> cat /sys/bus/ap/aqmask
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
echo -0x0 | sudo tee /sys/bus/ap/aqmask
0xfffffdffffffffffffffffffffffffffffffffffffffffffffffffffffffffff将适配器 0 和域 16(十进制 22)分配给 vfio-ap
>sudoecho +0x0 > /sys/devices/vfio_ap/matrix/${uuid}/assign_adapter>echo +0x16 | sudo tee /sys/devices/vfio_ap/matrix/${uuid}/assign_domain>echo +0x16 | sudo tee /sys/devices/vfio_ap/matrix/${uuid}/assign_control_domain
验证您配置的矩阵
> cat /sys/devices/vfio_ap/matrix/${uuid}/matrix
00.0016创建新的 VM(请参阅 第 9 章,Guest 安装)并等待其初始化,或使用现有的 VM。在两种情况下,请确保 VM 已关闭。
更改其配置以使用 MDEV 设备
>sudovirsh edit VM_NAME [...] <hostdev mode='subsystem' type='mdev' model='vfio-ap'> <source> <address uuid='24f952b3-03d1-4df2-9967-0d5f7d63d5f2'/> </source> </hostdev> [...]
重新启动 VM
>sudovirsh reboot VM_NAME
登录到 guest 并验证适配器是否存在
> lszcrypt
CARD.DOMAIN TYPE MODE STATUS REQUEST_CNT
-------------------------------------------------
00 CEX5C CCA-Coproc online 1
00.0016 CEX5C CCA-Coproc online 1虚拟化组件的安装细节请参见 第 6 章,虚拟化组件安装。
vfio_ap 架构的细节请参见 https://linuxkernel.org.cn/doc/Documentation/s390/vfio-ap.txt。
概述以及详细过程请参见 https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1787405。
VFIO 介导设备 (MDEVs) 的架构细节请参见 https://linuxkernel.org.cn/doc/html/latest/driver-api/vfio-mediated-device.html。