场景:
企业内部为了使服务器资源达到最大化利用,通常都会进行KVM虚拟化,每台服务器上运行多台KVM虚拟机。随着KVM虚拟机数量的不断增多,个别服务器会出现资源过载现象,这时候就需要对部分KVM虚拟机进行迁移,迁移到负载相对较低的服务器上。
为了解决以上问题,针对可停机的KVM虚拟机,可使用静态迁移的方式来迁移KVM 虚拟机。针对在线提供服务、不可停机的KVM虚拟机,可使用基于共享存储的动态迁移或基于数据块的动态迁移来完成迁移工作。最终按业务类型将虚拟机重新调配、合理布局,以保证服务器一直处于良好的运行状态。除了迁移之外,还可以在KVM宿主机上开启KSM 内核同页合并,以达到节省内存、降低负载的目的。
一.KVM虚拟机迁移
KVM虚拟机迁移,是将某一虚拟机上的环境和软件完全复制到另一台物理机上继续运。KVM虚拟机迁移可以优化系统负载、重新规划KVM虚拟机布局并简化KVM虚拟机的管理维护工作。
KVM虚拟机迁移的主要应用场景如下所示。
当一台KVM宿主机的负载比较高时,可将源KVM宿主机上的部分虚拟机迁移到负载较低的KVM宿主机中,以保证服务质量。
通过KVM虚拟机迁移将多台负载较低的KVM宿主机上的KVM虚拟机集中迁移到某一台KVM宿主机上,从而达到节约资源的目的。
在升级KVM宿主机硬件设备时,可以将KVM宿主机上运行的KVM虚拟机迁移到其他 KVM宿主机上,以解决对硬件的依赖,从而实现业务不中断情况下对物理硬件设备的升级。
跨地域迁移,实现KVM虚拟机的远程迁移。
根据迁移方式的不同,可将迁移分为静态迁移(static magration)和动态迁移(live migration)。二者的区别是:静态迁移时会有一段时间虚拟机中的服务是不可用的,而动态迁移则没有明显的服务暂停时间。
(1)静态迁移
静态迁移需要先关闭要迁移的KVM虚拟机,并拷贝它的磁盘文件和配置文件到目标 KVM宿主机,然后恢复启动,从而实现静态迁移。如果KVM虚拟机的磁盘文件存储在KVM 宿主机本地,在静态迁移时需要拷贝磁盘文件和配置文件;如果KVM虚拟机的磁盘文件存储在共享存储上,在静态迁移时,只需要拷贝KVM虚拟机的配置文件,KVM虚拟机的磁盘文件可通过挂载共享存储到本地目录的方式来获取。针对KVM虚拟机磁盘文件存储位置的不同,在静态迁移时需要做适当的调整。
(2)动态迁移
动态迁移是保证KVM虚拟机上运行的应用正常提供服务的同时,让KVM虚拟机在不同的KVM宿主机之间进行迁移。动态迁移的过程仅有非常短暂的停机时间,甚至可以忽略不计,同时KVM虚拟机上己经打开的应用连接不会断开,依然保持不变。KVM的动态迁移有两种方式:一种是基于共享存储的动态迁移,另一种是基于数据块的动态迁移。
基于共享存储的动态迁移
基于共享存储的动态迁移是在KVM虚拟机迁移开始后,被迁移的KVM虚拟机依然保持在源KVM宿主机上运行。与此同时,KVM虚拟机的内存页被传输到目标KVM宿主机之上。QEMU/KVM会监控并记录迁移过程中所有己被传输的内存页的任何修改,并在所有内存页传输完成后再开始传输在前面传输过程中被更改的内存页内容。QEMU/KVM也会评估迁移过程中的传输速度,当剩余的内存数据量能够在一个可设定的时间周期内完成传输, QEMU/KVM将会关闭源宿主机上的KVM虚拟机,再将剩余的数据量传输到目标宿主机,最后通过传输过来的内存内容在目标宿主机上恢复KVM虚拟机的运行状态。如此即可完成 KVM基于共享存储的动态迁移。如果KVM虚拟机中内存使用量非常大且修改频繁,内存中数据被不断修改的速度大于KVM能够传输的内存速度,该情况下无法使用动态迁移,只能使用静态迁移方法来进行KVM虚拟机迁移。
基于数据块的动态迁移
如果对使用本地存储的KVM虚拟机进行在线迁移,就要用到基于数据块的动态迁移。上述基于共享存储的动态迁移,为了实现动态迁移,源KVM宿主机和目标宿主机需要连接共享存储服务,而基于数据块的动态迁移,共享存储不再是动态迁移的必要条件。在迁移过程中,KVM虚拟机只使用本地存储,不再需要共享存储的支持,因此迁移环境比较简单,迁移的源宿主机和目标宿主机只需要保持以太网连接即可。因为少了共享存储,所以降低了动态迁移的难度。
二.KSM内核同页合并
KSM (Kernel SamePage Merging)被称为内核同页合并。KSM允许内核在两个或多个进程之间共享完全相同的内存页。KSM让内核扫描正在运行中的程序并比较它们的内存,如果发现它们的内存区域或内存页是完全相同的,就将相同的内存合并为一个单一的内存页,并将其标识为“写时复制(copy-on-write) ",这样可以起到节省系统内存使用量的作用。如果有进程试图去修改被合并且被标识为“写时复制"的内存页,就为该进程复制出一个新的内存页供其使用。
在QEMU/KVM中,一个KVM虚拟机就是一个QEMU进程,所以使用KSM也可以实现多个KVM虚拟机之间相同内存合并。如果在同一KVM宿主机上的多个KVM虚拟机运行的是相同的操作系统或应用程序,则KVM虚拟机之间的相同内存页数量就可能比较多,这种情况下使用KSM的效果就会更加显著。在KVM环境下使用KSM 只有那些相同的内存页才是可以被共享合并的,并且KSM只会识别并合并那些不会干扰客户机运行、不会影响KVM宿主机或KVM虚拟机的安全内存页。因此,在KVM虚拟化环境中,KSM能够提高内存的利用率。
KSM最初是为了在KVM虚拟化中使用而开发的,不过它对非虚拟化系统依然非常有用。KSM可以提高KVM宿主机中内存的使用效率,所以一般建议开启KSM功能。由于 KSM必须有一个或多个进程去检测和找出完全相同且可以用于合并的内存页,所以KSM 虽然能够让内存使用量降低,但是KVM宿主机中的CPU使用量会有一定程度的升高,因此可能会带来隐蔽的性能问题。在实际生产环境中使用KSM需要进行适当配置,以便达到较好的平衡。KSM节省内存的效果与KVM虚拟机操作系统及KVM虚拟机中运行的应用程序有关,如果KVM虚拟机上的操作系统及其上运行的应用程序相同,节省内存的效果就会很显著,甚至有可能节省超过50%的内存。反之,如果KVM虚拟机操作系统不同,且运行的应用程序也都大不相同,KSM节省内存的效果就不明显,节省的内存甚至可能达不到 5%。
在使用KSM时,为了防止内存过载,最好保证系统的交换分区(swap space)足够大。虽然KSM可以通过内存页合并而减少内存使用量,但是KVM虚拟机在运行过程中可能会修改KSM合并的内存页。修改这些内存页采用的方式是将这些内存页先复制出来,再进行修改,这样就会占用内存空间,因此可能会导致系统内存不足,这时就需要足够的交换空间来保证系统的正常运行。
三.实验步骤
主机 |
操作系统 |
IP地址 |
主要软件 |
kvm01 |
CentOS7.9 x86_64 |
192.168.10.201 |
Qemu-kvm、libvirt |
kvm02 |
CentOS7.9 x86_64 |
192.168.10.202 |
Qemu-kvm、libvirt、qemu-kvm-ev |
kvmnfs |
CentOS7.9 x86_64 |
192.168.10.101 |
nfs-utils |
先将CentOS-7-x86_64-DVD-2009.iso拷贝到/opt下
1.通过VNC Viewer安装虚拟机
在源宿主机上准备虚拟机
(1)用virt-install 命令安装虚拟机并设置VNC Viewer连接端口
systemctl stop firewalld
systemctl disable firewalld
mkdir -p /data_kvm/store
virt-install -n test01 -r 1024 --vcpus=1 --disk path=/data_kvm/store/test01.qcow2,size=10 -w bridge:br0 --virt-type=kvm --accelerate --autostart -c /opt/CentOS-7-x86_64-DVD-2009.iso --vnc --vncport=5901 --vnclisten=0.0.0.0
备注:
-n:指定虚拟机的名字。
-r:指定内存大小。
--vcpu:指定虚拟 CPU 个数。
--disk:指定磁盘文件放置位置及大小。
-w:制定所使用的网桥。
--autostart:设置虚拟机在宿主机开机时启动。
-c:指定镜像文件。
--vncport:通过 vnc viewer 连接的端口。
--vnclisten:通过 vnc
--accelerate:当安装qemu客户机时,如果支持可用kvm或kqemu内核加速能力,KVM加速器
备注:
执行此命令时会有报错提示,如下所示,使用文本方式安装会有这个提示。意思是告诉用户没有图形界面,
可以使用VNC远程连接过来进行安装,
ERROR
unsupported format character '奠(0xffffffe7) at index 47
域安装失败,您可以运行下列命令重启您的域:
'virsh start virsh --connect qemu:///system start test01'
否则请重新开始安装。
(2)在windows宿主机上安装VNC Viewer
(3)打开VNC Viewer,新建一个连接,连接上后,安装虚拟机,
注意:填写的IP地址(192.168.10.201)是Linux宿主机的IP地址,开放的端口号5901映射到了test01虚拟机。连接成功后,就可以开始安装虚拟机了。
(4)安装后查看
virsh list --all
(5)启动虚拟机
virsh start test01
安装完后,虚拟机是关闭状态
(6)在vnc终端上再次连接test01虚拟机并登录系统
2.静态迁移
提取磁盘和配置文件
(1)查看虚拟机test01当前状态
virsh list --all
(2)关闭虚拟机test01
virsh shutdown test01
virsh list --all
(3)导出虚拟机test01的xml配置文件
virsh dumpxml test01 > test01.xml
ll
(4)定位虚拟机test01的磁盘文件
virsh domblklist test01
(5)拷贝配置文件和磁盘文件到目标宿主机kvm02上
在kvm上创建目录
mkdir -p /data_kvm/store
到kvm01上拷贝文件到kvm02上
scp test01.xml 192.168.10.202:/etc/libvirt/qemu/
scp /data_kvm/store/test01.qcow2 192.168.10.202:/data_kvm/store/
3.在kvm02上配置和启动目标虚拟机
(1)查看被迁移过来的配置文件和磁盘文件
ls -l /etc/libvirt/qemu
ls -l /data_kvm/store/
(2)重新定义虚拟机 test01
virsh list --all
virsh define /etc/libvirt/qemu/test01.xml
virsh list --all
(3)启动虚拟机 test01
virsh start test01
virsh list --all
(4)连接虚拟机 test01 ,查看主机名
virt-manager
打开虚拟机管理器,查看虚拟机的运行
三.基于共享存储的动态迁移
1. 配置 NFS 共享存储
(1)打开一个新的服务器kvmnfs ,在 kvmnfs 服务器上面安装 NFS 服务
systemctl stop firewalld
setenforce 0
hostnamectl set-hostname kvmnfs
bash
yum -y install nfs-utils
备注:
两台kvm主机的selinux的状态要一致。
(2)配置共享目录
mkdir /data
chown -R 777 /data/
vim /etc/exports
/data 192.168.10.0/24(rw,sync,no_root_squash)
(3)启动并查看 NFS 服务
systemctl enable nfs
systemctl enable rpcbind
systemctl start nfs
systemctl start rpcbind
showmount -e localhost
2. 挂载 NFS 目录
(1)源宿主机 kvm01 上查看 NFS 共享目录
showmount -e 192.168.10.101
(2)源宿主机 kvm01 和kvm02上创建 kgc 目录
mkdir /data_kvm/kgc
mkdir /data_kvm/kgc
(3)源宿主机 kvm01 和kvm02上都挂载共享目录
mount -t nfs 192.168.10.101:/data /data_kvm/kgc
mount
mount -t nfs 192.168.10.101:/data /data_kvm/kgc
mount
(4)源宿主机 kvm01 上设置自动挂载
vim /etc/fstab
192.168.10.101:/data /data_kvm/kgc nfs defaults 0 0
3:通过现有的磁盘文件生成虚拟机
(1)拷贝qcow2磁盘文件
将实验用到的系统镜像上传到KVM主机的root家目录中。这里直接使用CentOS官方提供的qcow2格式的系统镜像(CentOS-7-x86_64-GenericCloud-2009.qcow2),这个镜像可以直接部署到kvm或openstack的平台中。
cp /opt/CentOS-7-x86_64-GenericCloud-2009.qcow2 /data_kvm/kgc/test02.qcow2
(2)部署虚拟机
yum -y install libguestfs-tools
备注:
该工具提供了virt的高级命令,其中有一个virt-customize命令,可以为系统镜像设置密码。
virt-customize -a /data_kvm/kgc/test02.qcow2 --root-password password:aptech
virt-install \
--name=test02 \
-r 1024 \
--vcpus=1 \
--disk device=disk,bus=virtio,path='/data_kvm/kgc/test02.qcow2',size=10 \
-w bridge:br0 \
--virt-type=kvm \
--boot hd
备注:
--disk:指定存储设备及其属性
device:设备类型,如cdrom、disk或floppy等,默认为disk;
bus:磁盘总线类型,其值可以为ide、scsi、usb、virtio或xen
--virt-type:使用的hypervisor(虚拟机监视器),如kvm、qemu、xen等
--boot cdrom,hd,network:指定引导次序;
(3)登录测试
备注:
如果觉得慢,此处可以将原有的虚拟机克隆出来
virt-clone -o test01 -n test02 -f /data_kvm/kgc/test02.qcow2
virsh list --all
virsh domblklist test02
4. 动态迁移
(1)查看 kvm01 和 kvm02 两台宿主机上虚拟机的运行状态
virsh list --all
virsh list --all
(2)在源宿主机 kvm01 上执行迁移命令
virsh shutdown test02
virsh edit test02
添加红色部分
<devices>
<emulator>/usr/libexec/qemu-kvm</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2' cache='none'/>
<source file='/data/kgc/test02.qcow2'/>
<target dev='vda' bus='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
virsh start test02
Domain test02 started
virsh list --all
virsh migrate --live --verbose test02 qemu+ssh://192.168.10.202/system tcp://192.168.10.202
备注:
migrate :迁移
--verbose :显示迁移的进度
--live:实时迁移
(4)查看迁移后虚拟机的状态
[root@kvm01 ~]# virsh list --all
[root@kvm02 ~]# virsh list --all
迁移之后源宿主机 kvm01 上虚拟机 test02 被关闭,目标宿主机 kvm02 上虚拟机 test02
处于启动状态
5. 生成配置文件
(1)创建虚拟机 test02 配置文件
[root@kvm02 ~]# ls -l /etc/libvirt/qemu
[root@kvm02 ~]# virsh dumpxml test02 > /etc/libvirt/qemu/test02.xml
[root@kvm02 ~]# cd /etc/libvirt/qemu/
[root@kvm02 qemu]# ll
(2)定义虚拟机 test02 配置文件
[root@kvm02 qemu]# virsh define /etc/libvirt/qemu/test02.xml
四: 基于数据块的动态迁移
1. 在kvm01和kvm02上安装依赖包
设置好阿里的yum源
[root@kvm02 ~]# yum -y install centos-release-qemu-ev
[root@kvm02 ~]# vim /etc/yum.repos.d/CentOS-QEMU-EV.repo
[centos-qemu-ev]
name=CentOS-$releasever - QEMU EV
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=virt-kvm-common
baseurl=http://mirrors.aliyun.com/$contentdir/$releasever/virt/$basearch/kvm-common/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-SIG-Virtualization
[root@kvm02 ~]# yum -y install qemu-kvm-ev
安装后重启系统
重启后注意检查防火墙的状态,要处于关闭状态
2. 迁移前准备工作
(1)源宿主机 kvm01 上的准备
[root@kvm01 ~]# vim /etc/hosts
192.168.10.201 kvm01
192.168.10.202 kvm02
[root@kvm01 ~]# virsh list --all
[root@kvm01 ~]# virsh shutdown test01
[root@kvm01 ~]# virt-clone -o test01 -n test03 -f /data_kvm/store/test03.qcow2
(2)目标宿主机 kvm02 上的准备
[root@kvm02 ~]# vim /etc/hosts
192.168.10.201 kvm01
192.168.10.202 kvm02
备注:
要确保kvm02主机没有同名的虚拟机
以下步骤是为了确保kvm02上没有同名的虚拟机,如果确定没有,就忽略
[root@kvm02 ~]# virsh list --all
[root@kvm02 ~]# virsh undefine test01
[root@kvm02 ~]# cd /data_kvm/store/
[root@kvm02 store]# ls
[root@kvm02 store]# rm -rf test01.qcow2
[root@kvm02 store]# virsh list --all
3. 在kvm02主机上检查资源池
[root@kvm02 store]# virsh pool-list --all
备注:
如果没有创建存储池,此处可能什么都没有,这是正常的
- 在kvm02主机上创建同名磁盘文件
[root@kvm02 ~]# mkdir -p /data_kvm/store
[root@kvm02 store]# qemu-img create -f qcow2 /data_kvm/store/test03.qcow2 20G
5. 在kvm01主机上执行迁移操作
[root@kvm01 ~]# virsh start test03
[root@kvm01 ~]# virsh migrate test03 qemu+ssh://192.168.10.202/system --live --persistent --undefinesource --copy-storage-all --verbose
备注:
--live:实时迁移
--persistent :将域保留为目标主机物理机器的持久性状态
--undefinesource:删除源主机物理机器上的客户机虚拟机
--copy-storage-all :使用全磁盘复制的非共享存储进行迁移
--verbose:显示迁移的进度
备注:
如果提示:
“错误:不支持的配置:Hypervisor 不支持 CPU 型号 Broadwell-noTSX-IBRS“
需要安装软件包如下:
yum -y install centos-release-qemu-ev
yum -y install qemu-kvm-ev
6. 验证迁移结果
[root@kvm01 ~]# virsh list --all
[root@kvm02 store]# virsh list --all
五:KSM
1: KSM 服务介绍
Linux内核特性称为Kernel Shared Memory(基于内核的共享内存)或Kernel Samepage Merging。KSMD作为守护进程,能够合并内存页面来增加并发虚拟机的数量。KSM 适用于宿主机过载的情况下。KSM 通过减少每个虚拟机实际占用的内存数,可以让多个虚拟机分配的内存数量之和大于物理内存数量。而对于相同类型的虚拟机,在物理内存量不变的情况下,可以在一个宿主机中创建更多虚拟机,从而提高虚拟化部署的密度,同时也可以提高物理资源的利用效率。
(1)检查当前 Linux 系统是否支持 KSM
[root@kvm02 ~]# egrep -i ksm /boot/config-3.10.0-1160.el7.x86_64
CONFIG_KSM=y
(2)ksmd服务的配置文件
[root@kvm02 ~]# ls -l /sys/kernel/mm/ksm/
备注:
KSM 的常用配置的作用分别如下所示。
- max_page_sharing:设置每个 KSM 页面允许的最大共享数量。这个配置设置了重复数据删除限制,以避免虚拟内存 rmap 列表变得太大。max_page_sharing 最小值为 2,因为新创建的 KSM 页面至少有两个共享器。
- merge_across_nodes:指定是否可以合并来自不同 numa 节点的页面。当设置为 0 时,ksm 只合并物理页面并驻留在同一 numa 节点的内存区域中,可以降低访问共享页面的延迟。
- pages_to_scan:在 KSM 进程休眠之前会去扫描的内存数量。
- run:控制 ksmd 进程是否运行,默认值为 0。要激活 ksm 必须设置其值为 1。如果设置为 0,表示停止运行 ksmd, 但会保留已经合并的内存页;如果设置为 1,表示马上运行 ksmd 进程;设置为 2 表示停止运行 ksmd,并分离已经合并的所有内存页,但是保留已经注册为合并的内存区域给下一次使用。
- sleep_millisecs:设置 ksmd 进程休眠的时间(单位:毫秒),即为 ksmd 进程两次运行之间的间隔。
- stable_node_chains_prune_millisecs: 在 stable_node“ 链 ” 中 链 接 的 整 个stable_node“dups”列表被周期性地扫描,以删除陈旧的 stable_nodes。该参数的值用于调节重复扫描的时间(单位:毫秒)。
2:配置 KSM 优化内存
(1)先将虚拟机test01克隆出三份
[root@kvm02 ~]# virt-clone -o test01 -n test02 -f /data_kvm/store/test02.qcow2
[root@kvm02 ~]# virt-clone -o test01 -n test03 -f /data_kvm/store/test03.qcow2
[root@kvm02 ~]# virt-clone -o test01 -n test04 -f /data_kvm/store/test04.qcow2
注意:
克隆虚拟机,源虚拟机需要关闭状态
(2)开启所有的虚拟机
[root@kvm02 ~]# virsh start test01
[root@kvm02 ~]# virsh start test02
[root@kvm02 ~]# virsh start test03
[root@kvm02 ~]# virsh start test04
(3)查看Linux宿主机的内存使用情况
[root@kvm02 ~]# free
total used free shared buff/cache available
Mem: 3861288 2464360 135440 15208 1261488 1157748
Swap: 4194300 2834 4194300
- 启动 KSM 服务
检查/sys/kernel/mm/ksm/run的值是否为1,如果不是,修改为1
[root@kvm02 ~]# echo 1 > /sys/kernel/mm/ksm/run
[root@kvm02 ~]# systemctl start ksm
[root@kvm02 ~]# systemctl start ksmtuned
重启系统
打开这些虚拟机
(5)再次查看Linux宿主机的内存使用情况
[root@kvm02 ~]# free
total used free shared buff/cache available
Mem: 3861288 2449008 103556 15212 1308724 1173004
Swap: 4194300 0 4194300