CPU 模型

Nova 允许您配置暴露给实例的虚拟 CPU 的特性。CPU 特性的组合统称为CPU 模型。使用场景包括

  • 通过暴露主机 CPU 的新特性到访客系统,以最大化实例的性能

  • 为了确保所有机器上的一致默认行为,消除对系统默认值的依赖。

要配置虚拟 CPU,您可以配置一个 CPU 模式,配置一个或多个 命名的 CPU 模型,并显式请求 CPU 特性标志

2018 年柏林峰会上的 Nova 中有效的虚拟 CPU 配置 演示文稿对此主题提供了很好的概述。

注意

也可以配置 CPU 的拓扑。这在 CPU 拓扑 中讨论。

重要提示

以下描述的功能当前仅受 libvirt 驱动程序支持。

CPU 模式

配置访客 CPU 的第一步是配置 CPU 模式。CPU 模式确定 CPU 模型是根据管理员配置手动配置,还是根据主机 CPU 自动配置。CPU 模式使用 libvirt.cpu_mode 配置选项进行配置。此选项可以接受以下值之一:nonehost-passthroughhost-modelcustom

主机模型

如果 cpu_mode=host-model,libvirt 请求与主机最匹配的 命名的 CPU 模型,并请求额外的 CPU 标志以完成匹配。此 CPU 模型具有许多优点

  • 它将主机 CPU 的几乎所有特性都提供给访客系统,从而提供尽可能接近的最大功能和性能。

  • 它会自动添加关键的访客 CPU 标志,以缓解某些安全漏洞,前提是 CPU 微码、内核、QEMU 和 libvirt 都已更新。

  • 它计算实时迁移兼容性,但需要注意的是,双向实时迁移并非始终可行。

通常,如果您的计算节点 CPU 大部分相同,则使用 host-model 是一个安全的选择。但是,如果您的计算节点跨多个处理器代,您可能最好选择 custom CPU 模型。

对于 KVM 和 QEMU 超visor (libvirt.virt_type=kvm/qemu) 在 x86-64 主机上,host-model CPU 模式是有效的默认值。此默认值由 libvirt 本身提供。

注意

如上所述,在使用 host-model 时,实时迁移并非始终在双向可行。在实时迁移期间,源 CPU 模型定义会按原样传输到目标主机。这导致迁移到目标主机上的访客系统看到与源主机上完全相同的 CPU 模型,即使目标计算主机能够提供更多的 CPU 特性。但是,关闭并重新启动访客系统可能会导致访客系统具有不同的硬件配置,具体取决于目标计算的新功能。

主机直通

如果 cpu_mode=host-passthrough,libvirt 会告诉 KVM 传递主机 CPU 而不进行任何修改。与仅匹配特性标志的 host-model 相比,host-passthrough 确保匹配主机 CPU 的每一个细节。这提供了最佳性能,并且对于某些检查低级 CPU 细节的应用程序来说非常重要,但它会牺牲迁移的便利性。

host-passthrough 模式下,访客只能实时迁移到与源主机极其匹配的目标主机。这包括物理 CPU 模型和正在运行的微码,甚至可能包括正在运行的内核。仅当您的计算节点具有非常高的同质性(即,您的计算节点大部分使用完全相同的 CPU 代和型号)并且您确保仅在内核版本完全匹配的主机之间进行实时迁移时,才使用此模式。否则,将无法支持任何形式的实时迁移。

注意

原因是硬件性能计数器暴露给实例,并且它们在不同的 CPU 模型之间可能不同。由于某些硬件安全漏洞的安全修复包含在 CPU 微码中,也可能有其他原因。

自定义

如果 cpu_mode=custom,您可以显式指定一个或多个受支持的命名 CPU 模型的有序列表,使用 libvirt.cpu_models 配置选项。这接受对给定主机有效的任何命名 CPU 模型,如 CPU 模型 中所述。如果提供多个 CPU 模型,则预计列表将按顺序排列,以便更常见和不太先进的 CPU 模型首先列出。

在选择 custom 模式以及与您的计算节点 CPU 中最旧的 CPU 模型匹配的命名 CPU 模型时,您可以确保计算节点之间的实时迁移始终可行。但是,您应该确保您选择的 CPU 模型将正确的 CPU 特性标志传递给访客系统。

如果您需要在 custom 模式下进一步调整 CPU 特性标志,请参阅 CPU 特性标志

注意

如果 libvirt.cpu_models 已配置,则列表中的 CPU 模型需要与主机 CPU 兼容。此外,如果 libvirt.cpu_model_extra_flags 已配置,则所有标志都需要与主机 CPU 兼容。如果指定了不兼容的 CPU 模型或标志,nova 服务将引发错误并无法启动。

如果 cpu_mode=none,libvirt 不会指定 CPU 模型。相反,hypervisor 会选择默认模型。

对于所有非 KVM/QEMU hypervisor,none CPU 模型是默认值。(libvirt.virt_type!= kvm / qemu

CPU 模型

libvirt.cpu_mode 设置为 custom 时,可以配置一个或多个应使用的显式 CPU 模型。这些 CPU 模型名称是特性标志集的简写。libvirt KVM 驱动程序提供许多标准的 CPU 模型名称。这些模型定义在 /usr/share/libvirt/cpu_map/*.xml 中。您可以检查这些文件以确定您的本地安装支持哪些模型。例如,考虑一个主机提供以下(不完整)的 CPU 模型集

$ ls /usr/share/libvirt/cpu_map/x86_*.xml -1
...
/usr/share/libvirt/cpu_map/x86_Broadwell-IBRS.xml
/usr/share/libvirt/cpu_map/x86_Broadwell-noTSX-IBRS.xml
/usr/share/libvirt/cpu_map/x86_Broadwell-noTSX.xml
/usr/share/libvirt/cpu_map/x86_Broadwell.xml
/usr/share/libvirt/cpu_map/x86_Haswell-IBRS.xml
/usr/share/libvirt/cpu_map/x86_Haswell-noTSX-IBRS.xml
/usr/share/libvirt/cpu_map/x86_Haswell-noTSX.xml
/usr/share/libvirt/cpu_map/x86_Haswell.xml
/usr/share/libvirt/cpu_map/x86_Icelake-Client-noTSX.xml
/usr/share/libvirt/cpu_map/x86_Icelake-Client.xml
/usr/share/libvirt/cpu_map/x86_Icelake-Server-noTSX.xml
/usr/share/libvirt/cpu_map/x86_Icelake-Server.xml
/usr/share/libvirt/cpu_map/x86_IvyBridge-IBRS.xml
/usr/share/libvirt/cpu_map/x86_IvyBridge.xml
/usr/share/libvirt/cpu_map/x86_SandyBridge-IBRS.xml
/usr/share/libvirt/cpu_map/x86_SandyBridge.xml
/usr/share/libvirt/cpu_map/x86_Skylake-Client-IBRS.xml
/usr/share/libvirt/cpu_map/x86_Skylake-Client-noTSX-IBRS.xml
/usr/share/libvirt/cpu_map/x86_Skylake-Client.xml
/usr/share/libvirt/cpu_map/x86_Skylake-Server-IBRS.xml
/usr/share/libvirt/cpu_map/x86_Skylake-Server-noTSX-IBRS.xml
/usr/share/libvirt/cpu_map/x86_Skylake-Server.xml
...

每个文件都包含有关 CPU 模型提供的特性集的信息。例如

$ cat /usr/share/libvirt/cpu_map/x86_SandyBridge-IBRS.xml
<cpus>
  <model name='SandyBridge-IBRS'>
    <decode host='on' guest='on'/>
    <signature family='6' model='42'/> <!-- 0206a0 -->
    <signature family='6' model='45'/> <!-- 0206d0 -->
    <vendor name='Intel'/>
    <feature name='aes'/>
    <feature name='apic'/>
    ...
  </model>
</cpus>

您还可以使用 virsh cpu-models ARCH 列出这些 CPU 模型。例如

$ virsh cpu-models x86_64
...
SandyBridge
SandyBridge-IBRS
IvyBridge
IvyBridge-IBRS
Haswell-noTSX
Haswell-noTSX-IBRS
Haswell
Haswell-IBRS
Broadwell-noTSX
Broadwell-noTSX-IBRS
Broadwell
Broadwell-IBRS
Skylake-Client
Skylake-Client-IBRS
Skylake-Client-noTSX-IBRS
Skylake-Server
Skylake-Server-IBRS
Skylake-Server-noTSX-IBRS
Icelake-Client
Icelake-Client-noTSX
Icelake-Server
Icelake-Server-noTSX
...

通过设置 cpu_mode=custom,可以在 nova.conf 中的 libvirt.cpu_models 配置选项中列出这些 CPU 模型中的一个或多个。例如

[libvirt]
cpu_mode = custom
cpu_models = IvyBridge

通常,您只需要在此处列出单个模型,但列出多个 CPU 模型对于通过特性请求 CPU 特性标志可能很有用。为此,只需按从最旧(因此最广泛支持)到最新的顺序列出其他 CPU 模型即可。例如

[libvirt]
cpu_mode = custom
cpu_models = Penryn,IvyBridge,Haswell,Broadwell,Skylake-Client

有关如何请求 CPU 特性标志以及为什么您可能希望指定多个 CPU 模型,请参阅 CPU 特性标志 下方。

CPU 特性标志

18.0.0 版本添加: (Rocky)

无论您配置的 libvirt.cpu_mode 如何,也可以选择性地启用其他特性标志。这可以使用 libvirt.cpu_model_extra_flags 配置选项来完成。例如,假设您已配置了 IvyBridge 的自定义 CPU 模型,通常不会启用 pcid 特性标志,但您希望将 pcid 传递到您的 Nova 实例。在这种情况下,您可以在 nova.conf 中配置以下内容以启用此标志。

[libvirt]
cpu_mode = custom
cpu_models = IvyBridge
cpu_model_extra_flags = pcid

最终用户也可以通过特性指定所需的 CPU 特性。当指定时,libvirt 驱动程序将选择 libvirt.cpu_models 列表中可以提供请求的特性特性的第一个 CPU 模型。如果未指定任何 CPU 特性特性,则实例将配置为列表中的第一个 CPU 模型。

考虑以下 nova.conf

[libvirt]
cpu_mode = custom
cpu_models = Penryn,IvyBridge,Haswell,Broadwell,Skylake-Client

这些不同的 CPU 模型支持不同的特性标志,并按从最旧(因此最广泛支持)到最新的顺序正确配置。如果用户显式要求 avxavx2 CPU 特性,后者仅在 Haswell 代处理器或更新版本中找到,则他们可以使用 trait{group}:HW_CPU_X86_AVXtrait{group}:HW_CPU_X86_AVX2 flavor extra specs 来请求它们。例如

$ openstack flavor set $FLAVOR \
    --property trait:HW_CPU_X86_AVX=required \
    --property trait:HW_CPU_X86_AVX2=required

由于 Haswell 是支持这两个 CPU 特性的第一个 CPU 模型,因此实例将配置为该模型。

缓解 MDS(“微体系结构数据采样”)安全漏洞

2019 年 5 月,发现了四个新的微处理器漏洞,称为 MDS,也称为 RIDL 和 FalloutZombieLoad。这些漏洞会影响未修补的 Nova 计算节点和在 Intel x86_64 CPU 上运行的实例。

解决方案

为了缓解上述 MDS 安全漏洞,需要将一个新的 CPU 标志 md-clear 暴露给 Nova 实例。这可以通过以下方式完成。

  1. 更新以下组件到您的 Linux 发行版中具有 MDS 漏洞修复的版本,在所有具有 Intel x86_64 CPU 的计算节点上

    • microcode_ctl

    • kernel

    • qemu-system-x86

    • libvirt

  2. 在使用 libvirt 驱动程序时,请确保将 CPU 标志 md-clear 暴露给 Nova 实例。这可以通过以下三种方式之一完成,具体取决于您配置的 CPU 模式

    1. libvirt.cpu_mode=host-model

      当使用 host-model CPU 模式时,md-clear CPU 标志将自动传递到 Nova 访客系统。

      此模式是默认模式,当 libvirt.virt_type=kvm|qemu 设置在 /etc/nova/nova-cpu.conf 计算节点上时。

    2. libvirt.cpu_mode=host-passthrough

      在使用 host-passthrough CPU 模式时,md-clear CPU 标志将自动传递到 Nova 虚拟机。

    3. libvirt.cpu_mode=custom

      在使用 custom CPU 模式时,除了之前漏洞所需的标志外,您必须显式地启用 CPU 标志 md-clear 到 Nova 实例,使用 libvirt.cpu_model_extra_flags。例如

      [libvirt]
      cpu_mode = custom
      cpu_models = IvyBridge
      cpu_model_extra_flags = spec-ctrl,ssbd,md-clear
      
  3. 重启计算节点以使修复生效。

    为了尽量减少工作负载的停机时间,您可以先将所有虚拟机实时迁移到另一个计算节点。

在部署中的每个易受攻击的计算节点上采取上述步骤后,集群中的每个正在运行的虚拟机必须完全关机,并冷启动(即显式停止后启动),才能激活新的 CPU 模型。这可以由虚拟机管理员在他们选择的时间完成。

验证

应用相关更新后,管理员可以检查内核的 sysfs 接口,以查看已实施的缓解措施,方法是在主机上运行以下命令

# cat /sys/devices/system/cpu/vulnerabilities/mds
Mitigation: Clear CPU buffers; SMT vulnerable

要解析消息“Mitigation: Clear CPU buffers; SMT vulnerable”

  • Mitigation: Clear CPU buffers 表示您已启用“CPU 缓冲区清除”缓解措施,这是一种通过调用名为“VERW”的 CPU 指令来触发刷新各种易受攻击的 CPU 缓冲区。

  • SMT vulnerable 表示,根据您的工作负载,您可能仍然容易受到 SMT 相关问题的影响。您需要评估您的工作负载是否需要 SMT(也称为“超线程”)被禁用。请参考您的 Linux 发行版和处理器供应商的指导。

要查看 /sys/devices/system/cpu/vulnerabilities/mds 的其他可能值,请参阅 Linux 内核文档中 MDS 的 MDS 系统信息 部分。

在主机上,验证 KVM 是否能够将 md-clear 标志暴露给虚拟机

# virsh domcapabilities kvm | grep md-clear
<feature policy='require' name='md-clear'/>

更多信息可以在 此安全公告文档 的“诊断”选项卡中找到。

性能影响

请参阅 此安全公告文档 的“解决”选项卡下的标题为“性能影响和禁用 MDS”的部分。

注意

虽然引用的文章来自 Red Hat,但关于性能影响的发现和建议也适用于其他发行版。