libvirt的很多配置选项其实是调用了qemu的接口,但也有增加和优化的地方,本文主要总结这些配置选项,当个手册来查询。
按照centos停服前最后一版centos-8.5.2111提供的rpm查看http://mirrors.aliyun.com/centos/8.5.2111/AppStream/aarch64/os/Packages/,两者间的版本对应是
qemu-4.2.0 <===> libvirt-6.0.0
之前遇到过一个bugfix,里面提到两者对应的版本是
qemu-6.0.0 <===> RHEL-8.5 <===> libvirt.6.0.0 (此处有待考证,感觉libvirt应该更高才对)
1991898 – Live migration fails with latest QEMU with migrate_set_speed missing error (redhat.com)
Log In | Red Hat IDPhttps://access.redhat.com/downloads/content/rhel---8/aarch64/7459/libvirt/6.0.0-37.1.module+el8.5.0+13858+39fdc467/aarch64/fd431d51/package
我自己测试的版本如下,测试了很多项目是没啥问题的。
qemu-6.2.0 <===> libvirt-8.0.0
一、CPU配置
1.1使用QEMU/KVM配置CPU型号的两种方法
1.Host passthrough 主机直通 (qemu-system-aarch64 -cpu host)
这会将主机CPU模型特性、模型、步进准确地传递给guest。请注意,如果虚拟化不支持某些主机CPU型号的功能,KVM可能会过滤掉这些功能。
当使用此模式时,实时迁移是不安全的,因为libvirt / QEMU不能保证跨主机向guest暴露稳定的CPU。
这是推荐使用的CPU,前提是不需要实时迁移。
2.Named model 命名模型 (qemu-system-aarch64 -cpu cortex-a57)
QEMU附带了许多预定义的命名CPU模型(qemu-system-aarch64 cpu --help),这些模型通常指的是Intel和AMD发布的特定一代硬件。
这允许guest VM与主机CPU有一定程度的隔离,从而在具有不同硬件的主机之间实现更大的实时迁移灵活性。
3.max (qemu-system-aarch64 -cpu max)(新版本qemu + 特定架构如aarch64)
-cpu max: if KVM is enabled, like -cpu host (best possible with this host); //kvm_enable(),则等同于 -cpu host
otherwise, a CPU with as many features enabled as our emulation supports. //否则,最大化模拟一个各个feature都有的cpu
在这几种情况下,都可以选择添加或删除单个CPU功能,以更改默认情况下呈现给guest的内容。
-cpu cortex-a57,psi=off,vmx=off
1.2 Libvirt支持三种配置CPU模型的方式
1.Host passthrough:
这种模式的优点是性能高,缺点是guest环境不能在不同的硬件上重现。因此,如果你遇到任何bug,你就只能靠自己了;
如果源主机和目标主机在硬件、QEMU版本、微码版本和配置方面都不相同,则使用host-passthrough迁移是危险的。
1.1)主机直通:
<cpu mode='host-passthrough'/>
1.2)具有自定义功能的主机直通:
<cpu mode='host-passthrough' migratable='off'>
<feature name="vmx" policy="disable"/>
...
</cpu>
2.Custom (Named model):
在这种模式下,cpu元素描述了应该呈现给guest的CPU。这是未指定mode属性时的默认值。
这种模式使得持久guest无论在什么主机上启动都将看到相同的硬件。
2.1)命名型号:
<cpu mode='custom'>
<model name="Westmere"/>
</cpu>
2.2)具有功能自定义的命名模型:
<cpu mode='custom'>
<model name="Westmere"/>
<feature name="pcid" policy="require"/>
...
</cpu>
3.Host model: 【需要迁移的最佳选择】
(qemu的介绍:Libvirt支持第三种配置CPU模型的方式,称为“主机模型”。这使用了QEMU的“命名模型”特性,自动选择一个与主机CPU相似的CPU模型,然后添加额外的特性以尽可能接近主机模型。(属于qemu两种模型的折中优化,支持迁移)
这并不能保证具备和“Host passthrough”一样的功能(如 CPU系列、步进等将与主机CPU精确匹配),但是提供了很多直通的好处,同时使实时迁移安全。)
主机模型模式本质上是从capabilities XML 中复制host CPU 的定义到domain XML。由于CPU定义是在启动域之前复制的,因此可以在不同的主机上使用完全相同的XML,同时仍然提供每个host支持的最佳guest CPU。
Libvirt并没有对每个CPU的各个方面进行建模,因此 guest CPU不会与host CPU完全匹配。
在迁移过程中,完整的CPU模型定义被传输到目标主机,因此即使目标主机包含更多功能的CPU或更新的内核,迁移的guest也会看到与guest运行实例完全相同的CPU模型;但是根据新主机的功能,关闭和重启guest后可能会呈现出不同的硬件。
2.1)主机型号:
<cpu mode='host-model'/>
2.2)具有功能自定义的主机型号:
<cpu mode='host-model'>
<model>xxx</model>
<feature name="vmx" policy="disable"/>
...
</cpu>
4.maximum 额外综合出来的一个选项
当使用硬件虚拟化运行guest时,此CPU模型在功能上与host-passthrough相同;
当运行具有CPU模拟的guest时,此CPU模型将启用模拟引擎能够支持的最大功能集。请注意,即使使用migratable='on',迁移也是危险的。
如果应用程序不关心具体的CPU,只是想要最佳的功能集而且不需要迁移兼容性,那么maximum模型是一个很好的选择。
4.1)最大模型:
<cpu mode='maximum'/>
2.2)具有功能自定义的最大模型:
<cpu mode='maximum' migratable='off'>
<cache mode='passthrough'/>
<feature policy='disable' name='lahf_lm'/>
...
</cpu>
1.3官网参考
QEMU / KVM CPU model configuration — QEMU documentation
libvirt: Domain XML format
二、热插拔
2.1 qemu控制热插拔
2.1.1 内存热插拔
qemu的src中有一个memory-hotplug.txt 详细说明了mem热插拔的步骤,总体就是通过hmp先增加一个memory-backend-xxx,再在memdev的基础上增加一个pc-dimm内存条。
(qemu) object_add memory-backend-ram,id=mem1,size=1G (qemu) device_add pc-dimm,id=dimm1,memdev=mem1 |
可以看到当增加设备后,登录虚机发现free -h总内存增加,且/sys/devices/system/memory/会多出一个memory9节点。
2.2 libvirt控制热插拔
操作了libvirt的热插拔后,就知道qemu的hmp操作如热插拔是多么的不友好,libvirt就直接attach各类xml就完了。
2.2.1 内存热插拔
#cat hot-mem.xml
<memory model='dimm'>
<target>
<size unit='MiB'>1024</size>
<node>0</node>
</target>
</memory>
#virsh start vm
#virsh attach-device $domain_name hot-mem.xml
#virsh detach-device $domain_name hot-mem.xml
2.2.2 虚拟磁盘热插拔
#cat hot-disk.xml
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/tmp/test.img'/>
<target dev='vdb' bus='virtio'/>
</disk>
#virsh start vm
#virsh attach-device $domain_name hot-disk.xml
#virsh detach-device $domain_name hot-disk.xml
2.2.3 直通磁盘热插拔
#cat hot-pci.xml
<hostdev mode='subsystem' type='pci' managed='yes'>
<source>
<address domain='0x0000' bus='0x04' slot='0x00' function='0x0'/>
</source>
</hostdev>
#virsh start vm
#virsh attach-device $domain_name hot-pci.xml (多等一会)
#virsh detach-device $domain_name hot-pci.xml
2.2.4虚拟网卡热插拔
#cat hot-disk.xml
<network>
<name>default</name>
<forward mode='nat'/>
<bridge name='virbr0' stp='on' delay='0'/>
<ip address='192.168.122.1' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.122.2' end='192.168.122.254'/>
</dhcp>
</ip>
</network>
#virsh start vm
#virsh attach-device $domain_name hot-disk.xml
#virsh detach-device $domain_name hot-disk.xml
2.3参考
qemu-6.2.0\docs\memory-hotplug.txt
libvirt-qemu-虚拟机设备热插拔实践-CSDN博客
三、热迁移
本文只分析动态迁移(静态迁移直接拷贝文件就是了),源机器称为src machine,目的迁移机器称为Dest/target machine。热迁移对源目机器要求较高,总是就是越接近越好,最起码是cpu model、OS版本、kernel版本、qemu版本,完全一致。
3.1 qemu控制热迁移
qemu可以通过qmp/hmp命令来控制热迁移,具体操作是:
1)在Dest机器上启动一个虚拟机,该虚拟机并没有真实启动(现象就好像是命令卡住),只是用于等待接收动态迁移过来的内存内容,使用VNC连接后显示界面状态为黑屏,或者是有一行提示。其中,启动命令要加上-incoming 选项。
qemu-system-x86_64 …… -incoming tcp:0:6666
“-incoming tcp:0:6666” 这个参数表示在6666 端口建立一个tcp socket 连接用于接收来自于源宿主机的动态迁移的内容,其中“0”表示允许来自任何主机的连接,“-incoming”表示使QEMU进程进入到迁移监听(migration-listen)模式,而不是真正以命令行中的镜像文件运行客户机。
2)在Src机器上启动源虚拟机,启动命令添加 “-monitor stdio”参数,表示可以进入QEMU监控器,以便接下来执行迁移命令;
qemu-system-x86_64…… -m 4G -smp 2 -vnc :0 -monitor stdio
(qemu)
3)在Src机器上的通过hmp命令操作热迁移。如果没有第三方存储,则需要拷贝磁盘,命令追加-b选项:
(qemu) migrate -b tcp:destination_host_ip:4444
Dest machine: qemu-system-aarch64 -machine virt,accel=kvm,gic-version=3 -cpu cortex-a72 -m 8G -smp 4 …… -incoming tcp:0:4444 Src machine: qemu-system-aarch64 -machine virt,accel=kvm,gic-version=3 -cpu cortex-a72 -m 8G -smp 4 …… -vnc :2 -monitor stdio (qemu) info status (qemu) migrate -b tcp:10.5.191.151:4444 (qemu) info migrate |
迁移中:
迁移完成:
感觉qemu对热迁移支持不是特别好,迁移完后src虚机变成pause状态不能自动恢复,dest虚机也不能直接访问得重启下才行。
另外一开始可以直接用-d选项检查下,如果有错误会直接报出来,而不用等待漫长的迁移过程。若显示迁移成功再开始迁。
3.2 libvirt控制热迁移
本文只考虑非共享存储场景,即没有NFS做为共享存储,也不是openstack等统一管理的机器平台,libvirt控制内存、磁盘全部热迁。
1)在Src上 # virsh domblklist 查看虚机的磁盘有哪些;
2)在Dest上相同磁盘目录下创建一个同样的虚拟磁盘文件,注意磁盘的名字、格式、大小必须保持一致;
3)在Src上 # virsh migrate命令来执行热迁移
Src上 # virsh domblklist Dest上 # qemu-img create -f qcow2 -o size=200G /home/jcf/centos5.img Src上 # virsh migrate --live --unsafe --persistent --verbose vm_name qemu+ssh://192.168.1.200/system tcp://192.168.1.200 --copy-storage-all |
其中,相关子选项(# virsh migrate --help
):
--live 热迁移
--copy-storage-all 使用全磁盘复制的非共享存储进行迁移
--unsafe 忽略安全检查步骤,即使不安全也要强制迁移
--verbose 显示迁移进程
--persistent 目的地中的持久VM
我迁移的时候因为libvirt版本老旧,导致调用了qemu中一个被废弃的命令,后期更新成qemu-6.2.0 <=> libvirt-8.0.0,继续迁移测试,发现cpu的状态在load时报错了。
检查两个机器上cpu的features,发现确实不一致。Dest端多了很多sve的特性。于是,编辑虚机关掉相应的sve特性后(其实libvirt也是调用qemu-system-aarch64 …… -cpu max,sve=off关闭cpu的sve特性),再次迁移,终于成功。
迁移成功后,在Dest侧关闭虚机前,记得dump xml创建vm的配置文件,virsh dumpxml centos> /etc/libvirt/qemu/centos.xml,否则虚机关了就找不到了。
3.3官网参考
Migration — QEMU documentation
https://www.cnblogs.com/zhy128/p/8042801.html