KVM热迁移¶
准备工作¶
KVM虚拟化技术有一个非常有用的杀手锏技术 KVM热迁移 ,我们现在已经得到了支持嵌套虚拟化的虚拟机 devstack
,我们现在从这个 devstack
复制出我们热迁移用的两个虚拟机 devstack-1
和 devstack-2
virt-clone --connect qemu:///system --original devstack --name devstack-1 --file /var/lib/libvirt/images/devstack-1.qcow2
sudo virt-sysprep -d devstack-1 --hostname devstack-1 --root-password password:CHANGE_ME
virt-clone --connect qemu:///system --original devstack --name devstack-2 --file /var/lib/libvirt/images/devstack-2.qcow2
sudo virt-sysprep -d devstack-2 --hostname devstack-2 --root-password password:CHANGE_ME
这两个支持 Nested Virtualization 的虚拟机 devstack-1
和 devstack-2
不仅是我们测试嵌套虚拟化的虚拟机,也是测试 热迁移技术的虚拟机。我们这里使用 Kubernetes Atlas 中 minikube 来作为”嵌在内部”的虚拟机。
备注
minikube
虚拟机是2c2g配置,我们需要调整 devstack-1
和 devstack-2
的虚拟机配置,修订成 2c4g
配置来支持嵌套运行 minikube
在
devstack-1
和devstack-2
虚拟机的内部参考 Studio环境KVM和Docker 安装KVM运行环境:sudo apt install qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils virtinst libguestfs-tools
基于NFS共享存储¶
KVM热迁移实现需要使用共享的存储池,最简便的方法是使用NFS共享。更为复杂且高可用、高性能的是使用共享的分布式文件系统,如Ceph ( 请参考 Ceph Atlas )。
在
xcloud
物理主机上 Studio环境的Btrfs存储 创建子卷images
btrfs subvolume create /data/images
修改
/etc/fstab
添加:/dev/sda3 /nfs/images btrfs subvol=images,defaults,noatime 0 1
挂载目录:
mkdir -p /nfs/images mount /nfs/images
安装NFS服务:
apt install nfs-kernel-server
设置NFS共享,即编辑
/etc/exports
/nfs/images 192.168.122.0/24(rw,sync,no_root_squash,no_subtree_check)
服务器端输出NFS:
exportfs -a
NFS客户端挂载¶
在作为KVM虚拟化运行的主机 devstack-1
和 devstack-2
中使用NFS方式挂载 xcloud
共享出来的NFS存储,以下命令都在这两个虚拟机中运行:
安装NFS客户端:
apt install nfs-common
编辑
/etc/fstab
添加:192.168.122.1:/nfs/images /var/lib/libvirt/nfs-images nfs auto,rw,vers=3,hard,intr,tcp,rsize=32768,wsize=32768 0 0
客户端挂载:
mkdir /var/lib/libvirt/images mount /var/lib/libvirt/images
挂载之后,在 devstack-1
和 devstack-2
两个虚拟机内部都会看到共享存储如下:
192.168.122.1:/nfs/images 184G 13G 170G 8% /var/lib/libvirt/images
配置libvirt的VM存储池¶
默认情况下libvirt使用的存储池目录是 /var/lib/libvirt/images
,需要修改成热迁移共享存储NFS。
备注
必须检查 devstack-1
和 devstack-2
上所有虚拟机运行状态,确保所有虚拟机都已经关闭:
virsh list --all
检查存储池:
virsh pool-list --all
如果没有创建过虚拟机,上述存储池输出可能是空的。如果创建了虚拟机,默认会有一个 images
存储池。这里尝试创建一个虚拟机来激活存储池:
virt-install \
--network bridge:virbr0 \
--name ubuntu18.04 \
--ram=2048 \
--vcpus=1 \
--os-type=ubuntu18.04 \
--disk path=/var/lib/libvirt/images/ubuntu18.04.qcow2,format=qcow2,bus=virtio,cache=none,size=16 \
--graphics none \
--location=http://mirrors.163.com/ubuntu/dists/bionic/main/installer-amd64/ \
--extra-args="console=tty0 console=ttyS0,115200"
报错:
ERROR Couldn't create storage volume 'ubuntu18.04.qcow2': 'internal error: Child process (/usr/bin/qemu-img create -f qcow2 -o preallocation=metadata,compat=1.1,lazy_refcounts /var/lib/libvirt/images/ubuntu18.04.qcow2 16777216K) unexpected exit status 1: qemu-img: /var/lib/libvirt/images/ubuntu18.04.qcow2: Failed to lock byte 100
备注
FYI, I’m told by a storage maintainer that this is only really a problem with NFSv3. With NFSv4, locks use an active lease mechanism with the client having to refresh the lease periodically for it to remain valid. So if you are using NFSv4 and the client dies with locks held, they should be revoked by the server after the lease renewal timeout is reached, allowing another host to acquire them.
Some more info here about NFSv4 locking here:
https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.1.0/com.ibm.zos.v2r1.idan400/lockv4.htm
Given NFSv3 is a legacy protocol, I don’t think it justifies disabling locking from QEMU side. The nolock mount option seems like a reasonable workaround for V3, if the sites in question really can’t use V4.
修改NFS挂载:
192.168.122.1:/nfs/images /var/lib/libvirt/images nfs4 _netdev,auto 0 0
然后重新挂载:
umount /var/lib/libvirt/images
mount /var/lib/libvirt/images
再次尝试创建虚拟机就可以成功,也就具备了 images
这个默认存储池。
如果已经有一个 images
存储池,则使用 virsh pool-edit images
编辑配置,其中的存储路径修改成新的NFS共享存储路径 /var/lib/libvirt/nfs-images
。
如果还没有存储池,则创建一个
images.xml
<pool type="dir"> <name>images</name> <target> <path>/var/lib/libvirt/images</path> </target> </pool>
然后执行:
virsh pool-create nfs-images.xml
备注
以上通过XML文件创建存储池方法也可用命令行实现:
virsh pool-create-as --name images --type dir --target /var/lib/libvirt/images
当然也可以直接创建一个虚拟机来实现存储卷 images
备注
详细请参考 Storage Pool Commands
测试虚拟机¶
在 创建KVM虚拟机 创建过第一个虚拟机名为 ubuntu18.04 ,我们现在将这个虚拟机从 xcloud
物理服务器上复制到支持嵌套虚拟化的 devstack-1
虚拟机中,存放到 /var/lib/libvirt/images
目录下:
- 在 ``xcloud`` 上执行::
cd /var/lib/libvirt/images scp ubuntu18.04.qcow2 devstack-1:/var/lib/libvirt/images/nested-ubuntu18.04.qcow2
备注
由于 devstack-1
的NFS共享挂载的就是 xcloud
的 /nfs/images
目录,所以上述命令其实也可以在 xcloud
上直接复制到本地目录 /nfs/images
下,同样会被 devstack-1
和 devstack-2
使用:
cp ubuntu18.04.qcow2 /nfs/images/nested-ubuntu18.04.qcow2
在
devstack-1
和devstack-2
中检查/var/lib/libvirt/images
目录下应该有如下文件:-rw------- 1 root root 17G Mar 13 16:56 nested-ubuntu18.04.qcow2
修改成 libvirt-qemu:kvm
属主:
chown libvirt-qemu:kvm /var/lib/libvirt/images/nested-ubuntu18.04.qcow2
在
devstack-1
上导入这个虚拟机 (使用--import
参数 ):virt-install \ --network bridge:virbr0 \ --name nested-ubuntu18.04 \ --os-type=ubuntu18.04 \ --ram=2048 \ --vcpus=1 \ --disk path=/var/lib/libvirt/images/nested-ubuntu18.04.qcow2,format=qcow2,bus=virtio,cache=none \ --network bridge=virbr0,model=virtio \ --import
备注
这里还有一点问题,照例说使用了 --import
不应该出现安装过程。不过依然可以使用
热迁移¶
在
devstack-1
和devstack-2
主机间设置好ssh免密码登陆
以下命令在物理主机 xcloud
上执行,将密钥分发到两个测试虚拟机上:
scp id_rsa* devstack-1:/home/huatai/.ssh/
scp id_rsa* devstack-2:/home/huatai/.ssh/
在
devstack-1
和devstack-2
的/etc/hosts
中添加主机名解析:192.168.122.21 devstack-1 192.168.122.22 devstack-2
在
devstack-1
和devstack-2
的~/.ssh/config
中添加:Host * ServerAliveInterval 60 ControlMaster auto ControlPath ~/.ssh/%h-%p-%r ControlPersist yes
这样只需要一次ssh登陆,后续复用socks就不需要密码:
ssh devstack-2 "virsh list"
热迁移:
virsh migrate nested-ubuntu18.04 qemu+ssh://devstack-2/system virsh migrate nested-ubuntu18.04 qemu+ssh://devstack-1/system