跳到内容跳到页面导航:上一页 [access key p]/下一页 [access key n]
documentation.suse.com / SUSE Linux Enterprise Server 文档 / 虚拟化指南 / 使用 libvirt 管理虚拟机 / 使用 virsh 配置虚拟机
适用范围 SUSE Linux Enterprise Server 15 SP2

15 使用 virsh 配置虚拟机

您也可以在命令行上使用 virsh 来配置虚拟机 (VM),以此替代虚拟机管理器。使用 virsh 可以控制 VM 的状态、编辑 VM 的配置,甚至将 VM 迁移到另一台主机。下列章节介绍如何使用 virsh 来管理 VM。

15.1 编辑 VM 配置

VM 配置储存在 /etc/libvirtd/qemu/ 中的某个 XML 文件内,其内容类似如下示例:

例 15.1︰ 示例 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-i440fx-2.11'>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 的配置,请检查它是否处于脱机状态:

tux > sudo virsh list --inactive

如果您的 VM Guest 在此列表中,则表明您可以放心地编辑其配置:

tux > sudo virsh edit NAME_OF_VM_GUEST

在保存更改之前,virsh 会根据 RelaxNG 纲要验证您的输入。

15.2 更改计算机类型

使用 virt-install 工具安装时,VM Guest 的计算机类型默认为 pc-i440fx。计算机类型储存在 VM Guest 配置文件中的 type 元素内:

<type arch='x86_64' machine='pc-i440fx-2.3'>hvm</type>

下面的过程示范了如何将此值更改为 q35 计算机类型。值 q35 表示一种 Intel* 芯片组,其中包括 PCIe,最多支持 12 个 USB 端口,并支持 SATAIOMMU

过程 15.1︰ 更改计算机类型
  1. 检查您的 VM Guest 是否处于非活动状态:

    tux > sudo virsh list --inactive
    Id    Name                           State
    ----------------------------------------------------
    -     sles15                         shut off
  2. 编辑此 VM Guest 的配置:

    tux > sudo virsh edit sles15
  3. machine 属性的值替换为 pc-q35-2.0

    <type arch='x86_64' machine='pc-q35-2.0'>hvm</type>
  4. 重启动 VM Guest:

    tux > sudo virsh start sles15
  5. 检查计算机类型是否已更改。登录到 VM Guest 并运行以下命令:

    tux > sudo dmidecode | grep Product
    Product 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。这样就可以利用计算机定义中最近的更新和更正,并确保将来可以更好地兼容。

15.3 配置超级管理程序功能

libvirt 可自动启用一组默认的超级管理程序功能(这些功能在大多数情况下已够用),同时还允许按需启用和禁用功能。例如,Xen 不支持默认启用 PCI 直通。必须使用直通设置来启用此功能。可以使用 virsh 来配置超级管理程序功能。请查看 VM Guest 配置文件中的 <features> 元素,并根据需要调整各项功能。沿用 Xen 直通示例:

tux > sudo virsh edit sle15sp1
 <features>
    <xen>
      <passthrough/>
    </xen>
 </features>

保存更改并重启动 VM Guest。

有关详细信息,请参见 https://libvirt.org/formatdomain.html#elementsFeatures 上 libvirt 的《Domain XML format》(域 XML 格式)手册中的“Hypervisor features”(超级管理程序功能)一节。

15.4 配置 CPU 分配

分配的 CPU 数量储存在 /etc/libvirt/qemu/ 下 VM Guest XML 配置文件中的 vcpu 元素内:

<vcpu placement='static'>1</vcpu>

在此示例中,只为 VM Guest 分配了一个 CPU。下面的过程说明如何更改分配给 VM Guest 的 CPU 数量:

  1. 检查您的 VM Guest 是否处于非活动状态:

    tux > sudo virsh list --inactive
    Id    Name                           State
    ----------------------------------------------------
    -     sles15                         shut off
  2. 编辑现有 VM Guest 的配置:

    tux > sudo virsh edit sles15
  3. 更改分配的 CPU 数量:

    <vcpu placement='static'>2</vcpu>
  4. 重启动 VM Guest:

    tux > sudo virsh start sles15
  5. 检查 VM 中的 CPU 数量是否已更改。

    tux > sudo virsh vcpuinfo sled15
    VCPU:           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

15.5 更改引导选项

VM Guest 的引导菜单包含在 os 元素中,其内容通常如下所示:

<os>
  <type>hvm</type>
  <loader>readonly='yes' secure='no' type='rom'/>/usr/lib/xen/boot/hvmloader</loader>
  <nvram template='/usr/share/OVMF/OVMF_VARS.fd'/>/var/lib/libvirt/nvram/guest_VARS.fd</nvram>
  <boot dev='hd'/>
  <boot dev='cdrom'/>
  <bootmenu enable='yes' timeout='3000'/>
  <smbios mode='sysinfo'/>
  <bios useserial='yes' rebootTimeout='0'/>
  </os>

此示例中有两个可用设备: hdcdrom 。配置还会反映实际引导顺序,因此 cdrom 先于 hd 引导。

15.5.1 更改引导顺序

VM Guest 的引导顺序通过 XML 配置文件中的设备顺序来表示。由于设备可以互换,因此可以更改 VM Guest 的引导顺序。

  1. 打开 VM Guest 的 XML 配置。

    tux > sudo virsh edit sles15
  2. 更改可引导设备的顺序。

    ...
    <boot dev='cdrom'/>
    <boot dev='hd'/>
    ...
  3. 通过查看 VM Guest 的 BIOS 中的引导菜单来检查引导顺序是否已更改。

15.5.2 使用直接内核引导

使用直接内核引导可以从主机上储存的内核和 initrd 引导。在 kernelinitrd 元素中设置这两个文件的路径:

<os>
    ...
  <kernel>/root/f8-i386-vmlinuz</kernel>
  <initrd>/root/f8-i386-initrd</initrd>
    ...
<os>

要启用直接内核引导,请执行以下操作:

  1. 打开 VM Guest 的 XML 配置:

    tux > sudo virsh edit sles15
  2. os 元素中,添加 kernel 元素以及主机上内核文件的路径:

    ...
    <kernel>/root/f8-i386-vmlinuz</kernel>
    ...
  3. 添加 initrd 元素以及主机上 initrd 文件的路径:

    ...
    <initrd>/root/f8-i386-initrd</initrd>
    ...
  4. 启动 VM 以从新内核引导:

    tux > sudo virsh start sles15

15.6 配置内存分配

您还可以使用 virsh 来配置分配给 VM Guest 的内存量。此值储存在 memory 元素中。请遵循以下步骤:

  1. 打开 VM Guest 的 XML 配置:

    tux > sudo virsh edit sles15
  2. 搜索 memory 元素并设置分配的 RAM 量:

    ...
    <memory unit='KiB'>524288</memory>
    ...
  3. 运行以下命令检查 VM 中分配的 RAM 量:

    tux > cat /proc/meminfo

15.7 添加 PCI 设备

要使用 virsh 将 PCI 设备指派到 VM Guest,请执行以下步骤:

  1. 标识要指派到 VM Guest 的主机 PCI 设备。在下面的示例中,我们要将一块 DEC 网卡指派到 Guest:

    tux > sudo lspci -nn
    [...]
    03:07.0 Ethernet controller [0200]: Digital Equipment Corporation DECchip \
    21140 [FasterNet] [1011:0009] (rev 22)
    [...]

    请记下设备 ID(在本例中为 03:07.0)。

  2. 使用 virsh nodedev-dumpxml ID 收集有关设备的详细信息。要获取 ID,请将设备 ID (03:07.0) 中的冒号和句点替换为下划线。使用 pci_0000_ 作为结果的前缀:pci_0000_03_07_0.

    tux > sudo virsh 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 代码)。

  3. 从主机系统上分离设备,然后将其挂接到 VM Guest:

    tux > sudo virsh nodedev-detach pci_0000_03_07_0
      Device pci_0000_03_07_0 detached
    提示
    提示:多功能 PCI 设备

    使用不支持 FLR(功能级重设置)或 PM(电源管理)重设置的多功能 PCI 设备时,需要从 VM 主机服务器分离其所有功能。出于安全原因,整个设备都必须重设置。如果 VM 主机服务器或其他 VM Guest 仍在使用设备的某个功能,libvirt 将拒绝指派该设备。

  4. 将域、总线、插槽和功能值从十进制转换为十六进制。在本示例中,域 = 0,总线 = 3,插槽 = 7,功能 = 0。确保按正确顺序插入值:

    tux > 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'/>
  5. 在您的域上运行 virsh edit,并使用上一步的结果在 <devices> 部分添加以下设备项:

    <hostdev mode='subsystem' type='pci' managed='yes'>
      <source>
        <address domain='0x0' bus='0x03' slot='0x07' function='0x0'/>
      </source>
    </hostdev>
    提示
    提示:受管模式与不受管模式的比较

    libvirt 可识别 PCI 设备的两种处理模式:受管不受管。在受管模式下,libvirt 将处理从现有驱动程序取消绑定设备(如果需要)、重设置设备、在启动域之前将设备绑定到 vfio-pci 等事项的所有细节。对于受管设备,当终止域或者从域中去除设备时,libvirt 会将设备从 vfio-pci 取消绑定,然后将其重新绑定到原始驱动程序。如果设备不受管,则用户必须确保在将设备指派到域之前以及在设备不再由域使用之后,所有这些设备管理方面的操作都已完成。

    在上面的示例中,managed='yes' 选项表示设备是受管的。要将设备切换为不受管模式,请在上面的列表中设置 managed='no'。如果这样做,需使用 virsh nodedev-detachvirsh nodedev-reattach 命令处理相关的驱动程序。在启动 VM Guest 之前,需运行 virsh nodedev-detach pci_0000_03_07_0 以从主机分离设备。如果 VM Guest 未运行,您可以运行 virsh nodedev-reattach pci_0000_03_07_0,使设备可供主机使用。

  6. 关闭 VM Guest,并禁用 SELinux(如果它正在主机上运行)。

    tux > sudo setsebool -P virt_use_sysfs 1
  7. 启动 VM Guest 以使指派的 PCI 设备可用:

    tux > sudo virsh start sles15

15.8 添加 USB 设备

要使用 virsh 将 USB 设备指派到 VM Guest,请执行以下步骤:

  1. 标识要指派到 VM Guest 的主机 USB 设备:

    tux > sudo lsusb
    [...]
    Bus 001 Device 003: ID 0557:2221 ATEN International Co., Ltd Winbond Hermon
    [...]

    记下供应商 ID 和产品 ID。在本示例中,供应商 ID 为 0557,产品 ID 为 2221

  2. 在您的域上运行 virsh edit,并使用上一步获得的值在 <devices> 部分添加以下设备项:

    <hostdev mode='subsystem' type='usb'>
      <source startupPolicy='optional'>
       <vendor id='0557'/>
       <product id='2221'/>
      </source>
    </hostdev>
    提示
    提示:供应商/产品或设备地址

    如果不使用 <供应商/><产品/> ID 来定义主机设备,可以使用 <address/> 元素,具体请参见第 15.7 节 “添加 PCI 设备”中的主机 PCI 设备相关内容。

  3. 关闭 VM Guest,并禁用 SELinux(如果它正在主机上运行):

    tux > sudo setsebool -P virt_use_sysfs 1
  4. 启动 VM Guest 以使指派的 PCI 设备可用:

    tux > sudo virsh start sles15

15.9 添加 SR-IOV 设备

支持单根 I/O 虚拟化 (SR-IOV) 的 PCIe 设备能够复制其资源,因此它们看上去像是多个设备。可将其中的每个伪设备指派到 VM Guest。

SR-IOV 是外围部件互连专业组 (PCI-SIG) 联盟制定的行业规范。其中介绍了物理功能 (PF) 和虚拟功能 (VF)。PF 是用于管理和配置设备的完整 PCIe 功能。PF 还可以移动数据。VF 在配置和管理方面的作用有所欠缺 — 它们只能移动数据,提供的配置功能有限。由于 VF 不包括所有的 PCIe 功能,主机操作系统或超级管理程序必须支持 SR-IOV 才能访问和初始化 VF。理论上 VF 的最大数量为每台设备 256 个(因此,对于双端口以太网卡,最大数量为 512 个)。在实际环境中,此最大数量要少得多,因为每个 VF 都会消耗资源。

15.9.1 要求

要使用 SR-IOV,必须符合以下要求:

  • 支持 SR-IOV 的网卡(从 SUSE Linux Enterprise Server 15 开始,只有网卡支持 SR-IOV

  • 支持硬件虚拟化的 AMD64/Intel 64 主机(AMD-V 或 Intel VT-x),有关详细信息,请参见第 7.3 节 “KVM 硬件要求”

  • 支持设备指派的芯片组(AMD-Vi 或 Intel VT-d

  • libvirt 0.9.10 或更高版本

  • 主机系统上必须装载并配置 SR-IOV 驱动程序

  • 符合重要:VFIO 和 SR-IOV 的要求中所列要求的主机配置

  • 要指派到 VM Guest 的 VF 的 PCI 地址列表

提示
提示:检查设备是否支持 SR-IOV

可以通过运行 lspci 从设备的 PCI 描述符中获取有关该设备是否支持 SR-IOV 的信息。支持 SR-IOV 的设备会报告类似如下的功能:

Capabilities: [160 v1] Single Root I/O Virtualization (SR-IOV)
注意
注意:在创建 VM Guest 时添加 SR-IOV 设备

您必须已按照第 15.9.2 节 “装载和配置 SR-IOV 主机驱动程序”中所述配置 VM 主机服务器,才可在最初设置 VM Guest 时向其添加 SR-IOV 设备。

15.9.2 装载和配置 SR-IOV 主机驱动程序

要访问和初始化 VF,需在主机系统上装载一个支持 SR-IOV 的驱动程序。

  1. 在装载驱动程序之前,请运行 lspci 来确保可正常检测到网卡。下面的示例显示了双端口 Intel 82576NS 网卡的 lspci 输出:

    tux > sudo /sbin/lspci | grep 82576
    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)
    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 中的设置。

  2. 运行 lsmod 来检查是否已装载 SR-IOV 驱动程序。在下面的示例中,用于检查是否装载了 Intel 82576NS 网卡的 igb 驱动程序的命令返回了一条结果。这表示已装载该驱动程序。如果该命令未返回任何结果,则表示未装载该驱动程序。

    tux > sudo /sbin/lsmod | egrep "^igb "
    igb                   185649  0
  3. 如果已装载驱动程序,请跳过以下步骤。如果尚未装载 SR-IOV 驱动程序,需要先去除非 SR-IOV 驱动程序,然后再装载新驱动程序。使用 rmmod 卸载驱动程序。下面的示例会卸载 Intel 82576NS 网卡的非 SR-IOV 驱动程序:

    tux > sudo /sbin/rmmod igbvf
  4. 随后使用 modprobe 命令装载 SR-IOV 驱动程序 — 必须指定 VF 参数 (max_vfs):

    tux > sudo /sbin/modprobe igb max_vfs=8

或者,您也可以通过 SYSFS 装载驱动程序:

  1. 通过列出以太网设备确定物理 NIC 的 PCI ID:

    tux > sudo lspci | grep Eth
    06:00.0 Ethernet controller: Emulex Corporation OneConnect NIC (Skyhawk) (rev 10)
    06:00.1 Ethernet controller: Emulex Corporation OneConnect NIC (Skyhawk) (rev 10)
  2. 要启用 VF,请向 sriov_numvfs 参数回送需要装载的 VF 数量:

    tux > sudo echo 1 > /sys/bus/pci/devices/0000:06:00.1/sriov_numvfs
  3. 校验是否已装载 VF NIC:

    tux > sudo lspci | grep Eth
    06: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)
  4. 获取可用 VF 的最大数量:

    tux > sudo lspci -vvv -s 06:00.1 | grep 'Initial VFs'
                           Initial VFs: 32, Total VFs: 32, Number of VFs: 0,
    Function Dependency Link: 01
  5. 创建 /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
  6. 在启动 VM 之前,需要创建指向 /etc/init.d/after.local 脚本(用于分离 NIC)的另一个服务文件 (after-local.service)。否则 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
  7. 将此文件复制到 /etc/systemd/system

    #! /bin/sh
    # ...
    virsh nodedev-detach pci_0000_06_08_0

    将它另存为 /etc/init.d/after.local

  8. 重引导计算机,然后根据本过程的第一步所述,重新运行 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)
    [...]

15.9.3 将 VF 网络设备添加到 VM Guest

在 VM 主机服务器上正确设置 SR-IOV 硬件后,便可将 VF 添加到 VM Guest。为此,您需要先收集一些数据。

过程 15.2︰ 将 VF 网络设备添加到现有 VM Guest

下面的过程使用的是示例数据。请务必将其替换为您设置中的相应数据。

  1. 使用 virsh nodedev-list 命令获取您要指派的 VF 的 PCI 地址及其对应的 PF。第 15.9.2 节 “装载和配置 SR-IOV 主机驱动程序”中所示的 lspci 输出中的数字值(例如 01:00.004:00.1)已经过转换:添加了前缀“pci_0000_”并将冒号和句点替换为下划线。因此,lspci 列出的 PCI ID“04:00.0”会被 virsh 列为“pci_0000_04_00_0”。下面的示例列出了 Intel 82576NS 网卡的第二个端口的 PCI ID:

    tux > sudo virsh 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。

  2. 对您要添加的 VF 的 PCI ID 运行以下 virsh nodedev-dumpxml 命令:

    tux > sudo virsh 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>

  3. 创建一个临时 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>

    1

    VF 的 MAC 地址不固定;每次重引导主机后,MAC 地址都会改变。如果以传统方式使用 hostdev添加网络设备,每次重引导主机后都需要重新配置 VM Guest 的网络设备,因为 MAC 地址会改变。为了避免此类问题,libvirt 引入了 hostdev 值,该值可以在指派设备之前设置网络特定的数据。

    2

    请在此处指定上一步中获取的数据。

  4. 如果设备已挂接到主机,则无法将它挂接到 VM Guest。要使该设备可供 Guest 使用,请先将它从主机分离:

    tux > sudo virsh nodedev-detach pci_0000_04_10_0
  5. 将 VF 接口添加到现有 VM Guest:

    tux > sudo virsh 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 中。

  6. 要分离 VF 接口,请使用 virsh detach-device 命令,该命令也接受上面所列的选项。

15.9.4 动态分配池中的 VF

如果您按照第 15.9.3 节 “将 VF 网络设备添加到 VM Guest”中所述以静态方式在 VM Guest 的配置中定义了 VF 的 PCI 地址,此类 Guest 将很难迁移到另一台主机。该主机必须在 PCI 总线上的相同位置具有相同的硬件,否则每次启动之前都必须修改 VM Guest 配置。

另一种方法是使用一个包含 SR-IOV 设备所有 VF 的设备池创建 libvirt 网络。之后,VM Guest 将引用此网络,每次 VM Guest 启动时,系统都会向它动态分配单个 VF。当 VM Guest 停止时,该 VF 将返回到池中,可供其他 Guest 使用。

15.9.4.1 在 VM 主机服务器上使用 VF 池定义网络

下面的网络定义示例为 SR-IOV 设备创建了一个包含所有 VF 的池,该设备的物理功能 (PF) 位于主机中的网络接口 eth0 上:

<network>
  <name>passthrough</name>
    <forward mode='hostdev' managed='yes'>
      <pf dev='eth0'/>
    </forward>
  </network>

要在主机上使用此网络,请将上述代码保存到文件(例如 /tmp/passthrough.xml)中,然后执行以下命令。请记得将 eth0 替换为 SR-IOV 设备的 PF 的实际网络接口名称:

tux > sudo virsh net-define /tmp/passthrough.xml
tux > sudo virsh net-autostart passthrough
tux > sudo virsh net-start passthrough

15.9.4.2 将 VM Guest 配置为使用池中的 VF

下面的 VM Guest 设备接口定义示例使用第 15.9.4.1 节 “在 VM 主机服务器上使用 VF 池定义网络”中为 SR-IOV 设备创建的池中的某个 VF。Guest 首次启动时,libvirt 会自动派生与该 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>

15.10 列出挂接的设备

尽管 virsh 中没有任何机制可列出 VM 主机服务器中已挂接到其 VM Guest 的所有设备,但您可以通过运行以下命令列出已挂接到特定 VM Guest 的所有设备:

virsh dumpxml VMGUEST_NAME | xpath -e /domain/devices/hostdev

例如:

tux > sudo virsh 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

15.11 配置储存设备

储存设备定义于 disk 元素中。常规的 disk 元素支持多个属性。下面是两个最重要的属性:

  • 属性 type 描述虚拟磁盘设备的来源。有效值为 fileblockdirnetworkvolume

  • 属性 device 指示如何向 VM Guest 操作系统公开磁盘。例如,可能的值可能包括 floppydiskcdrom 及其他。

下面是最重要的子元素:

  • driver 包含驱动程序和总线。VM Guest 使用驱动程序和总线来操作新磁盘设备。

  • 元素 target 包含新磁盘显示在 VM Guest 中时所用的设备名称。它还包含可选的总线属性,该属性定义用于操作新磁盘的总线的类型。

下面的过程说明如何将储存设备添加到 VM Guest:

  1. 编辑现有 VM Guest 的配置:

    tux > sudo virsh edit sles15
  2. disk 元素中添加 disk 元素以及 typedevice属性:

    <disk type='file' device='disk'>
  3. 指定 driver 元素并使用默认值:

    <driver name='qemu' type='qcow2'/>
  4. 创建一个磁盘映像,用作新虚拟磁盘设备的来源:

    tux > sudo qemu-img create -f qcow2 /var/lib/libvirt/images/sles15.qcow2 32G
  5. 添加磁盘来源的路径:

    <source file='/var/lib/libvirt/images/sles15.qcow2'/>
  6. 定义 VM Guest 中的目标设备名以及用于操作磁盘的总线:

    <target dev='vda' bus='virtio'/>
  7. 重启动您的 VM:

    tux > sudo virsh start sles15

现在,新储存设备在 VM Guest 操作系统中应该可供使用。

15.12 配置控制器设备

一般情况下,libvirt 会根据 VM Guest 使用的虚拟设备类型自动管理控制器。如果 VM Guest 包含 PCI 和 SCSI 设备,libvirt 将自动创建并管理 PCI 和 SCSI 控制器。libvirt 还可为特定于超级管理程序的控制器(例如 KVM VM Guest 的 virtio-serial 控制器,或 Xen VM Guest 的 xenbus 控制器)建模。尽管默认控制器及其配置在一般情况下都可满足需求,但在某些用例中,需要手动调整控制器或其属性。例如,virtio-serial 控制器可能需要更多端口,或者 xenbus 控制器可能需要更多内存或更多虚拟中断。

Xenbus 控制器的独特之处在于,它充当着所有 Xen 半虚拟设备的控制器。如果 VM Guest 包含许多磁盘和/或网络设备,则控制器可能需要更多内存。Xen 的 max_grant_frames 属性设置要将多少授权帧或共享内存块分配给每个 VM Guest 的 xenbus 控制器。

默认值 32 在大多数情况下已够用,但包含大量 I/O 设备的 VM Guest 以及 I/O 密集型工作负载可能会由于授权帧耗尽而发生性能问题。可以使用 xen-diag 来检查 dom0 与 VM Guest 的当前和最大 max_grant_frames 值。VM Guest 必须正在运行:

tux > sudo virsh list
 Id   Name             State
--------------------------------
 0    Domain-0         running
 3    sle15sp1         running

 tux > sudo xen-diag gnttab_query_size 0
domid=0: nr_frames=1, max_nr_frames=256

tux > sudo xen-diag gnttab_query_size 3
domid=3: nr_frames=3, max_nr_frames=32

sle15sp1 Guest 仅使用了 32 个帧中的 3 个。如果您发现了性能问题并且有日志项指出帧数不足,请使用 virsh 增大该值。查看 Guest 配置文件中的 <controller type='xenbus'> 行,并添加 maxGrantFrames 控制元素:

tux > sudo virsh edit sle15sp1
 <controller type='xenbus' index='0' maxGrantFrames='40'/>

保存更改并重启动 Guest。现在,xen-diag 命令应该会显示您的更改:

tux > sudo xen-diag gnttab_query_size 3
domid=3: nr_frames=3, max_nr_frames=40

与 maxGrantFrames 类似,xenbus 控制器也支持 maxEventChannels。事件通道类似于半虚拟中断,它们与授权帧共同构成半虚拟驱动程序的数据传输机制。它们还用于处理器间的中断。包含大量 vCPU 和/或许多半虚拟设备的 VM Guest 可能需要增大最大默认值 1023。可以像更改 maxGrantFrames 那样更改 maxEventChannels:

tux > sudo virsh edit sle15sp1
 <controller type='xenbus' index='0' maxGrantFrames='128' maxEventChannels='2047'/>

有关详细信息,请参见 https://libvirt.org/formatdomain.html#elementsControllers 上 libvirt 的《Domain XML format》(域 XML 格式)手册中的“Controllers”(控制器)一节。

15.13 配置视频设备

使用虚拟机管理器时,只能定义视频设备型号。只能在 XML 配置中更改分配的 VRAM 量或 2D/3D 加速。

15.13.1 更改分配的 VRAM 量

  1. 编辑现有 VM Guest 的配置:

    tux > sudo virsh edit sles15
  2. 更改分配的 VRAM 大小:

    <video>
    <model type='vga' vram='65535' heads='1'>
    ...
    </model>
    </video>
  3. 通过查看虚拟机管理器中的数量来检查 VM 中的 VRAM 量是否已更改。

15.13.2 更改 2D/3D 加速状态

  1. 编辑现有 VM Guest 的配置:

    tux > sudo virsh edit sles15
  2. 要启用/禁用 2D/3D 加速,请相应地更改 accel3daccel2d 的值:

    <video>
    <acceleration accel3d='yes' accel2d='no'>
    ...
    </model>
    </video>
提示
提示:启用 2D/3D 加速

只有 vbox 视频设备支持 2D/3D 加速。无法在其他视频设备上启用此功能。

15.14 配置网络设备

本节介绍如何使用 virsh 配置虚拟网络设备的特定方面。

https://libvirt.org/formatdomain.html#elementsDriverBackendOptions 中提供了有关 libvirt 网络接口规范的更多细节。

15.14.1 使用多队列 virtio-net 提升网络性能

多队列 virtio-net 功能允许 VM Guest 的虚拟 CPU 并行传输包,因此可以提升网络性能。有关更多一般信息,请参见第 30.3.3 节 “使用多队列 virtio-net 提升网络性能”

要为特定的 VM Guest 启用多队列 virtio-net,请遵照第 15.1 节 “编辑 VM 配置”中所述编辑其 XML 配置,并按如下所示修改其网络接口:

<interface type='network'>
 [...]
 <model type='virtio'/>
 <driver name='vhost' queues='NUMBER_OF_QUEUES'/>
</interface>

15.15 使用 Macvtap 共享 VM 主机服务器网络接口

使用 Macvtap 可将 VM Guest 虚拟接口直接挂接到主机网络接口。基于 macvtap 的接口扩展了 VM 主机服务器网络接口,它在相同以太网段上有自己的 MAC 地址。通常,使用此功能是为了使 VM Guest 和 VM 主机服务器都直接显示在 VM 主机服务器连接的交换机上。

注意
注意:Macvtap 不能与 Linux 网桥搭配使用

Macvtap 不能与已连接到 Linux 网桥的网络接口搭配使用。在尝试创建 macvtap 接口之前,请去除网桥中的接口。

注意
注意:使用 Macvtap 实现 VM Guest 到 VM 主机服务器的通讯

使用 macvtap 时,一个 VM Guest 可与其他多个 VM Guest 通讯,并可与网络上的其他外部主机通讯。但是,该 VM Guest 无法与用于运行它的 VM 主机服务器通讯。这是规定的 macvtap 行为,原因与 VM 主机服务器物理以太网挂接到 macvtap 网桥的方式有关。从 VM Guest 进入该网桥并转发到物理接口的流量无法回弹到 VM 主机服务器的 IP 堆栈。同样,来自 VM 主机服务器 IP 堆栈并发送到物理接口的流量无法回弹到 macvtap 网桥以转发到 VM Guest。

libvirt 通过指定接口类型 direct 支持基于 macvtap 的虚拟网络接口。例如:

<interface type='direct'>
   <mac address='aa:bb:cc:dd:ee:ff'/>
   <source dev='eth0' mode='bridge'/>
   <model type='virtio'/>
   </interface>

可以使用 mode 属性控制 macvtap 设备的操作模式。下面的列表显示了该属性的可能的值以及每个值的说明:

  • vepa:将所有 VM Guest 包都发送到外部网桥。如果包的目标是某个 VM Guest,而该 VM Guest 所在的 VM 主机服务器与包的来源服务器相同,那么这些包将由支持 VEPA 的网桥(现今的网桥通常都不支持 VEPA)发回到该 VM 主机服务器。

  • bridge:将其目标与来源为同一 VM 主机服务器的包直接递送到目标 macvtap 设备。来源和目标设备需处于 bridge 模式才能直接递送。如果其中一个设备处于 vepa 模式,则需要使用支持 VEPA 的网桥。

  • private:将所有包都发送到外部网桥;仅当通过外部路由器或网关发送所有包,并且设备会将其发回到 VM 主机服务器时,才将所有包递送到同一 VM 主机服务器上的目标 VM Guest。如果来源或目标设备处于 private 模式,将遵循此过程。

  • passthrough:可为网络接口提供更强大的能力的一种特殊模式。将所有包转发到接口,并允许 virtio VM Guest 更改 MAC 地址或设置混杂模式,以桥接该接口或在该接口上创建 VLAN 接口。请注意,在 passthrough 模式下,网络接口不可共享。将某个接口指派到 VM Guest 会使其与 VM 主机服务器断开连接。出于此原因,在 passthrough 模式下常常会将 SR-IOV 虚拟功能指派到 VM Guest。

15.16 禁用内存气球设备

内存气球已成为 KVM 的默认选项。设备将显式添加到 VM Guest,因此您无需在 VM Guest 的 XML 配置中添加此元素。但是,如果您出于任何原因想要在 VM Guest 中禁用内存气球,需按如下所示设置 model='none'

<devices>
   <memballoon model='none'/>
</device>

15.17 配置多个监视器(双头)

libvirt 支持使用双头配置在多个监视器上显示 VM Guest 的视频输出。

重要
重要:不受 Xen 支持

Xen 超级管理程序不支持双头配置。

过程 15.3︰ 配置双头
  1. 当虚拟机正在运行时,请校验 xf86-video-qxl 软件包是否已安装在 VM Guest 中:

    tux > rpm -q xf86-video-qxl
  2. 关闭 VM Guest,并按照第 15.1 节 “编辑 VM 配置”中所述开始编辑其 XML 配置。

  3. 校验虚拟显卡的型号是否为“qxl”:

    <video>
     <model type='qxl' ... />
  4. 将显卡型号规格中的 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>
  5. 将虚拟机配置为使用 Spice 显示器而不是 VNC:

    <graphics type='spice' port='5916' autoport='yes' listen='0.0.0.0'>
     <listen type='address' address='0.0.0.0'/>
    </graphics>
  6. 启动虚拟机并使用 virt-viewer 连接到其显示器,例如:

    tux > virt-viewer --connect qemu+ssh://USER@VM_HOST/system
  7. 在 VM 列表中,选择您已修改了其配置的 VM,并单击连接确认。

  8. 在 VM Guest 中装载图形子系统 (Xorg) 后,选择视图 › 显示器 › 显示器 2 打开一个新窗口,其中会显示第二个监视器的输出。