目录
一、案例概述与前置知识
1.1 案例背景与目标
1.2 KVM 虚拟机迁移基础
1.2.1 迁移的定义与应用场景
1.2.2 迁移的分类与区别
1.3 动态迁移的两种方式
1.3.1 基于共享存储的动态迁移
1.3.2 基于数据块的动态迁移
1.4 KSM 内核同页合并技术
二、案例环境准备
2.1 案例环境配置
2.2 案例需求与实现思路
2.2.1 案例需求
2.2.2 实现思路
三、KVM 静态迁移实现
3.1 在源宿主机上准备虚拟机
3.1.1 创建虚拟机 test01
3.1.2 配置虚拟机 test01 可通过 console 登录
3.1.3 标记虚拟机 test01 当前 IP 地址
3.2 提取磁盘和配置文件
3.2.1 查看虚拟机 test01 当前状态
3.2.2 关闭虚拟机 test01
3.2.3 导出虚拟机 test01 的 xml 配置文件
3.2.4 定位虚拟机 test01 的磁盘文件
3.2.5 拷贝配置文件和磁盘文件到目标宿主机 kvm02
3.3 配置和启动目标虚拟机
3.3.1 查看被迁移过来的配置文件和磁盘文件
3.3.2 重新定义虚拟机 test01
3.3.3 启动虚拟机 test01
3.3.4 验证虚拟机 test01 的 IP 地址信息
四、基于共享存储的动态迁移实现
4.1 配置 NFS 共享存储
4.1.1 在 kvmnfs 服务器上安装 NFS 服务
4.1.2 配置共享目录
4.1.3 启动并查看 NFS 服务
4.2 挂载 NFS 目录
4.2.1 在源宿主机 kvm01 上查看 NFS 共享目录
4.2.2 在源宿主机 kvm01 上创建本地数据目录
4.2.3 在源宿主机 kvm01 上挂载共享目录
4.2.4 在源宿主机 kvm01 上设置自动挂载
4.3 创建动态迁移的虚拟机
4.3.1 创建虚拟机 test02
4.3.2 登录虚拟机 test02 并查看 IP 地址
4.4 执行动态迁移
4.4.1 查看 kvm01 和 kvm02 上虚拟机的运行状态
4.4.2 在源宿主机 kvm01 上执行迁移命令
4.4.3 查看迁移过程是否中断
4.4.4 查看迁移后虚拟机的状态
4.5 生成配置文件
4.5.1 创建虚拟机 test02 的配置文件
4.5.2 定义虚拟机 test02 的配置文件
4.6 验证迁移结果
五、基于数据块的动态迁移实现
5.1 安装依赖包
5.2 迁移前准备工作
5.2.1 源宿主机 kvm01 上的准备
5.2.2 目标宿主机 kvm02 上的准备
5.3 检查资源池
5.4 创建同名磁盘文件
5.5 执行迁移操作
5.6 验证迁移结果
六、KSM 内存优化实现
6.1 KSM 服务介绍
6.1.1 检查系统是否支持 KSM
6.1.2 KSM 配置文件说明
6.2 配置 KSM 优化内存
6.2.1 克隆虚拟机
6.2.2 记录开启 KSM 前内存使用情况
6.2.3 启动 KSM 服务
6.2.4 对比 KSM 开启后内存使用情况
七、关键技术总结与注意事项
7.1 迁移技术对比
7.2 KSM 使用注意事项
7.3 动态迁移6常见问题与解决方案
7.4 生产环境5最佳实践
八、案例拓展与延伸
8.1 跨网段迁移方案
8.2 大规模集群迁移策略
8.3 KSM 与 Docker 的结合应用
企业在使用 KVM 虚拟化技术时,随着虚拟机数量的增加,部分服务器可能出现资源过载的情况。为了实现服务器资源的最大化利用,需要对虚拟机进行迁移,并通过 KSM 内核同页合并技术优化内存使用。本案例的主要目标包括:
KVM 虚拟机迁移是将某一虚拟机上的环境和软件完全复制到另一台物理机上继续运行的过程。其主要应用场景包括:
根据迁移方式的不同,KVM 虚拟机迁移可分为静态迁移和动态迁移:
该方式要求源宿主机和目标宿主机连接共享存储服务。迁移开始后,虚拟机依然在源宿主机上运行,同时内存页被传输到目标宿主机。QEMU/KVM 会监控并记录迁移过程中内存页的修改,在所有内存页传输完成后,传输修改的内容,最后在目标宿主机恢复虚拟机运行状态。
当虚拟机使用本地存储时,可采用基于数据块的动态迁移。该方式不需要共享存储,迁移环境简单,源宿主机和目标宿主机只需要保持以太网连接即可。
KSM(Kernel SamePage Merging)允许内核在两个或多个进程之间共享完全相同的内存页。它通过扫描正在运行的程序,比较它们的内存,将相同的内存区域或内存页合并为一个单一的内存页,并标识为 "写时复制"。当有进程试图修改被合并的内存页时,为该进程复制出一个新的内存页供其使用。
在 KVM 环境下,多个运行相同操作系统或应用程序的虚拟机之间,相同内存页数量较多,使用 KSM 的效果更加显著,甚至可以节省超过 50% 的内存。但 KSM 会使宿主机的 CPU 使用量有一定程度的升高,在实际生产环境中需要进行适当配置,以达到较好的平衡。
本案例使用三台服务器模拟 KVM 虚拟机迁移,具体环境如下表所示:
主机 | 操作系统 | IP 地址 | 主要软件 |
---|---|---|---|
kvm01 | CentOS 7.3 x86_64 | 192.168.9.61 | Qemu-kvm、libvirt |
kvm02 | CentOS 7.3 x86_64 | 192.168.9.62 | Qemu-kvm、libvirt、qemu-kvm-ev |
kvmnfs | CentOS 7.3 x86_64 | 192.168.9.63 | nfs-utils |
使用 virt-install 命令在源宿主机 kvm01 上创建虚拟机 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-Minimal-1611.iso -vnc -vncport=5901 -vnclisten=0.0.0.0
命令选项说明:
-n
:指定虚拟机的名字-r
:指定内存大小(单位:MB)--vcpus
:指定虚拟 CPU 个数--disk
:指定磁盘文件放置位置及大小-w
:指定所使用的网桥--autostart
:设置虚拟机在宿主机开机时启动-c
:指定镜像文件--vncport
:通过 VNC Viewer 连接的端口--vnclisten
:通过 VNC Viewer 连接的 IP在虚拟机 test01 上进行如下配置,以便通过 virsh console 命令连接:
[root@test01 ~]# grubby --update-kernel=ALL --args="console=ttyS0"
[root@test01 ~]# reboot
通过 virsh console 命令连接到虚拟机 test01,查看其 IP 地址:
[root@kvm01 ~]# virsh console test01
Connected to domain test01
Escape character is ^]
[root@test01 ~]# ifconfig
记录下虚拟机 test01 的 IP 地址为 192.168.9.97,使用Ctrl+]
组合键退出虚拟机。
[root@kvm01 ~]# virsh list --all
[root@kvm01 ~]# virsh shutdown test01
[root@kvm01 ~]# virsh list --all
[root@kvm01 ~]# virsh dumpxml test01 > test01.xml
[root@kvm01 ~]# virsh domblklist test01
[root@kvm01 ~]# scp test01.xml 192.168.9.62:/etc/libvirt/qemu/
[root@kvm01 ~]# scp /data/store/test01.qcow2 192.168.9.62:/data/store/
[root@kvm02 ~]# ls -l /etc/libvirt/qemu/
[root@kvm02 ~]# ls -l /data/store/
[root@kvm02 ~]# virsh define /etc/libvirt/qemu/test01.xml
[root@kvm02 ~]# virsh start test01
[root@kvm02 ~]# virsh list --all
[root@kvm02 ~]# virsh console test01
[root@test01 ~]# ifconfig
确认虚拟机 test01 的 IP 地址与迁移前一致,静态迁移成功。
[root@kvmnfs ~]# yum -y install nfs-utils
[root@kvmnfs ~]# mkdir /data
[root@kvmnfs ~]# vim /etc/exports
/data 192.168.9.0/24(rw,sync,no_root_squash)
[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
[root@kvm01 ~]# showmount -e 192.168.9.63
[root@kvm01 ~]# mkdir /data/kgc
[root@kvm01 ~]# mount -t nfs 192.168.9.63:/data /data/kgc
[root@kvm01 ~]# mount
[root@kvm01 ~]# vim /etc/fstab
192.168.9.63:/data /data/kgc nfs defaults 0 0
[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-Minimal-1611.iso -vnc -vncport=5902 -vnclisten=0.0.0.0
[root@kvm01 ~]# virsh console test02
[root@test02 ~]# ifconfig
记录虚拟机 test02 的 IP 地址为 192.168.9.42。
[root@kvm01 ~]# virsh list --all
[root@kvm02 ~]# virsh list --all
在 Windows 机器上 ping 虚拟机 test02 的 IP 地址,观察迁移过程中是否存在网络中断:
ping 192.168.9.42
在 kvm01 上执行迁移命令:
[root@kvm01 ~]# virsh migrate --live --verbose test02 qemu+ssh://192.168.9.62/system tcp://192.168.9.62
如果出现错误,修改虚拟机 test02 的配置文件:
[root@kvm01 ~]# virsh shutdown test02
[root@kvm01 ~]# virsh edit test02
在磁盘配置中添加cache='none'
,然后重新启动虚拟机并执行迁移命令。
观察 ping 命令的输出,迁移过程中只丢失了一个包,中断时间可以忽略不计。
[root@kvm01 ~]# virsh list --all
[root@kvm02 ~]# virsh list --all
[root@kvm02 ~]# virsh dumpxml test02 > /etc/libvirt/qemu/test02.xml
[root@kvm02 ~]# virsh define /etc/libvirt/qemu/test02.xml
[root@kvm02 ~]# virsh console test02
[root@test02 ~]# ifconfig
确认虚拟机 test02 的 IP 地址与迁移前一致,基于共享存储的动态迁移成功。
在 kvm01 和 kvm02 上安装 qemu-kvm-ev:
[root@kvm01 ~]# yum -y install centos-release-qemu-ev
[root@kvm01 ~]# yum -y install qemu-kvm-ev
[root@kvm01 ~]# cat /etc/hosts
192.168.9.61 kvm01
192.168.9.62 kvm02
[root@kvm01 ~]# virsh start test01
[root@kvm01 ~]# virsh list --all
[root@kvm02 ~]# cat /etc/hosts
192.168.9.61 kvm01
192.168.9.62 kvm02
[root@kvm02 ~]# virsh undefine test01
[root@kvm02 ~]# cd /data/store/
[root@kvm02 store]# rm -rf test01.qcow2
[root@kvm02 store]# virsh list --all
[root@kvm02 store]# virsh pool-list --all
[root@kvm02 store]# qemu-img create -f qcow2 /data/store/test01.qcow2 10G
[root@kvm01 ~]# virsh migrate test01 qemu+ssh://192.168.9.62/system --live --persistent --undefinesource --copy-storage-all --verbose
[root@kvm01 ~]# virsh list --all
[root@kvm02 store]# virsh list --all
确认虚拟机 test01 已成功迁移到 kvm02,基于数据块的动态迁移完成。
[root@kvm02 ~]# egrep -i ksm /boot/config-3.10.0-514.el7.x86_64
KSM 的配置文件位于/sys/kernel/mm/ksm/
目录下,常用配置项包括:
max_page_sharing
:设置每个 KSM 页面允许的最大共享数量merge_across_nodes
:指定是否可以合并来自不同 numa 节点的页面pages_to_scan
:KSM 进程休眠前扫描的内存数量run
:控制 ksmd 进程是否运行sleep_millisecs
:设置 ksmd 进程休眠时间(单位:毫秒)stable_node_chains_prune_millisecs
:调节重复扫描 stable_node"链" 的时间(单位:毫秒)在目标宿主机 kvm02 上克隆两台新虚拟机:
[root@kvm02 ~]# virt-clone -o test02 -n test03 -f /data/store/test03.qcow2
[root@kvm02 ~]# virt-clone -o test02 -n test04 -f /data/store/test04.qcow2
确保四台虚拟机启动且内存使用量稳定后执行:
[root@kvm02 ~]# free -m
输出示例:
total used free shared buff/cache available
Mem: 4939 2213 1744 30 981 2401
Swap: 1023 3 1020
[root@kvm02 ~]# systemctl start ksm
[root@kvm02 ~]# systemctl start ksmtuned
[root@kvm02 ~]# echo 1 > /sys/kernel/mm/ksm/run # 确保KSM运行
5 分钟后执行:
[root@kvm02 ~]# free -m
输出示例:
total used free shared buff/cache available
Mem: 4939 1491 2438 30 1009 3099
Swap: 1023 3 1020
可见used
内存从 2213M 降至 1491M,系统内存得到有效节约。
迁移类型 | 静态迁移 | 基于共享存储的动态迁移 | 基于数据块的动态迁移 |
---|---|---|---|
服务中断 | 中断(需关闭虚拟机) | 几乎不中断(短暂停机) | 几乎不中断(短暂停机) |
存储要求 | 本地存储需拷贝磁盘文件 | 源 / 目标宿主机连接共享存储 | 目标宿主机需提前创建同名磁盘 |
适用场景 | 可停机的虚拟机 | 在线服务且使用共享存储的虚拟机 | 在线服务且使用本地存储的虚拟机 |
关键命令 | virsh shutdown/migrate | virsh migrate --live | virsh migrate --copy-storage-all |
/sys/kernel/mm/ksm/sleep_millisecs
调节扫描间隔,避免过度消耗 CPU。/sys/kernel/mm/ksm/run
值是否为 1,否则 KSM 不生效。cache='none'
或cache='directsync'
。qemu-kvm-ev
和centos-release-qemu-ev
包。watch -n 5 cat /sys/kernel/mm/ksm/pages_shared
实时监控内存合并效果。若源 / 目标宿主机位于不同网段,需:
对于包含 50 + 宿主机的集群,建议:
在混合部署 KVM 和 Docker 的宿主机上:
cgroup
限制 KSM 对 Docker 进程的影响