ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

KVM虚拟机冷迁移与热迁移实战:原理、命令与避坑指南

KVM虚拟机冷迁移与热迁移实战:原理、命令与避坑指南 上周刚帮同事把一台跑了三年线上业务的KVM虚拟机从旧宿主机迁了出来。很多人一听到“虚拟机迁移”第一反应是“把镜像文件拷过去再启动不就行了”确实这是最原始的思路但一旦落到生产环境光是“业务不能断”这一条整套流程的复杂度就会成倍上涨。这篇文章是我完整做完一次KVM高级功能虚拟机迁移实验的记录冷迁移、热迁移两条路都走了从原理到命令再到踩坑全部拆开讲。适合运维、虚拟化平台维护、以及刚接触KVM开发的同学结合自己的环境参考。看完你至少能明白热迁移到底在后台做了什么哪些环节决定成败以及很多文档里不会写的经验教训。1. 先想清楚冷迁移和热迁移到底在解决什么问题1.1 两种迁移方式的适用场景判断KVM的迁移按业务中断程度划分本质就两类冷迁移离线迁移和热迁移在线迁移。冷迁移是先把虚拟机彻底关机然后把磁盘镜像和配置文件同步到目标宿主机再在目标机上启动。整个过程业务是停的但实施起来非常朴素可靠不需要复杂依赖网络带宽不够也能慢慢传。热迁移则是让虚拟机在一台宿主机上运行时把它的全部运行状态“搬”到另一台宿主机中间只有极短的切换停顿通常几百毫秒到一两秒。迁移完成后业务以为宿主机没换过连接不会断数据库事务也不会中断。判断用哪一种我自己的标准非常简单计划内维护比如宿主机要换硬件、升级内核、机房断电演练只要允许停机窗口优先冷迁移省心且容错高。不允许业务中断比如线上数据库、对外API服务、正在跑批处理的任务必须热迁移覆盖。批量整合服务器一台宿主机负载太高要把一部分虚拟机匀到空闲机器上优先热迁移因为迁移过程不会触发客户端重连。表格更直观对比项冷迁移热迁移业务中断完全中断毫秒至秒级抖动实施复杂度低高对存储要求任意磁盘文件即可共享存储最佳非共享也能迁但风险高对网络要求较低慢速也扛得住高要求稳定带宽和低延迟典型场景硬件报废、跨机房搬迁负载均衡、滚动维护1.2 共享存储不是必选项但它决定热迁移的“姿势”热迁移能否优雅很大程度上取决于虚拟机磁盘放在哪里。如果两台宿主机共享一块存储比如NFS、GlusterFS、Ceph RBD虚拟机磁盘镜像本身就挂在共享存储上迁移时只需要同步内存和CPU状态磁盘数据不用搬所以热迁移命令非常简单也最安全。如果两台宿主机完全没有共享存储磁盘镜像只在源端热迁移就必须连磁盘数据一起在线拷贝也就是“存储内存同时迁移”。KVM/libvirt同样支持而且会先做磁盘预拷贝再触发内存同步最后一并切换。代价是迁移时间变长、网络开销巨大一旦中途断连源和目标两边状态可能不一致排查起来相当头疼。我这次实验选择的是NFS共享存储方案理由很直接可靠、配置快、符合大部分中小团队的现有基础设施。很多团队并没有专业SAN或CephNAS挂NFS是现实起点后续平滑升级到Ceph也顺理成章。1.3 迁移的最终价值整套系统免重装很多人问既然系统都装在虚拟化平台里迁移到底比重新部署强在哪答案其实是一句很实在的话KVM虚拟机迁移相当于把一台服务器上的整套操作系统连同它的运行状态、配置、已打开的文件、网络连接、运行中的服务原封不动地搬到另一台物理服务器上整台服务器系统不需要重装数据不需要重新同步。这也是“通过KVM给服务器做系统”这件事的高级形态——虚拟化不止是装系统方便而是让操作系统本身变成了可以被调度、被移动、被热切换的工作负载。迁移相当于KVM在底层帮你做了一次“系统整体搬迁”比任何物理机迁移方案都干净。2. 热迁移的原理不搞懂这个后面全是坑2.1 迁移不是拷贝文件而是同步一台“活机器”的状态KVM虚拟机由QEMU进程承载虚拟机看到的CPU、内存、磁盘、网卡都是QEMU模拟出来的。一个运行中的虚拟机本质上由三部分组成磁盘数据这是静态的存在镜像文件里内存数据这是动态的包括应用缓存、内核状态、未写盘的日志缓冲设备状态包括CPU寄存器、中断控制器、时钟偏移、virtio队列状态。冷迁移只需要管第一样但热迁移必须把三样全部搬到目标宿主机而且搬的过程中虚拟机还在运行内存每分每秒都在变化。这就像你要把一整个正在办公的房间原样搬到隔壁房间里的人还在打字、接电话、做表格搬的时候还不能让人察觉。2.2 预拷贝迭代机制内存怎么一点点“追”过去KVM热迁移采用的是迭代预拷贝机制逻辑并不复杂第一轮把整个虚拟机内存全量从源端发送到目标端数据量就是虚拟机的内存大小比如8GB。但在发送过程中虚拟机还在运行源端内存不断被写入新数据这部分被修改过的内存页叫“脏页”。第一轮发完之后目标端的“内存快照”和源端实际内存之间差的就是这一轮产生的脏页。接下来开始第二轮只发送脏页。第二轮发送期间又会产生新的脏页接着第三轮、第四轮……每轮要传的数据量取决于业务写内存的速率。只要每一轮的新增脏页量在递减迁移就能收敛最终达到一个临界点剩余脏页量已经很小并且增长很慢此时就可以进入停机拷贝阶段。这里面最关键的数值关系是脏页产生速率必须小于网络传输速率。用数字感受一下8GB内存虚拟机千兆网卡实际传输约100MB/s第一轮全量传输大约需要80秒如果业务产生的脏页速率是30MB/s那第一轮产生的脏页约2400MB第二轮需要24秒第二轮期间又产生720MB脏页第三轮需要7秒左右三轮之后剩余脏页降到几百MB级别进入停机拷贝。但如果业务写内存速率极快比如数据库大量加载数据时脏页速率飙到200MB/s而网络只有100MB/s脏页永远越积越多迁移就无法收敛表现就是迁移进度卡在99%或持续几十分钟不结束。这是热迁移最经典的故障之一后面排查部分专门说。脏页追踪是QEMU通过内存日志模式实现的。QEMU为虚拟机内存建立位图KVM内核模块在EPT被写入时记录对应页面为dirty然后通过KVM_GET_DIRTY_LOG接口交给QEMU比对发送。可以说没有KVM内核态的脏页跟踪就没有热迁移这回事。2.3 最后一步停机拷贝与秒级切换当预拷贝迭代收敛到只剩几十MB脏页时QEMU会执行最后一步叫停机拷贝源端暂停虚拟机CPU运行把剩余脏页一次性发送到目标端此时目标端的内存数据已经和源端完全一致目标端QEMU开始运行虚拟机源端QEMU退出。这一步就是业务能感知到的唯一抖动窗口。正常情况下只有几百毫秒熟练的运维会观察到ping延迟突然跳一次然后恢复SSH连接不掉。为了保证最后一轮停机时间可控libvirt允许设置最大停机时间比如virsh migrate --maxdowntime 500单位是毫秒意思是“停机拷贝阶段我最多接受500毫秒的停顿”。如果剩余脏页在500毫秒内传不完QEMU会再多做几轮预拷贝直到能在预期时间内传完为止。2.4 CPU兼容性是迁移的第一道门槛热迁移过程中虚拟机的CPU寄存器也要同步所以两台宿主机的CPU必须兼容否则迁到目标端之后虚拟机可能直接崩溃或者莫名其妙出现非法指令。QEMU/KVM的CPU模型有三种模式迁移时差别很大host-passthroughCPU特性完全透传宿主机的所有能力性能最好但只能在CPU型号完全一致的两台机器间迁移跨型号必挂。host-model自动挑选宿主机CPU型号作为基础并过滤掉迁移不安全特性这是很多发行版默认策略兼容性好一些但性能略低于透传。custom手动指定CPU型号比如cpu modecustom matchexact modelskylake-avx512用于精确控制CPU基线。生产环境里最保险的做法是把所有宿主机的CPU模型统一。比如一台是E5 v4一台是E5 v3虽然都是Intel但特性集不一致推荐统一设成modelhaswell-noTSX或modelSkylake-Client这类中间型号避免迁移后虚拟机看到目标CPU带上了源端没有的指令集。这里有个非常坑的细节如果源端虚拟机用了host-passthrough业务又在启动时检测到AVX512指令集迁移到一台不支持AVX512的宿主机时QEMU并不会立刻报错而是等虚拟机执行到相关指令时直接SIGILL崩溃。所以迁移前必须用virsh capabilities对比两台宿主机的CPU特性差异。3. 实验环境准备基础配置决定迁移成败3.1 宿主机与虚拟机规划清单先说清楚我的实验环境方便你对照节点角色IP配置操作系统kvm-node1源宿主机192.168.10.11双路E5-2680 v4 / 96G内存CentOS 7.9kvm-node2目标宿主机192.168.10.12单路E5-2680 v4 / 128G内存CentOS 7.9nfs-storage共享存储192.168.10.104T SAS阵列同机部署NFS虚拟机规划我准备了一台测试用的web-01配置为vCPU 4核、内存8GB、系统盘raw格式20GB磁盘路径/data/kvm/web-01.raw。操作系统是CentOS 7.9里面跑了一个nginx服务用来验证迁移后业务是否还活着。两台宿主机必须装齐的组件是qemu-kvm、libvirt、virt-manager图形调试用、rsync冷迁移同步镜像用。版本差异影响很大我这边源端是qemu-kvm 6.2.0、libvirt 8.0.0目标端保持完全一致这是避免兼容性踩雷的最低成本操作。3.2 NFS共享存储搭建一次配置热迁移和灾备都能用共享存储不是热迁移的绝对前提但强烈建议实验阶段先搭NFS因为它能帮你隔离“磁盘迁移”这个变量专心验证内存迁移机制。在nfs-storage上做这些操作yum install -y nfs-utils mkdir -p /data/kvm chmod 755 /data/kvm然后修改/etc/exports/data/kvm 192.168.10.0/24(rw,sync,no_root_squash,no_subtree_check)三处权限参数逐个说清楚rw读写权限迁移过程中目标机要在共享存储上创建临时状态文件。syncNFS服务端等数据落盘后再响应客户端比async慢但避免断电后存储数据不一致。生产环境不要省这个参数。no_root_squash允许root用户以root身份在NFS共享上读写。如果不加guest在迁移期间创建的临时文件可能因权限不足而失败表现就是迁移一直报Unable to write to storage。配置完成后重启服务systemctl enable nfs-server systemctl restart nfs-server两台宿主机分别挂载并验证mount -t nfs 192.168.10.10:/data/kvm /data/kvm grep /data/kvm /etc/fstab挂载后建议先做一次性能验证避免迁移到一半发现存储读写太慢。用dd简单测试dd if/dev/zero of/data/kvm/testfile bs1M count1024 oflagdirect如果写速低于50MB/s优先排查网卡bond模式、交换机端口协商和NFS挂载参数比如是否缺了wsize1048576。迁移对存储带宽很敏感尤其是非共享存储迁移时磁盘预拷贝和内存预拷贝同时跑存储慢就是双重灾难。3.3 libvirt版本和虚拟机配置确认迁移前用两条命令做体检virsh version virsh list --allvirsh version输出里有三个版本号要注意libvirt、QEMU、KVM内核模块版本。我的习惯是两台宿主机三个版本必须一致或至少大版本一致。版本差异可能导致目标端无法识别源端传来的迁移参数常见报错是unknown flag或migration protocol mismatch。然后检查虚拟机的CPU模型和网卡模型virsh dumpxml web-01 | grep -A6 cpu virsh dumpxml web-01 | grep -A5 interface确认磁盘路径是否在共享存储上。如果虚拟机磁盘之前用的是/var/lib/libvirt/images/web-01.raw需要先关机用qemu-img把镜像搬到/data/kvm/下再修改XML里的磁盘路径。这块操作最好在冷迁移章节一起做避免虚拟化平台路径混乱。4. 冷迁移实操从关机到重新开机每一步都别跳4.1 优雅关机与数据落盘别直接virsh destroy很多新手一上来就virsh destroy web-01这相当于直接拔电源。确实能关但guest里的数据库、文件系统没有完成日志提交迁移过去后可能出现文件系统不一致或数据损坏。正确操作是virsh shutdown web-01 --timeout 120这条命令会向guest发送ACPI关机信号等待120秒。如果guest在超时时间内没关机才执行virsh destroy。等待期间可以控制台观察virsh domstate web-01直到输出shut off才确认关机完成。之后还有一道保险如果guest用了RAW格式磁盘可以用qemu-img check验证磁盘完整性qemu-img check /data/kvm/web-01.raw有错误就立刻记录迁移前发现远比迁过去再发现好。4.2 用rsync同步磁盘镜像三种工具各自适用场景冷迁移的核心就是同步磁盘文件。我推荐rsync但工具选择要看场景工具适用场景不适用备注rsync常规裸盘或qcow2镜像同步支持增量、断点续传磁盘稀疏文件未正确处理会膨胀最通用qemu-img convert需要压缩或转换格式时比如qcow2转raw不能增量同步适合一次性全量迁移e2image针对ext2/3/4文件系统做静态镜像同步只支持部分文件系统适合有文件系统级别的精准拷贝本次我用的命令rsync -avP --progress /data/kvm/web-01.raw 192.168.10.12:/data/kvm/参数解释-a归档模式保留权限和属主-v显示过程-P包含--partial --progress意思是如果中断下次执行能续传进度条也能看到实时速度。同步完成后到目标机端验证文件大小和MD5md5sum /data/kvm/web-01.raw源端也执行一次两个哈希必须一致。这一步是冷迁移最笨但最有效的校验手段一刻都不能省。4.3 XML配置导出与重定义路径和PCI地址最容易出错磁盘文件同步过去之后接著要把虚拟机的定义信息迁过去。命令是virsh dumpxml web-01 /data/kvm/web-01.xml然后把XML文件传到目标宿主机在目标机上定义并启动virsh define /data/kvm/web-01.xml virsh start web-01但这里有个非常容易踩的坑XML默认记录的是源端磁盘绝对路径如果两台机器路径布局不一样启动时会提示找不到镜像。需要先检查grep source file /data/kvm/web-01.xml如果路径不一致直接改XMLsed -i s#/var/lib/libvirt/images#/data/kvm#g /data/kvm/web-01.xml注意不要用sed替换所有字符串只替换磁盘source路径。否则如果你VM名称也包含这个路径片段就会误伤。另外XML里的PCI地址address是从源宿主机导出的目标宿主机的PCI拓扑可能不同。冷迁移启动时libvirt一般会自动重新分配PCI地址但如果你启用了pcie-to-pci桥接或者SR-IOV直通就必须先确认目标机网卡驱动和PCI资源是否支持。4.4 启动后的验证清单别急着切流量冷迁移启动成功不等于迁移完成。我建立了一个三分钟验证清单首先确认guest系统状态virsh list --all virsh domstate web-01如果状态是running说明dom控制层正常。接着进guest确认文件系统virsh console web-01 fsck -nf /dev/sda1 df -h如果之前rsync全量复制文件系统多半是干净状态。然后验证业务监听ss -tlnp | grep nginx curl -I http://127.0.0.1最后是网络层检查。如果guest的IP是静态配置马上检查网卡名是否漂移。现代CentOS用一致性网络设备命名PCI地址变了网卡名可能从eth0变成ens3这会导致静态IP配置失效业务无法监听。这个问题在热迁移里也会出现排查时要放在最前面。5. 热迁移实操一条命令迁走生产虚拟机5.1 共享存储下的在线迁移命令全解冷迁移成功验证后我才开始做热迁移实验。环境还是web-01但此时虚拟机保持开机状态里面nginx持续跑着。在源宿主机上执行virsh migrate --live --verbose --p2p --unsafe web-01 qemussh://root192.168.10.12/system逐个参数拆开--live执行在线迁移不让VM停机。--verbose显示传输进度。--p2p点对点模式。迁移数据不走管理端中转源端QEMU直接和目标端QEMU建连分担管理机压力。没有这个参数libvirt会走客户端中转性能差很多。--unsafe跳过安全检查。因为共享存储已经挂载好这台VM没有本地非共享磁盘实际是安全的但libvirt默认会做保守检查先加这个参数让流程跑通。执行之后命令会卡住然后逐渐显示迁移进度一直到100%后返回shell。这是迁移过程中最紧张但最正常的画面。如果是GUI环境也可以用virt-manager右键虚拟机选择“Migrate”原理一样只是把参数变成了选项框。5.2 不共享存储时怎么迁copy-storage-all方案如果环境里没有共享存储虚拟机磁盘只在源端可以用这个命令把所有存储一起在线迁移virsh migrate --live --p2p --copy-storage-all --verbose web-01 qemussh://root192.168.10.12/system--copy-storage-all让QEMU在预拷贝阶段把整个磁盘镜像从源端传到目标端。但我要明确说一句这种方式能跑通但生产环境要非常谨慎。因为磁盘预拷贝和内存预拷贝是并行跑的网络带宽会被吃满如果业务写入频繁脏页速率高迁移可能长时间无法收敛。即使收敛成功一旦迁移过程中网络抖动源和目标两边的磁盘状态可能无法确认一致恢复成本极高。如果你的业务本身就长期存在且无法接受共享存储带来的单点风险建议优先调研存储层做双写或同步复制后再做热迁移而不是靠迁移命令本身去补存储短板。5.3 迁移过程监控与结果验证别只看一个RTT热迁移命令返回后事情还没完。我习惯做四步验证第一步看目标宿主机虚拟机是否在运行virsh list --all正常情况下目标端会出现web-01状态为running。第二步回源端确认虚拟机已消失virsh list --allweb-01应该不在了只剩domstate输出为undefined或直接消失。第三步业务连续性验证。从外部机器持续ping虚拟机IP同时观察nginx访问日志watch -n1 tail -5 /var/log/nginx/access.log迁移前后访问日志应该连续最多有1到2个请求响应时间略微升高那是停机拷贝窗口造成的。第四步检查虚拟机内部时钟。热迁移后guest认为时间延续不会明显跳变。如有NTP配置日志不会出现大幅校正。如果出现明显时间跳变多半是时钟模型设置有问题这个问题我在下一节详说。5.4 热迁移中必须掌握的监控命令virsh migrate是有进度的但真正的运维监控要看virsh domjobinfo web-01这个命令输出选项卡能看到非常关键的信息比如Data processed、Data remaining这决定迁移处于预拷贝的哪一轮。另外virsh domjobabort web-01可以在迁移确实卡死时手动取消避免它无限挂在那里。我见过有人跑着迁移就去开会回来发现两小时还没结束内存脏页根本收敛不了最后手动abort才恢复。6. 常见问题与排查技巧实录6.1 迁移后虚拟机网络不通第一反应别改网卡这个问题我在冷迁移和热迁移里都碰到过。现象迁移完成guest状态running但ping不通SSH也连不上。很多人的第一反应是去调br0桥接或防火墙但真正原因往往是guest内部网卡命名变了。因为虚拟机在目标端启动时PCI插槽顺序可能变化原来的eth0变成了eth1而CentOS的静态IP配置还绑在eth0上结果新网卡没有IP。排查方法virsh console web-01 ip addr nmcli device如果确认是网卡命名漂移两种解法一是改/etc/sysconfig/network-scripts/ifcfg-eth0里的DEVICE为新网卡名更一劳永逸的是在XML里给网卡固定PCI地址前文提到过不要乱改PCI但给网卡绑定固定PCI号是迁移后的标准操作。6.2 热迁移一直卡在99%或进度不动dirty rate降不下来热迁移卡住九成以上是预拷贝不收敛。原因已经在原理章节用数字说明过脏页产生速率高于网络传输速率。表现就是迁移进度到了90%以上然后长时间不动domjobinfo里Data remaining反复在几百MB到1GB之间抖动。处理方案按优先级加大网络带宽或者为迁移流量单独走一条万兆VLAN缩短单轮传输时间调大停机时间上限让QEMU在最后一轮多承受一点脏页量virsh migrate --maxdowntime 20002000毫秒这样可收敛窗口变大业务会多停顿一小会儿如果上面都不行考虑--postcopy后拷贝模式先让虚拟机在目标端跑起来再把内存页从源端按需拉取能规避脏页收敛问题但要求平台支持post-copy且网络质量不能太差。生产环境的看法热迁移50分钟内还结束不了基本可以判定业务写内存速率远超预期继续等待没意义果断abort回到业务低峰期再操作。6.3 NFS权限导致的IO错误共享存储NFS权限设置错启动或迁移时会看到类似qemu: could not open disk image /data/kvm/web-01.raw: Permission denied。最坑的是报错不在执行迁移命令的宿主机而是在目标端的libvirtd日志里journalctl -u libvirtd -f处理方式比较简单确保两台宿主机挂载NFS的用户在存储端映射到同一个root权限也就是no_root_squash如果NFS是独立存储机存储机的防火墙也要放行NFS相关端口。端口不止2049还需要rpcbind111端口否则能mount成功但启动时IO会随机超时。建议直接把NFS服务加入防火墙白名单。6.4 迁移后guest时钟跳变KVM虚拟机的时钟模型通常有三种kvm-clock默认、rtc、pit。热迁移后guest时钟必须保持连续否则数据库、消息队列、分布式锁会踩到时间回头看的问题。如果你发现迁移后date跳了十几秒甚至几分钟首先确认XML里是否没关tscvirsh dumpxml web-01 | grep -i tsc如果 guest 用的cpu model不支持constant_tsc迁移时TSC频率可能发生变化guest内核时钟源会重新校准造成时间跳变。建议统一用host-model或显式指定checkfull的CPU模型并且装好chrony或ntpd它能在迁移完成后自动平滑校正。6.5 核心问题快速排查速查表现象可能原因优先排查项迁移命令报unknown flaglibvirt/qemu版本不一致统一版本升级后再试迁移后guest无法启动CPU模型不兼容检查XML cpu mode迁移卡在99%脏页率过高domjobinfo观察remaining考虑maxdowntime迁移后网络不通网卡PCI漂移进guest查IP/网卡名启动IO Permission deniedNFS权限或挂载问题检查no_root_squash和防火墙端口迁移成功但业务断连停机拷贝窗口太长检查--maxdowntime调小停机时间7. 一些在实验之外才想明白的事做完整套实验之后我最大的体会是KVM热迁移表面上是一条命令背后其实是内存追踪、CPU调度、存储IO、网络传输的协同。任何一环性能不达标结果不是迁移报错而是“看起来成功但业务悄悄受损”这种隐患比失败还要恼人。如果你刚入门建议先在NFS共享存储的简单拓扑下把冷迁移跑熟再上热迁移。不要一上来就搞非共享存储热迁移那是把存储的复杂度叠到迁移上排障时很难分清到底是存储慢还是迁移协议问题。最后分享一个小技巧迁移前最好先手动sync一次guest内的文件系统把被缓存的数据主动落盘能显著降低预拷贝期间的内存脏页率。我这次实验里同样的8GB虚拟机做了一次sync后热迁移总时间缩短了将近三分之一。这个操作普通文档很少提到但实测下来很有用。如果后续你有把热迁移常态化跑进生产环境的计划可以考虑把迁移配置固化到libvirt的hooks脚本里迁移完成后自动校验业务端口、自动恢复NTP校正、自动刷新DNS记录。KVM迁移从来不是终点能把它嵌进自动化运维体系才算真正把KVM高级功能用出价值。
返回列表