目录
一、案例分析
1.1、案例概述
1.2、案例前置知识点
1)KVM 虚拟机迁移
2)KSM 内核同页合并
1.3、案例环境
1)本案例环境
2)案例需求
3)案例实现思路
二、案例实施
2.1、静态迁移
1)在源宿主机上准备虚拟机
2)提取磁盘和配置文件
3)配置和启动目标虚拟机
2.2、基于共享存储的动态迁移
1)配置 NFS 共享存储
2)挂载 NFS 目录
3)创建动态迁移的虚拟机
4)动态迁移
5)生成配置文件
6)验证迁移结果
2.3、基于数据块的动态迁移
1)依赖包安装
2) 迁移前准备工作
3)检查资源池
4)创建同名磁盘文件
5)执行迁移操作
6)验证迁移结果
2.4、KSM
1)KSM 服务介绍
2)配置 KSM 优化内存
一、案例分析
1.1、案例概述
企业内部为了使服务器资源达到最大化利用,通常都会进行 KVM 虚拟化,每台服务器上运行多台 KVM 虚拟机。随着 KVM 虚拟机数量的不断增多,个别服务器会出现资源过载现象,这时候就需要对部分 KVM 虚拟机进行迁移,迁移到负载相对较低的服务器上。
为了解决以上问题,针对可停机的 KVM 虚拟机,可使用静态迁移的方式来迁移 KVM 虚拟机。针对在线提供服务、不可停机的 KVM 虚拟机,可使用基于共享存储的动态迁移或基于数据块的动态迁移来完成迁移工作。最终按业务类型将虚拟机重新调配、合理布局,以保证服务器一直处于良好的运行状态。除了迁移之外,还可以在 KVM 宿主机上开启 KSM 内核同页合并,以达到节省内存、降低负载的目的。
1.2、案例前置知识点
1)KVM 虚拟机迁移
KVM 虚拟机迁移,是将某一虚拟机上的环境和软件完全复制到另一台物理机上继续运行。KVM 虚拟机迁移可以优化系统负载、重新规划 KVM 虚拟机布局并简化 KVM 虚拟机的管理维护工作。
KVM 虚拟机迁移的主要应用场景如下所示。
- 当一台 KVM 宿主机的负载比较高时,可将源 KVM 宿主机上的部分虚拟机迁移到负载较低的 KVM 宿主机中,以保证服务质量。
- 通过 KVM 虚拟机迁移将多台负载较低的 KVM 宿主机上的 KVM 虚拟机集中迁移到某一 台 KVM 宿主机上,从而达到节约资源的目的。
- 在升级 KVM 宿主机硬件设备时,可以将 KVM 宿主机上运行的 KVM 虚拟机迁移到其他 KVM 宿主机上,以解决对硬件的依赖,从而实现业务不中断情况下对物理硬件设备的升级。
- 跨地域迁移,实现 KVM 虚拟机的远程迁移。
根据迁移方式的不同,可将迁移分为静态迁移(static magration)和动态迁移(live migration)。二者的区别是:静态迁移时会有一段时间虚拟机中的服务是不可用的,而动态迁移则没有明显的服务暂停时间。
- 静态迁移
静态迁移需要先关闭要迁移的 KVM 虚拟机,并拷贝它的磁盘文件和配置文件到目标 KVM 宿主机,然后恢复启动,从而实现静态迁移。如果 KVM 虚拟机的磁盘文件存储在 KVM 宿主机本地,在静态迁移时需要拷贝磁盘文件和配置文件;如果 KVM 虚拟机的磁盘文件存储在共享存储上,在静态迁移时,只需要拷贝 KVM 虚拟机的配置文件,KVM 虚拟机的磁盘文件可通过挂载共享存储到本地目录的方式来获取。针对 KVM 虚拟机磁盘文件存储位置 的不同,在静态迁移时需要做适当的调整。
- 动态迁移
动态迁移是保证 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 虚拟机只使用本地存储,不再需要共享存储的支持,因此迁移环境比较简单, 迁移的源宿主机和目标宿主机只需要保持以太网连接即可。因为少了共享存储,所以降低了动态迁移的难度。
2)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 合并的内存页。修改这些内存页采用的方式是将这些内存页先复制出来,再进行修改,这样就会占用内存空间,因此可能会导致系统内存不足,这时就需要足够的交换空间来保证系统的正常运行。
1.3、案例环境
1)本案例环境
本案例中使用三台服务器模拟 KVM 虚拟机迁移,具体的网络拓扑如下图所示。
动态迁移
案例环境如下表所示:
主机 | 操作系统 | IP 地址 | 主要软件 |
kvm01 | CentOS 7.6 x86 | 192.168.23.213 | Qemu-kvm、libvirt |
kvm02 | CentOS 7.6 x86 | 192.168.23.214 | Qemu-kvm、libvirt、qemu-kvm-ev |
kvmnfs | CentOS 7.6 x86 | 192.168.23.215 | nfs-utils |
2)案例需求
- 通过静态迁移实现 KVM 虚拟机的迁移。
- 通过基于共享存储的动态迁移方式实现 KVM 虚拟机的迁移。
- 通过基于数据块的动态迁移方式实现 KVM 虚拟机的迁移。
- 实现 KSM 内存优化。
3)案例实现思路
- 通过拷贝磁盘文件和配置文件的方式实现静态迁移。
- 通过配置 NFS 共享服务,实现基于共享存储的动态迁移。
- 通过基于数据块的方式实现动态迁移。
- 针对同类型 KVM 虚拟机和应用使用 KSM 来优化内存。
二、案例实施
2.1、静态迁移
使用源宿主机 kvm01 和目标宿主机 kvm02 来完成静态迁移。首先在源宿主机 kvm01 上创建虚拟机 test01,虚拟机 test01 的数据放在本地磁盘。然后将虚拟机 test01 从源宿主机 kvm01 迁移到目标宿主机 kvm02 上,并进行一些相应的配置。
1)在源宿主机上准备虚拟机
在源宿主机 kvm01 上进行迁移前的准备工作。
[root@centos7-13 ~]# hostnamectl set-hostname kvm01
[root@centos7-13 ~]# bash
[root@kvm01 ~]# yum -y install qemu-kvm qemu-kvm-tools virt-install qemu-img bridge-utils libvirt
[root@kvm01 ~]# cat /proc/cpuinfo | grep vmx
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon rep_good nopl xtopology tsc_reliable nonstop_tsc eagerfpu pni pclmulqdq vmx ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 arat umip pku ospke gfni vaes vpclmulqdq movdiri movdir64b md_clear spec_ctrl intel_stibp flush_l1d arch_capabilities
[root@kvm01 ~]# lsmod | grep kvm
kvm_intel 188740 0
kvm 637515 1 kvm_intel
irqbypass 13503 1 kvm
[root@kvm01 ~]# systemctl start libvirtd
[root@kvm01 ~]# systemctl enable libvirtd
[root@kvm01 ~]# cd /etc/sysconfig/network-scripts/
[root@kvm01 network-scripts]# cp ifcfg-ens32 ifcfg-br0
[root@kvm01 network-scripts]# vim ifcfg-ens32
TYPE="Ethernet"
PROXY_METHOD="none"
BROWSER_ONLY="no"
BOOTPROTO="none"
DEFROUTE="yes"
IPV4_FAILURE_FATAL="no"
NAME="ens32"
UUID="eebf1a51-e1aa-482d-91c6-178818b3ecd8"
DEVICE="ens32"
ONBOOT="yes"
#IPADDR="192.168.23.213"
#PREFIX="24"
#GATEWAY="192.168.23.2"
#DNS1="202.96.128.86"
BRIDGE=br0
[root@kvm01 network-scripts]# vim ifcfg-br0
TYPE="Bridge"
PROXY_METHOD="none"
BROWSER_ONLY="no"
BOOTPROTO="none"
DEFROUTE="yes"
IPV4_FAILURE_FATAL="no"
NAME="br0"
DEVICE="br0"
ONBOOT="yes"
IPADDR="192.168.23.213"
PREFIX="24"
GATEWAY="192.168.23.2"
DNS1="202.96.128.86"
[root@kvm01 network-scripts]# systemctl restart network
[root@kvm01 network-scripts]# ip add | grep br0
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP group default qlen 1000
3: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
inet 192.168.23.213/24 brd 192.168.23.255 scope global noprefixroute br0
[root@kvm01 ~]# fdisk /dev/sdb
[root@kvm01 ~]# mkfs.xfs /dev/sdb1
[root@kvm01 ~]# mkdir /data
[root@kvm01 ~]# mount /dev/sdb1 /data
[root@kvm01 ~]# vim /etc/fstab
......//省略部分内容
/dev/sdb1 /data xfs defaults 0 0
[root@kvm01 ~]# cd /data/
[root@kvm01 data]# mkdir store iso
[root@kvm01 data]# ls
iso store
[root@kvm01 ~]# ll -h /data/iso/ 将镜像上传
总用量 4.5G
-rw-r--r-- 1 root root 4.5G 4月 9 11:02 CentOS-7-x86_64-DVD-2207-02.iso
- 创建虚拟机 test01
创建虚拟机 test01 的方法既可以参考之前章节使用 virt-manager 图形界面创建虚拟机,也可以在文本格式下使用 virt-install 命令来创建虚拟机。本章使用 virt-install 命令在源宿主机 kvm01 上面创建虚拟机 test01。在执行 virt-install 命令之前,需要提前准备 VNC Viewer 软件,其主要作用是在本地 Windows 上来连接 KVM 虚拟机,方便管理。VNC Viewer 软件如下图所示。
VNC Viewer 软件界面
单击上图中菜单栏的“File”,选择“New connection”,新建到虚拟机的连接。“VNC Server” 和“Name”填写宿主机的 IP 地址,如下图所示。其中,“5901”是执行 virt-install 安装命令时分配给对应虚拟机的端口,可以自己定义,通常都是以 5901 开始逐个递增。
创建 VNC 连接
单击“OK”确认之后,会生成对应的连接。如下图所示
VNC 连接生成
以上 VNC 的相关配置完成后,就可以通过文本方式创建 test01 虚拟机了。具体操作命令如下所示。
[root@kvm01 ~]# virt-install -n test01 -r 1024 --vcpus=1 --disk path=/data/store/test01.qcow2,size=10 -w bridge:br0 --virt-type=kvm --accelerate --autostart -c /data/iso/CentOS-7-x86_64-DVD-2207-02.iso --vnc --vncport=5901 --vnclisten=0.0.0.0
virt-install 安装命令各选项的具体作用如下所示:
- -n:指定虚拟机的名字。
- -r:指定内存大小。
- --vcpu:指定虚拟 CPU 个数。
- --disk:指定磁盘文件放置位置及大小。
- -w:制定所使用的网桥。
- --autostart:设置虚拟机在宿主机开机时启动。
- -c:指定镜像文件。
- --vncport:通过 vnc viewer 连接的端口。
- --vnclisten:通过 vnc viewer 连接的 IP。
上述命令执行后忽略如下所示报错信息,立刻双击打开上图中 VNC Viewer 创建的连接“192.168.23.213:5901”。
WARNING 未检测到操作系统,虚拟机性能可能会受到影响。使用 --os-variant 选项指定操作系统以获得最佳性能。
WARNING 无法连接到图形控制台:没有安装 virt-viewer。请安装 'virt-viewer' 软件包。
WARNING 没有控制台用于启动客户机,默认为 --wait -1
开始安装......
正在分配 'test01.qcow2' | 10 GB 00:00:00
ERROR unsupported format character '奠(0xffffffe7) at index 47
域安装失败,您可以运行下列命令重启您的域:
'virsh start virsh --connect qemu:///system start test01'
否则请重新开始安装。
之所以会出现上述“WARNING”和“ERROR”信息,是因为宿主机的 CentOS 系统采用了文本方式安装,没有图形化界面。这种情况不影响虚拟机的正常使用,可使用 VNC Viewer 软件来开始 CentOS 系统的安装,如下图所示。
test01 虚拟机安装界面
通过 VNC Viewer 安装 test01 虚拟机的具体过程这里省略,实际就是 CentOS 7.6 系统的安装过程,等虚拟机的操作系统安装完成后,test01 虚拟机就安装完成了 。
- 配置虚拟机 test01 可通过 console 登录
如果在宿主机 kvm01 上想要实现通过 virsh console 命令连接到虚拟机 test01,需要在 test01 虚拟机上进行如下配置。
添加 ttyS0 终端
- 标记虚拟机 test01 当前 IP 地址
[root@kvm01 ~]# virsh console test01
连接到域 test01
换码符为 ^] //输入 Enter 键
CentOS Linux 7 (Core)
Kernel 3.10.0-1160.71.1.el7.x86_64 on an x86_64
test01 login: root
Password:
Last login: Tue Apr 9 11:40:53 on tty1
[root@test01 ~]# ip add | grep ens3
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
inet 192.168.23.142/24 brd 192.168.23.255 scope global noprefixroute dynamic ens3
从上述命令执行结果中可以得知,迁移前虚拟机 test01 的 IP 地址是 192.168.23.142。若想从虚拟机 test01 中退出,可以使用“Ctrl+]”组合键来实现。
2)提取磁盘和配置文件
在宿主机 kvm01 上,将虚拟机 test01 的磁盘文件和 xml 配置文件上传到目标宿主机 kvm02 上。
- 查看虚拟机 test01 当前状态
[root@kvm01 ~]# virsh list --all
Id 名称 状态
----------------------------------------------------
2 test01 running
- 关闭虚拟机 test01
[root@kvm01 ~]# virsh shutdown test01
域 test01 被关闭
[root@kvm01 ~]# virsh list --all
Id 名称 状态
----------------------------------------------------
- test01 关闭
- 导出虚拟机 test01 的 xml 配置文件
[root@kvm01 ~]# virsh dumpxml test01 > ~/test01.xml
[root@kvm01 ~]# ll
总用量 8
-rw-------. 1 root root 1769 3月 26 09:49 anaconda-ks.cfg
-rw-r--r-- 1 root root 3408 4月 9 11:49 test01.xml
- 定位虚拟机 test01 的磁盘文件
[root@kvm01 ~]# virsh domblklist test01
目标 源
------------------------------------------------
hda /data/store/test01.qcow2
hdb -
- 拷贝配置文件和磁盘文件到目标宿主机 kvm02 上
[root@kvm01 ~]# scp test01.xml 192.168.23.214:/etc/libvirt/qemu/
The authenticity of host '192.168.23.214 (192.168.23.214)' can't be established.
ECDSA key fingerprint is SHA256:zOL41F94RnflLuQ0Nn2JjhdpUfPLQFnaw7WPJJ3XXgw.
ECDSA key fingerprint is MD5:3c:83:19:bf:6f:5e:92:c9:72:a1:6c:8d:b6:f4:70:d7.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.23.214' (ECDSA) to the list of known hosts.
root@192.168.23.214's password:
test01.xml 100% 3408 1.5MB/s 00:00
[root@kvm01 ~]# scp /data/store/test01.qcow2 192.168.23.214:/data/store/
root@192.168.23.214's password:
test01.qcow2 100% 10GB 60.4MB/s 02:49
3)配置和启动目标虚拟机
在目标宿主机 kvm02 上,对拷贝过来的虚拟机 test01 的数据进行重新定义,启动之后验证虚拟机 test01 的 IP 地址信息是否正确。
- 查看被迁移过来的配置文件和磁盘文件
[root@kvm02 ~]# ls /etc/libvirt/qemu/
networks test01.xml
[root@kvm02 ~]# ls /data/store/
test01.qcow2
- 重新定义虚拟机 test01
[root@kvm02 ~]# virsh list --all
Id 名称 状态
----------------------------------------------------
[root@kvm02 ~]# virsh define /etc/libvirt/qemu/test01.xml
定义域 test01(从 /etc/libvirt/qemu/test01.xml)
[root@kvm02 ~]# virsh list --all
Id 名称 状态
----------------------------------------------------
- test01 关闭
- 启动虚拟机 test01
[root@kvm02 ~]# virsh start test01
域 test01 已开始
[root@kvm02 ~]# virsh list --all
Id 名称 状态
----------------------------------------------------
1 test01 running
- 连接虚拟机 test01 并验证 IP 地址信息
[root@kvm02 ~]# virsh console test01
连接到域 test01
换码符为 ^] //按 Enter 键进入 test01
CentOS Linux 7 (Core)
Kernel 3.10.0-1160.71.1.el7.x86_64 on an x86_64
test01 login: root
Password:
Last login: Tue Apr 9 11:44:11 on ttyS0
[root@test01 ~]# ip add | grep ens3
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
inet 192.168.23.142/24 brd 192.168.23.255 scope global noprefixroute dynamic ens3
至此虚拟机 test01 已实现从源宿主机 kvm01 到目标宿主机 kvm02 的静态迁移。
2.2、基于共享存储的动态迁移
在 kvmnfs 服务器上部署 NFS 服务并创建共享目录实现共享存储。在源宿主机 kvm01 和目标宿主机 kvm02 上分别挂载共享目录。被迁移虚拟机的磁盘文件存储在共享目录内, 最终实现虚拟机从源宿主机 kvm01 迁移到目标宿主机 kvm02 上。
1)配置 NFS 共享存储
在 kvmnfs 服务器上面配置 NFS 服务实现共享存储。
- 在 kvmnfs 服务器上面安装 NFS 服务
[root@kvmnfs ~]# yum -y install nfs-utils
- 配置共享目录
在 NFS 服务的配置文件 /etc/exports 中,配置共享目录及相应权限。设置 192.168.23.0/24 网段对/data 共享目录可读写、同步共享目录等权限。
[root@kvmnfs ~]# mkdir /data
[root@kvmnfs ~]# vim /etc/exports
/data 192.168.23.0/24(rw,sync,no_root_squash)
- 启动并查看 NFS 服务
[root@kvmnfs ~]# systemctl enable nfs
[root@kvmnfs ~]# systemctl enable rpcbind
[root@kvmnfs ~]# systemctl start nfs
[root@kvmnfs ~]# systemctl start rpcbind
[root@kvmnfs ~]# showmount -e localhost
Export list for localhost:
/data 192.168.23.0/24
2)挂载 NFS 目录
在 kvm01 和 kvm02 两台宿主机上,先创建本地数据目录,之后再分别挂载 NFS 目录, 并设置开机自动挂载。下面以宿主机 kvm01 为例进行操作演示。
- 源宿主机 kvm01 上查看 NFS 共享目录
[root@kvm01 ~]# showmount -e 192.168.23.215
Export list for 192.168.23.215:
/data 192.168.23.0/24
- 源宿主机 kvm01 上创建 kgc 目录
[root@kvm01 ~]# mkdir /data/kgc
- 源宿主机 kvm01 上挂载共享目录
[root@kvm01 ~]# mount -t nfs 192.168.23.215:/data /data/kgc/
[root@kvm01 ~]# mount
......//省略部分内容
192.168.23.215:/data on /data/kgc type nfs4 (rw,relatime,vers=4.1,rsize=262144,wsize=262144,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=192.168.23.213,local_lock=none,addr=192.168.23.215)
- 源宿主机 kvm01 上设置自动挂载
[root@kvm01 ~]# vim /etc/fstab
......//省略部分内容
192.168.23.215:/data /data/kgc nfs defaults 0 0
3)创建动态迁移的虚拟机
在源宿主机 kvm01 上,新建虚拟机 test02,用于测试基于共享存储的动态迁移。
- 创建虚拟机 test02
创建虚拟机 test02,创建完后查看虚拟机 test02 当前状态。虚拟机 test02 的虚拟磁盘存放到了之前创建的共享目录/data/kgc 下。
[root@kvm01 ~]# virt-install -n test02 -r 1024 --vcpus=1 --disk path=/data/kgc/test02.qcow2,size=10 -w bridge:br0 --virt-type=kvm --accelerate --autostart -c /data/iso/CentOS-7-x86_64-DVD-2207-02.iso --vnc --vncport=5902 --vnclisten=0.0.0.0
[root@kvm01 ~]# virsh list --all
Id 名称 状态
----------------------------------------------------
4 test02 running
- test01 关闭
[root@kvm01 ~]# virsh domblklist test02
目标 源
------------------------------------------------
hda /data/kgc/test02.qcow2
hdb -
- 登录虚拟机 test02 并查看 IP 地址
[root@kvm01 ~]# virsh console test02
连接到域 test02
换码符为 ^] //按 Enter 键进入 test02
CentOS Linux 7 (Core)
Kernel 3.10.0-1160.71.1.el7.x86_64 on an x86_64
test02 login: root
Password:
Last login: Tue Apr 9 14:34:02 on tty1
[root@test02 ~]# ip add | grep ens3
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
inet 192.168.23.143/24 brd 192.168.23.255 scope global noprefixroute dynamic ens3
从上述命令执行结果可以得知,虚拟机 test02 的 IP 地址是 192.168.23.143
4)动态迁移
- 查看 kvm01 和 kvm02 两台宿主机上虚拟机的运行状态
[root@kvm01 ~]# virsh list --all
Id 名称 状态
----------------------------------------------------
4 test02 running //kvm01 上 test02 运行
- test01 关闭
[root@kvm02 ~]# virsh list --all
Id 名称 状态
----------------------------------------------------
- test01 关闭 //kvm02 上无 test02
- 在源宿主机 kvm01 上执行迁移命令
在开始执行迁移操作之前,首先在本地 Windows 机器上面 ping 虚拟机 test02 的 IP 地址,用于迁移过程中观察是否存在网络中断情况。具体的 ping 命令如下图所示。
下面开始执行迁移操作。
[root@kvm01 ~]# virsh migrate --live --verbose test02 qemu+ssh://192.168.23.214/system tcp://192.168.23.214
root@192.168.23.214's password:
错误:不安全的迁移:Migration may lead to data corruption if disks use cache != none or cache != directsync
如果迁移命令在执行时出现上述错误,根据提示修改虚拟机 test02 的配置文件,加入标注为红色的字体部分,具体方法如下。
[root@kvm01 ~]# virsh shutdown test02
域 test02 被关闭
[root@kvm01 ~]# virsh edit test02
......//省略部分内容
33 <devices>
34 <emulator>/usr/libexec/qemu-kvm</emulator>
35 <disk type='file' device='disk'>
36 <driver name='qemu' type='qcow2' cache="none"/> //在36行添加 cache="none"
37 <source file='/data/kgc/test02.qcow2'/>
38 <target dev='hda' bus='ide'/>
39 <address type='drive' controller='0' bus='0' target='0' unit='0'/>
40 </disk>
......//省略部分内容
[root@kvm01 ~]# virsh start test02
域 test02 已开始
[root@kvm01 ~]# virsh list --all
Id 名称 状态
----------------------------------------------------
5 test02 running
- test01 关闭
[root@kvm01 ~]# virsh migrate --live --verbose test02 qemu+ssh://192.168.23.214/system tcp://192.168.23.214
root@192.168.23.214's password:
迁移: [100 %]
- 查看迁移过程是否中断
从下图中可以看到,在迁移过程中并未中断
迁移过程网络 ping 值
- 查看迁移后虚拟机的状态
[root@kvm01 ~]# virsh list --all
Id 名称 状态
----------------------------------------------------
- test01 关闭
- test02 关闭
[root@kvm02 ~]# virsh list --all
Id 名称 状态
----------------------------------------------------
2 test02 running
- test01 关闭
迁移之后源宿主机 kvm01 上虚拟机 test02 被关闭,目标宿主机 kvm02 上虚拟机 test02 处于启动状态。
5)生成配置文件
完成上述操作之后,基于共享存储的动态迁移已经实现了虚拟机 test02 从源宿主机kvm01 转移到目标宿主机 kvm02 上,但是其配置文件并没有一起迁移过来,此时还需要根据当前运行的虚拟机test02 生成对应的配置文件,并重新定义。
- 创建虚拟机 test02 配置文件
[root@kvm02 ~]# ls -l /etc/libvirt/qemu/
总用量 4
drwx------ 3 root root 42 4月 9 11:46 networks
-rw------- 1 root root 3631 4月 9 11:56 test01.xml
[root@kvm02 ~]# virsh dumpxml test02 > /etc/libvirt/qemu/test02.xml
[root@kvm02 ~]# ls -l /etc/libvirt/qemu/
总用量 12
drwx------ 3 root root 42 4月 9 11:46 networks
-rw------- 1 root root 3631 4月 9 11:56 test01.xml
-rw-r--r-- 1 root root 4391 4月 9 14:56 test02.xml
- 定义虚拟机 test02 配置文件
[root@kvm02 ~]# virsh define /etc/libvirt/qemu/test02.xml
定义域 test02(从 /etc/libvirt/qemu/test02.xml)
6)验证迁移结果
查看虚拟机 test02 的 IP 地址,验证迁移是否成功。
[root@kvm02 ~]# virsh console test02
连接到域 test02
换码符为 ^] //按 Enter 键进入 test02
CentOS Linux 7 (Core)
Kernel 3.10.0-1160.71.1.el7.x86_64 on an x86_64
test02 login: root
Password:
Last login: Tue Apr 9 14:51:09 on tty1
[root@test02 ~]# ip add | grep ens3
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
inet 192.168.23.143/24 brd 192.168.23.255 scope global noprefixroute dynamic ens3
至此,KVM 基于共享存储的动态迁移已经完成。
2.3、基于数据块的动态迁移
要实现基于数据块的动态迁移,首先要安装 qemu-kvm-ev。并且在目标宿主机上提前生成同名的空白磁盘文件,最后再通过数据块进行动态迁移。
1)依赖包安装
CentOS 7 默认安装的 qemu-kvm 包是不支持数据块动态迁移的,需要单独安装 qemu-kvm-ev。在 kvm01 和 kvm02 两台宿主机中都需要安装 qemu-kvm-ev。下面以源宿主机 kvm01 为例进行 qemu-kvm-ev 的安装操作演示。
[root@kvm01 ~]# yum -y install centos-release-qemu-ev
[root@kvm01 ~]# yum -y install qemu-kvm-ev
2) 迁移前准备工作
- 源宿主机 kvm01 上的准备
[root@kvm01 ~]# tail -2 /etc/hosts
192.168.23.213 kvm01
192.168.23.214 kvm02
[root@kvm01 ~]# virsh list --all
Id 名称 状态
----------------------------------------------------
- test01 关闭
- test02 关闭
[root@kvm01 ~]# virsh start test01
域 test01 已开始
[root@kvm01 ~]# virsh list --all
Id 名称 状态
----------------------------------------------------
6 test01 running
- test02 关闭
- 目标宿主机 kvm02 上的准备
[root@kvm02 ~]# tail -2 /etc/hosts
192.168.23.213 kvm01
192.168.23.214 kvm02
[root@kvm02 ~]# virsh list --all
Id 名称 状态
----------------------------------------------------
2 test02 running
- test01 关闭
[root@kvm02 ~]# virsh undefine test01
域 test01 已经被取消定义
[root@kvm02 ~]# ls /data/store/
test01.qcow2
[root@kvm02 ~]# rm -rf /data/store/*
[root@kvm02 ~]# virsh list --all
Id 名称 状态
----------------------------------------------------
2 test02 running
3)检查资源池
确保 kvm01 和 kvm02 两台宿主机拥有相同的资源池,若没有,则需创建。
[root@kvm01 ~]# virsh pool-list --all
名称 状态 自动开始
-------------------------------------------
iso 活动 是
kgc 活动 是
store 活动 是
[root@kvm02 ~]# virsh pool-list --all
名称 状态 自动开始
-------------------------------------------
创建 kvm02 资源池
[root@kvm02 ~]# virsh pool-define-as --name iso --type dir --target /data/iso
定义池 iso
[root@kvm02 ~]# virsh pool-build iso
构建池 iso
[root@kvm02 ~]# virsh pool-autostart iso
池 iso 标记为自动启动
[root@kvm02 ~]# virsh pool-start iso
池 iso 已启动
[root@kvm02 ~]# virsh pool-define-as --name kgc --type dir --target /data/kgc
定义池 kgc
[root@kvm02 ~]# virsh pool-build kgc
构建池 kgc
[root@kvm02 ~]# virsh pool-autostart kgc
池 kgc 标记为自动启动
[root@kvm02 ~]# virsh pool-start kgc
池 kgc 已启动
[root@kvm02 ~]# virsh pool-define-as --name store --type dir --target /data/store
定义池 store
[root@kvm02 ~]# virsh pool-build store
构建池 store
[root@kvm02 ~]# virsh pool-autostart store
池 store 标记为自动启动
[root@kvm02 ~]# virsh pool-start store
池 store 已启动
[root@kvm02 ~]# virsh pool-list --all
名称 状态 自动开始
-------------------------------------------
iso 活动 是
kgc 活动 是
store 活动 是
4)创建同名磁盘文件
[root@kvm02 ~]# qemu-img create -f qcow2 /data/store/test01.qcow2 10G
Formatting '/data/store/test01.qcow2', fmt=qcow2 size=10737418240 cluster_size=65536 lazy_refcounts=off refcount_bits=16
5)执行迁移操作
[root@kvm01 ~]# virsh migrate test01 qemu+ssh://192.168.23.214/system --live --persistent --undefinesource --copy-storage-all --verbose
root@192.168.23.214's password:
迁移: [100 %]
6)验证迁移结果
[root@kvm01 ~]# virsh list --all
Id 名称 状态
----------------------------------------------------
- test02 关闭 //kvm01 上 test01 已经被迁移
[root@kvm02 ~]# virsh list --all
Id 名称 状态
----------------------------------------------------
2 test02 running
3 test01 running //kvm02 上 test01 处于开启状态
至此,基于数据块的动态迁移已经完成。
2.4、KSM
当前主流的操作系统大多都支持 KSM,因为 KSM 可以合并相同的内存页,减少虚拟机内存的使用量。这样有利于提高 CPU 的工作效率,加快数据缓存效率,同时可以节省更多的内存空间来缓存额外的磁盘数据。
KSM 适用于宿主机过载的情况下。KSM 通过减少每个虚拟机实际占用的内存数,可以让多个虚拟机分配的内存数量之和大于物理内存数量。而对于相同类型的虚拟机,在物理内存量不变的情况下,可以在一个宿主机中创建更多虚拟机,从而提高虚拟化部署的密度,同时也可以提高物理资源的利用效率。
1)KSM 服务介绍
KSM 是在 Linux 2.6 内核版本中被添加进去的,目前大多数常用的、主流的 Linux 发行版都默认支持 KSM 技术,执行以下命令即可检查当前 Linux 系统是否支持 KSM。
[root@kvm02 ~]# egrep -i ksm /boot/config-3.10.0-1160.71.1.el7.x86_64
CONFIG_KSM=y //结果为 y 表示支持
KSM 服务在 CentOS 7 内是以 ksmd 作为守护进程的,针对该服务的一些配置文件, 都在目录“/sys/kernel/mm/ksm”下。
[root@kvm02 ~]# ls -l /sys/kernel/mm/ksm/
总用量 0
-r--r--r-- 1 root root 4096 4月 9 15:28 full_scans
-rw-r--r-- 1 root root 4096 4月 9 15:28 max_page_sharing
-rw-r--r-- 1 root root 4096 4月 9 15:28 merge_across_nodes
-r--r--r-- 1 root root 4096 4月 9 15:28 pages_shared
-r--r--r-- 1 root root 4096 4月 9 15:28 pages_sharing
-rw-r--r-- 1 root root 4096 4月 9 15:28 pages_to_scan
-r--r--r-- 1 root root 4096 4月 9 15:28 pages_unshared
-r--r--r-- 1 root root 4096 4月 9 15:28 pages_volatile
-rw-r--r-- 1 root root 4096 4月 9 15:28 run
-rw-r--r-- 1 root root 4096 4月 9 15:28 sleep_millisecs
-r--r--r-- 1 root root 4096 4月 9 15:28 stable_node_chains
-rw-r--r-- 1 root root 4096 4月 9 15:28 stable_node_chains_prune_millisecs
-r--r--r-- 1 root root 4096 4月 9 15:28 stable_node_dups
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 优化内存
在目标宿主机 kvm02 上,有 test01 和 test02 两台虚拟机。现在通过克隆的方式再创建两台新的虚拟机。然后开启这四台虚拟机,等四台虚拟机都启动后,观察内存使用情况。等内存使用量不再变化后,启动 KSM 服务,过 5 分钟,观察内存使用量的变化情况。
- 克隆虚拟机
[root@kvm02 ~]# virt-clone -o test02 -n test03 -f /data/store/test03.qcow2
WARNING 设置图形设备端口为自动端口,以避免相互冲突。
正在分配 'test03.qcow2' | 10 GB 00:00:57
成功克隆 'test03'。
[root@kvm02 ~]# virt-clone -o test02 -n test04 -f /data/store/test04.qcow2
WARNING 设置图形设备端口为自动端口,以避免相互冲突。
正在分配 'test04.qcow2' | 10 GB 00:00:56
成功克隆 'test04'。
- 启动4台虚拟机
[root@kvm02 ~]# virsh list --all
Id 名称 状态
----------------------------------------------------
3 test01 running
4 test02 running
5 test03 running
6 test04 running
- 记录开启 KSM 之前内存使用情况
[root@kvm02 ~]# free -m //确保虚拟机都开启好后,内存不再变化
total used free shared buff/cache available
Mem: 7963 1547 137 11 6278 6127
Swap: 1023 1 1022
- 启动 KSM 服务
在 CentOS 7 系统中,通过 ksm 和 ksmtuned 两个服务来动态调节 KSM 的运行情况, 要想保证两个服务的存在,需要 qemu-kvm-common 这个 RPM 包的支持。执行以下命令启动 ksm 和 ksmtuned 这两个服务。
[root@kvm02 ~]# systemctl start ksm
[root@kvm02 ~]# systemctl start ksmtuned
当 ksm 服务启动后,需要检查/sys/kernel/mm/ksm/run 文件的值是否为 1,若为 0 则 KSM 功能不会生效,需要将其置为 1。
[root@kvm02 ~]# echo 1 > /sys/kernel/mm/ksm/run
在 KSM 服务启动之后,KSM 能够最多共享系统物理内存一半的内存页。而 ksmtuned 服务一直保持循环执行,以调用 ksm 服务来运行。
- 对比 KSM 开启之后的内存使用情况
[root@kvm02 ~]# free -m
total used free shared buff/cache available
Mem: 7963 1067 634 11 6262 6608
Swap: 1023 1 1022
对比 KSM 开启前后内存的使用情况,“used”从开始的 1547M 降到了 1067M,说明节约了系统内存。
至此,KVM 虚拟机的各种迁移及 KSM 内存优化已经介绍完成。