CPU 虚拟化之Cpu Models
通过本章的学习,读者可以了解在 Nova 的配置文件中如何配置各种 CPU Mode,以及当 CPU 跨代迁移时,若经兼容性判断发现结果不兼容,该如何选择 CPU Mode 以保证虚拟机之间能正常迁移。
在之前的章节中已经简单介绍过CPU模式,如果对CPU Mode之前没有接触过,建议先查看
CPU Models 第一篇
问题1 什么是 CPU Models?
Nova allows you to configure features of the virtual CPU that are exposed to instances. The combined set of CPU features is collectively referred to as the CPU model (官方原文引用)
Nova 允许用户配置虚拟 CPU 的特性,这些特性会暴露给虚拟机实例。而这些 CPU 特性的组合,统称为 CPU 模型(CPU model)
简单解释就是 一个物理CPU上有多种 flag 标记,每一个flag 对应CPU的一个特征,如常见的CPU虚拟化支持的特性
lscpu | egrep "vmx|svm"
这里的 vmx和 svm 就对应是CPU flag ,同理lscpu 对应的 Flags 就是当前物理机CPU 全部特征。
通过配置CPU Mode ,在CPU Mode 基础上配置一个或多个CPU models ,还可以额外指定一些 CPU flags ,将这些特征暴露给虚拟机使用。
问题2:CPU Flags和 CPU Models 和 CPU Mode 三者的关系?
为方便描述,本文中 CPU Model
统一称为 CPU 模型
,CPU Mode
统一称为 模式
。
从图中可知,CPU Flag(CPU 标志位)集合构成了不同的 CPU 模型;
而 CPU 模式是 CPU 模型的更高层级抽象,它既可以是多个 CPU 模型的集合,也可以是单个 CPU 模型。
这里如何理解?
例如CPU模式 custom 中可以定义多个模型,如 Haswell,Skylake 等,
在生成环境中我们需要先确定CPU 模式,之后在确定CPU 模型 最后才是CPU flags
问题3:CPU 四种模式分别是什么?
cpu 四种mode
-
host-model(主机模型)
- 自动选择最贴近主机的模型,并补充缺失特性。
- 性能几近原生,安全补丁自动激活。
- 默认适用于 KVM/QEMU。如主机为多代 CPU,可能影响向后迁移
-
host-passthrough(主机直通)
- 完全透传主机 CPU 特性,性能最优。
- 要求主机环境极度同质,否则无法迁移
-
custom(自定义)
- 管理员通过 libvirt.cpu_models 指定一个或多个模型列表(建议按从旧到新的顺序)。
可结合 cpu_model_extra_flags 添加细粒度控制,提升迁移兼容性
- 管理员通过 libvirt.cpu_models 指定一个或多个模型列表(建议按从旧到新的顺序)。
-
none(无设置)
- 不指定模型,由 hypervisor(如 QEMU)选择默认模型。默认用于非 KVM/QEMU 环境
一句话总结:host-passthrough
(主机直通性能最好),默认其使用所有物理机Flags 。
host-model
(主机模式),默认系统会选择和其对应flags 最匹配的CPU 模型。
而 custom
则是管理原自定义模型,可以用来屏蔽,CPU 不同型号之间特征差异,来保证迁移的兼容性。
使用建议:
-
如果服务器在虚拟化层面追求极致性能,建议使用
host-passthrough
(主机直通)。 -
如果该服务器在追求性能的同时,还要考虑部分迁移兼容性,(例如同一代CPU,不同版本小型号),此时应该选
host-model
模式。 -
如果考虑跨代CPU之间的CPU迁移使用,建议使用
custom
模式。
无论选择何种模式,我们都可以在其基础上增加和减少某些Flags(注意)
问题4: Custom模型下选择Models
如果服务器上安安装了 libvirt-lib 包则下面目录,每一个文件对应一个model对应需要的flags 。
也可以使用命令行的方式来查看models
virsh cpu-models x86_64
SandyBridge
SandyBridge-IBRS
IvyBridge
IvyBridge-IBRS
Haswell-noTSX
Haswell-noTSX-IBRS
Haswell
Haswell-IBRS
Broadwell-noTSX
Broadwell-noTSX-IBRS
通过查看模型的自定义文件,可以查看到其定义的Flags
cat /usr/share/libvirt/cpu_map/x86_Icelake-Server.xml
<cpus><model name='Icelake-Server'><decode host='on' guest='on'/><signature family='6' model='134'/> <!-- 080660 --><vendor name='Intel'/><feature name='3dnowprefetch'/><feature name='abm'/><feature name='adx'/><feature name='aes'/><feature name='apic'/><feature name='arat'/><feature name='avx'/>...
在多种模式中我们尽量选择Flags 和当前CPU flags 匹配度较高的就行,如果除了模型自带的flag,我们还行额外增加Flag 可以用如下方式来添加
#nova.conf 对应nova-compute 的配置文件
[libvirt]
cpu_mode = custom
cpu_models = IvyBridge
cpu_model_extra_flags = pcid
此时 cpu_model_extra_flags 就是在模型之外额外添加的,此时除了添加外还可以减少特定的flag 使用方式也很简单
这里的的 -invtsc
-hle
-rtm
都是-开头都是减少对应的Flag ,正式因为可以额外增加和减少特点的flag,为虚拟机跨代迁移,提供了良好的支撑。
问题5: 同时配置多个models ,nova在虚拟机创建时选择策略?
在回答这个问题时,我们先简单说明下,Openstack 在创建机型时,可以指定一些属性,如
hw:mem_page_size":"1048576"
指定大叶内存的pagesize ,还可以指定使用网卡的多队列
hw:vif_multiqueue_enabled
等等 这一系列的属性。
同理我们也可以在flavor 中指定需要的flag ,如
openstack flavor set $FLAVOR \--property trait:HW_CPU_X86_AVX=required \--property trait:HW_CPU_X86_AVX2=required
HW_CPU_X86_AVX=required → 必须有 AVX
HW_CPU_X86_AVX2=required → 必须有 AVX2
因此在选出model时会从左到右找出第一个满足要求的model ,则虚拟机实例就是该model.
如果没有在flavor 中定义属性,则默认永远选择第一个model, 在生产环境中如果多种跨代CPU 宿主机时,我们建议是先旧后新来指定多个models 。因为这样能最大程度的保证迁移的兼容性。默认都匹配时会先使用旧的model,这样在新的model中,也能满足。
问题6:CPU 跨代不兼容怎么解决?
在上一篇文章中我们通过命令virsh domcapabilities > domA.caps
导出cpu 的flags时,然后在迁移端执行virsh hypervisor-cpu-compare --error domA.caps
判断两个CPU 是否兼容,仅仅是做了判断,并未完全解决该问题, 现在重点分析下其比较背后的原理。
virsh domcapabilities<cpu><mode name='host-passthrough' supported='yes'><enum name='hostPassthroughMigratable'><value>on</value><value>off</value></enum></mode><mode name='host-model' supported='yes'><model fallback='forbid'>Dhyana</model><vendor>Hygon</vendor><feature policy='require' name='pclmuldq'/><feature policy='require' name='x2apic'/><feature policy='require' name='tsc-deadline'/><feature policy='require' name='aes'/><feature policy='require' name='hypervisor'/><feature policy='require' name='tsc_adjust'/><feature policy='require' name='sha-ni'/><feature policy='require' name='ssbd'/><feature policy='require' name='cmp_legacy'/><feature policy='require' name='perfctr_core'/><feature policy='require' name='invtsc'/><feature policy='require' name='virt-ssbd'/><feature policy='require' name='npt'/><feature policy='require' name='nrip-save'/><feature policy='disable' name='monitor'/></mode><mode name='custom' supported='yes'><model usable='yes'>qemu64</model><model usable='yes'>qemu32</model><model usable='no'>phenom</model><model usable='no'>SandyBridge-IBRS</model><model usable='yes'>SandyBridge</model><model usable='yes'>Penryn</model><model usable='no'>Icelake-Server</model><model usable='no'>Icelake-Client-noTSX</model><model usable='no'>Icelake-Client</model><model usable='no'>Haswell-noTSX-IBRS</model><model usable='no'>Haswell-noTSX</model><model usable='no'>Haswell-IBRS</model><model usable='no'>Haswell</model> </mode></cpu>
上面是一款海光CPU 执行命令virsh domcapabilities
之后的部分输出结果,
从mode name 这个属性中可以看到
-
mode name='host-passthrough' supported='yes'
,说明其支持 主机直通模式。 -
mode name='host-model' supported='yes'
也支持 host-model,
其host-model 模式时,其必须的flag ,如<feature policy='require' name='pclmuldq'/>
等, -
mode name=‘custom’ supported=‘yes’ ,说明其也支持,同时 usable=yes 的model,标识在当前宿主下支持的model ,同理 usable=no 标识不支持的model ,
而 virsh hypervisor-cpu-compare
命令比较是什么就是比较当前 kvm 使用的mode 下,CPU之间的flag的差异有哪些
virsh hypervisor-cpu-compare --error domA.caps
error: Failed to compare hypervisor CPU with domA.caps
error: the CPU is incompatible with host CPU: 主机 CPU 不提供所需功能: vmx, pdcm, invtsc
此时的 vmx, pdcm, invtsc 就是当前CPU 不具备的,结合上面的nova的配置文件 libvirt段落的配置
cpu_model_extra_flags = -vmx,-pdcm,-invtsc
写在最后
通过同时修改修改两端的该配置,就可以实现cpu之间的迁移操作。(注意1 配置需要重启后才能生效,且配置对已经存在的虚拟机是无效的,仅仅是对那些新创建的虚拟机才能生效。)
(注意2 上面的例子仅仅是说明 A -> B
的操作,并不代表B-> A
的迁移操作能正常。)
在文章的最后,我们留下一个问题,如何双向迁移都能正常呢?欢迎评论区讨论。