资讯详情

资讯详情

OpenStack实例迁移实操:冷迁移与热迁移的选型、命令与排查

Migrate Instance也就是OpenStack里的实例迁移是我在运维虚拟化集群时最常用、也最怕用错的一个功能。说它常用是因为宿主机维护、负载均衡、故障规避都离不开它说它怕用错是因为冷迁移和热迁移的适用场景完全不同一旦选错方式轻则业务中断时间超出预期重则实例直接进入ERROR状态需要人工介入恢复。这个系列已经写到第40篇前面我们把OpenStack的架构、计算节点、存储、网络都过了一遍今天这篇就专门把Migrate Instance这件实操性极强的事彻底讲透。迁移操作本质上解决的是“虚拟机与宿主机绑定”的问题。物理机总有寿命负载总会不均衡磁盘总会亮告警灯这些时候你既不能接受业务停摆也不能眼睁睁看着风险扩大。Migrate Instance就是那个让虚拟机动起来的手段把一台虚拟机从当前宿主机搬到另一台宿主机迁移过程中实例ID、IP、主机名、磁盘数据都不变变的只是它跑在哪个物理机上。这篇文章适合正在维护OpenStack生产环境的运维工程师也适合刚接触虚拟化、想在测试环境里把迁移机制吃透的学习者。我尽量把原理、命令、踩坑记录都写成可以直接抄作业的形式。1. Migrate Instance 到底在解决什么问题1.1 为什么运维要频繁做实例迁移先说一个最典型的场景。某天早上你收到监控告警一台计算节点nova-compute的硬盘SMART信息开始报错或者内存ECC纠错次数持续上升。这时候这台宿主机上的几十台虚拟机都处在“风险区”你需要在硬件彻底损坏前把它们全部搬到别的宿主机上。如果没有迁移能力就只能停机、拔盘、换硬件、再开机整个过程中业务全部中断。有了迁移能力尤其是在线迁移一台接着一台把虚拟机搬走业务几乎感知不到变化硬件维护窗口甚至可以选在工作时间。第二个高频场景是负载均衡。OpenStack集群跑了一段时间后不同宿主机上的资源使用率会严重失衡。有的是因为早期调度没规划好有的是因为后来某些大规格实例集中创建在某几台机器上。内存超售率超过预期、CPU steal指标飙高、磁盘IO延迟增大这些都会影响业务稳定性。通过实例迁移把高负载宿主机上的部分虚拟机挪到空闲节点是成本最低、见效最快的调优手段。还有一个场景容易被忽略架构调整。比如把虚拟机从老旧的KVM宿主机迁移到新采购的、支持AVX-512或者NUMA亲和性更好的机器上比如把原来走本地存储的实例逐步迁移到Ceph后端比如机房机柜调整需要整体搬移一批宿主机。这些都属于计划内迁移完全可以安排在业务低峰期一个个处理。理解了这些场景你会发现Migrate Instance不是“偶尔用一次的高级功能”而是OpenStack运维的基本功。1.2 冷迁移和热迁移该怎么选OpenStack里的实例迁移分为两大类搞清楚区别是入门的第一道坎。冷迁移Cold Migration对应命令nova migrate它做的事是先在源宿主机上把虚拟机关机然后调度到目标宿主机把磁盘数据搬过去最后在目标宿主机上重新开机。整个过程虚拟机处于停机状态业务中断时间取决于磁盘大小和存储网络带宽。冷迁移的优点是逻辑简单、依赖少、失败风险低缺点就是“要停机”所以通常用在可以接受短暂停机的场景比如非核心应用、计划内维护窗口、或者源宿主机已经宕机需要恢复实例的场景。热迁移Live Migration对应命令nova live-migration它不关机通过libvirt/QEMU的迁移协议把虚拟机内存状态和磁盘状态从源主机同步到目标主机最终在目标主机上无缝接管运行。业务中断时间通常不足一秒是保证高可用运维的关键手段。但热迁移的约束条件也多CPU特性要兼容、存储要能打通、网络要互通、libvirt版本不能差太远任何一个环节掉链子都会导致迁移失败。这是我自己的选型判断宿主机计划内维护、要做硬件升级能用热迁移就别用冷迁移源宿主机已经宕机或者实例本来就在关机状态直接冷迁移实例承载的是非核心业务且磁盘量巨大冷迁移反而更稳因为热迁移大内存虚拟机时如果内存变化太快无法收敛风险反而更高。还有一点要记住冷迁移是“先停后搬再开”热迁移是“边跑边搬再切换”两者失败后的后果也不一样冷迁移失败实例还在原主机上关机热迁移失败虚拟机可能两头都不稳定所以线上操作前一低要先备份再动手。2. 迁移前的环境体检这些检查项一个都不能省每次实施迁移前我都会花几分钟做一轮环境检查。看起来多花了几分钟实际是省掉后面几小时的故障排查时间。很多迁移失败案例根源都在迁移前没确认好存储架构和CPU兼容性。2.1 存储架构决定迁移方式共享存储还是本地盘这是最关键、也最容易被新手忽略的地方。Nova 实例的磁盘分两部分根盘root disk和临时盘ephemeral disk另外还可能挂载Cinder云硬盘。这些盘放在哪里直接决定了热迁移能不能做、怎么做。如果/var/lib/nova/instances这个目录在三台宿主机之间通过NFS共享或者实例的根盘和临时盘都落在Ceph RBD里那么所有宿主机天然都能看到同一份磁盘数据。这种架构下热迁移只需要传输内存状态不需要拷贝磁盘迁移速度快、网络带宽消耗小。命令上也不需要额外加参数直接nova live-migration server host就行。如果实例的磁盘是纯本地盘每台宿主机各存各的那热迁移就必须同时把磁盘数据也搬过去这就是 block migration。OpenStack会在迁移过程中阶段性地把磁盘内容同步到目标主机再结合内存同步一起完成切换。block migration会占用大量存储网络带宽磁盘越大的实例耗时越长。老版本的nova live-migration需要用--block-migrate参数显式开启新版本用openstack server migrate --live dst server --block-migration。我在实际运维中见过有人以为声卡共享存储就没加block参数结果迁移开始后发现实例状态一直卡住日志里报找不到磁盘就是这个原因。判断当前环境是哪种存储架构用两个命令就能看清。登录计算节点执行df -h | grep nova看/var/lib/nova/instances是否挂载了NFS或共享文件系统再执行ls /var/lib/nova/instances/instance_id看看里面是实际磁盘文件还是软链接。如果磁盘文件指向/var/lib/ceph或者/dev/rbd基本就可以确定走的是Ceph后端。2.2 CPU、内存与宿主机资源盘点热迁移有个硬性前提目标宿主机CPU必须兼容源宿主机CPU。不是说型号必须完全一致而是目标CPU提供的指令集必须能覆盖源CPU上虚拟机正在使用的指令集。举个例子源宿主机是Intel Xeon Gold 6248目标宿主机是Intel Xeon Silver 4210两者都是Cascade Lake架构指令集大体一致迁移没问题。如果目标宿主机是AMD EPYC或者Intel和AMD混合池那就非常容易出现CPU不兼容导致的迁移失败。保障CPU兼容性最好的办法是在部署OpenStack之初就规划好CPU模式。在/etc/nova/nova.conf的[libvirt]段cpu_mode建议配置成host-model这样Nova会挑选源和目标宿主机CPU特性的交集给虚拟CPU用。如果整个集群的物理CPU型号统一也可以配置成host-passthrough性能最好但跨型号就没法迁移了。如果集群里新老机器混用我建议干脆配置一个较老的基础型号比如cpu_modecustom加上cpu_modelSandyBridge性能损失一点但保证了迁移的灵活性这在混合硬件池里非常实用。内存方面目标宿主机除了满足实例本身的内存规格还得预留足够的内存给页表开销和热迁移过程中的临时内存。我自己的经验是目标宿主机剩余内存至少要大于实例内存的110%。磁盘空间同理block migration时目标主机上至少要有实例已用磁盘空间的1.3倍。这些都可以用nova hypervisor-show hostname来查看重点关注memory_mb_used、free_ram_mb、local_gb_used这几栏。2.3 nova 服务状态与关键配置核对迁移是多个组件合作完成的。源计算节点要发起迁移目标计算节点要接收实例nova-conductor负责状态协调nova-scheduler负责在冷迁移时挑选目标主机如果用了Neutron迁移完成后还要做网络层面的绑定更新。任何一层服务异常都建议不要开始批量迁移。操作很简单登录控制节点执行nova service-list确认所有nova-compute、nova-scheduler、nova-conductor的状态都是enabled且up。同时也要确认目标宿主机上的nova-compute日志里没有未恢复的异常比如磁盘满、文件系统只读、libvirt连接断开等。再就是检查网络连通性源和目标宿主机之间要能互相访问libvirt迁移默认走管理网络管理网络的延迟和带宽会直接影响迁移速度和成功率。配置上有个平时不起眼、关键时刻致命的选项。/etc/nova/nova.conf的[libvirt]段里有一项live_migration_tunnelled默认是false。如果把它配成true迁移流量会走加密隧道安全性和隔离性更好但性能开销很大大内存实例迁移容易超时。生产环境没有特别的合规要求我建议保持默认同时保证计算节点之间的管理网络是隔离和可信的。3. 冷迁移实操nova migrate 完整记录冷迁移看起来简单但里面有几个容易被忽视的细节。我把整个流程从头到尾走一遍包括命令、参数、状态观察和迁移后的确认项。3.1 冷迁移的核心流程与命令冷迁移本质上是“先关机再搬家后开机”。第一次接触这个操作的人可能会觉得既然命令只有一个过程应该很简单。但实际上OpenStack在后台做了一系列工作先通过scheduler在目标主机池里筛选出符合条件的宿主机然后在源宿主机上shutdown实例接着把实例的磁盘数据复制到目标宿主机最后在目标宿主机用libvirt重新定义并启动虚拟机。整个过程在数据库里的状态流转大致是ACTIVE - MIGRATING - SHUTDOWN - BUILDING - ACTIVE。命令行操作很简单nova migrate server-uuid-or-name如果集群里有多个可用域或主机聚合想让Nova只从指定主机聚合里选目标可以加参数nova migrate server-uuid --availability-zone nova:aggregate-name执行后可以用以下命令跟踪状态nova show server-uuid nova migration-listmigration-list能看到这次迁移的类型、源主机、目标主机和状态。冷迁过程的status通常是pre-migrating、migrating、post-migrating和done这样一个顺序。如果看到error直接去nova-compute.log里查原因。有一点我必须提醒如果你要迁移的这个实例有不同的flavor比如从m1.small改到m1.medium那不能直接叫“迁移”那是nova resize。冷迁移和resize在End down层其实是同一套Resize流程只是迁移时flavor不变。这个设计很多人不知道排查问题时会走弯路。3.2 用 --block-migration 处理本地磁盘刚才在第2章提过冷迁移默认只在共享存储架构下才能工作。如果实例的磁盘在本地直接执行nova migrate会失败或者调度器根本不选择目标主机。这时候必须显式告诉Nova要迁移本地磁盘。nova migrate server-uuid --block-migrate新版本OpenStack用OpenStackClient命令的话是export OS_COMPUTE_API_VERSION2.56 openstack server migrate server-uuid --block-migration--block-migrate的含义是允许Nova把本地磁盘一起拷贝过去。加了参数后迁移刚开始时会进行一次磁盘的全量镜像后续再按块同步增量数据。对于只有10GB左右的小盘很快就能完成对于几百GB甚至几TB的大数据盘冷迁移的耗时会很长这时建议提前计算带宽评估停机窗口。还有个参数--disk-over-commit它允许目标宿主机在磁盘超售状态下容纳本次迁移。生产环境我会建议默认不开启除非你知道目标宿主机确实还有缓冲空间。磁盘超售的坑我在后面常见问题里再展开。3.3 冷迁移后要做的三件确认冷迁移完成后第一件事是确认实例状态已经回到ACTIVE这个用nova show server-uuid一眼就能看到。第二件事是确认实例所在宿主机确实变了看nova show输出里的OS-EXT-SRV-ATTR:host字段或者用nova list --host hostname反查。第三件事是同网络连通性进入实例执行ping网关或DNS确认虚拟网络在目标宿主机上正常工作。第三件事最容易被忽略。尤其在使用VLAN或OpenVSwitch的网络模式下目标宿主机上的网络要能识别新的虚拟端口。偶尔会出现实例成功拉起但网络不通的情况这通常不是迁移本身的问题而是目标宿主机的网桥或ovs配置没同步。这个坑我踩过一次后来养成了条件反射迁移完任何实例第一件事先测网络再通知业务方。冷迁移还会带来一个变化虚拟CPU所在的NUMA节点、PCI设备直通绑定、SR-IOV虚拟功能等与硬件强相关的东西可能需要重新适配。如果源实例启用了CPU pinningvcpu_pin_set或NUMA亲和性迁移后Nova会尝试在目标宿主机上重新计算绑定关系目标宿主机没有合适拓扑时实例会进入ERROR。生产环境确有这种需求的话建议用主机聚合把满足NUMA拓扑的宿主机聚到一块冷迁移时指定到这个聚合里。4. 在线迁移实操nova live-migration 关键细节如果说冷迁移是“搬家式”操作那热迁移就是“熨斗式”操作。实例一边跑一边搬最后在目标机上无缝接管。这一章我把在线迁移的原理和实操细节完整拆开讲。4.1 在线迁移的原理预拷贝与内存收敛OpenStack在线迁移调用的是libvirt的virDomainMigrateToURI底层实现是QEMU的Migration。现在用得最多的是预拷贝模式pre-copy流程大致是先建立连接在目标宿主机上创建好空的虚拟机对象。然后把源虚拟机的所有内存页全量传输到目标主机这个过程叫“全量同步”。传输过程中源虚拟机还在运行内存数据不断变化于是QEMU会把变化过的内存页记录成脏页dirty pages。全量同步结束后QEMU开始周期性传输脏页每轮传完统计剩余脏页数量如果数量在逐步减小说明内存变化速率小于传输速率系统会继续迭代。直到脏页数量压到一个阈值以下QEMU暂停源虚拟机停机时间极短把剩余的脏页和CPU寄存器状态一起传给目标机然后目标机接管启动。这个“收敛”过程是热迁移成败的核心。如果一个虚拟机内存写入特别频繁比如跑着大型内存数据库每轮脏页量非但不减反增QEMU怎么都等不到收敛迁移就会长时间处于MIGRATING状态源机和目标机两边都在硬撑着风险很高。遇到这种场景可以使用QEMU的自动收敛机制或者切换到后拷贝模式post-copy后拷贝先把CPU状态传过去目标机先跑起来内存页按需从源机拉取但代价是源机一旦故障目标机可能跟着崩溃。生产环境我是建议默认别开post-copy宁可业务低峰期迁移。4.2 共享存储下的快速迁移共享存储架构下做热迁移是所有场景里最省心的。因为目标宿主机本来就能看到同一份磁盘迁移时不需要复制磁盘只需要同步内存和虚拟机的运行状态。命令很简洁nova live-migration server-uuid target-host如果第二项不填目标宿主机Nova会让scheduler自己挑一个符合条件的宿主机。我一般会显式指定目标因为心里有数知道哪台机器的资源余量足、哪台机器网络路径短。指定目标还能避免scheduler选到同机架内网络带宽突出的机器之后反而引起流量拥塞。共享存储热迁移的执行速度很快一个8GB内存的实例通常几十秒到一两分钟就能完成。迁移期间可以通过下面命令观察状态openstack server migration list --server server-uuid输出的Migration Type是liveStatus从running变成completed就是成功。也可以实时看源和目标宿主机上的nova-compute日志里面会有Live migration succeeded之类的字样。注意一点如果使用的是NFS共享存储迁移前最好确认一下/var/lib/nova/instances挂载正常并且有足够的INode和文件句柄。NFS在IO高峰期容易出现锁等待或延迟毛刺曾有例子实例迁移中途NFS重新挂载导致虚拟机的磁盘IO卡死。对于NFS环境我会在迁移前用df -i查inode用nfsstat -l检查NFS连接数是否异常。4.3 非共享存储的 block migration本地磁盘架构下做在线迁移命令要加--block-migrate。这个参数通知Nova在迁移内存的同时同步磁盘块。原理类似预拷贝先是磁盘全量复制然后同步内存最后切换。因为磁盘复制会持续很长时间整个迁移耗时主要取决于磁盘大小和网络带宽。老版本命令nova live-migration server-uuid target-host --block-migrate新版本openstack server migrate --live target-host server-uuid --block-migrationblock migration有几个需要特别注意的坑第一要确保目标宿主机有足够的磁盘空间否则迁移到一半会因为写不进去而失败。经验值是预留实例磁盘已用量的1.2到1.5倍。前面提过--disk-over-commit参数这时候如果加上Nova会忽略磁盘空间的严格校验风险自行承担。第二block migration会占用大量存储网络带宽。计算节点之间如果只有千兆管理网络一个200GB磁盘的实例迁移得折腾很久。建议在计算节点之间配置独立的存储网络或者在[libvirt]段设置live_migration_bandwidth00代表不限速或设置为具体Mbps限制。第三Cinder卷不在block migration的范围内。Cinder卷如果是iSCSI或FC SAN只要目标宿主机能访问同一个LUN就能继续使用如果Cinder卷本身是本地LVM类型的lvm后端那实例其实没法跨宿主机迁移除非Cinder配置了多路径。这个细节在异构存储环境里特别容易踩雷。4.4 迁移进度、取消与超时处理在线迁移执行后如何判断到底还要多久最直观的是看目标宿主机的磁盘使用量和网络IO。迁移期间目标机上的/var/lib/nova/instances/instance_id目录里会越来越“丰满”网络带宽也会被占满。真实的迁移进度用下面命令看virsh migrate-setmaxdowntime domname 100或者从源宿主机上执行virsh qemu-monitor-command domname {execute:query-migrate}输出的ram部分里有remaining、total、dirty-sync-count等字段能看到剩余内存量和脏页同步次数。虽然不是人人都熟悉virsh但关键时刻这招真的能救命。注意domname一般是nova-instance-uuid这种格式。如果发现迁移迟迟不结束可以先上调允许的停机时间让QEMU更快收敛nova migrate --resize ... # 不是这个实际上Nova层面控制停机时间的参数在nova.conf的[libvirt]段live_migration_downtime 500 live_migration_downtime_steps 10 live_migration_downtime_delay 75含义是迁移过程中逐步把停机时间从初始值抬高到最大值给脏页收敛更大的容忍度。单位是毫秒。调大这个参数可以显著提高迁移成功率代价是切换瞬间的业务卡顿时间变长默认的几百毫秒其实业务几乎感知不到。如果实在等不下去或者迁移异常了可以中止迁移。老版本命令nova live-migration-abort server-uuid注意这个命令不是所有版本都支持新版OpenStack用openstack server migration delete server-uuid migration-id中止之后实例会继续在源宿主机上运行整体影响很小。这也是为什么热迁移被我列为“最怕用错但用对很爽”的功能。5. 常见故障与排查技巧实录迁移操作在真实环境里从来不是一路顺风我把这四五年遇到的高频故障和排查思路整理成了一份速查表基本可以覆盖90%的迁移事故场景。5.1 高频报错速查表现象可能原因处理办法迁移后实例变成ERROR目标宿主机磁盘空间不足、CPU不兼容、内存不足看源宿主机nova-compute日志定位释放目标机资源或换目标机迁移一直卡在MIGRATING内存脏页不收敛、网络带宽不足、libvirt连接异常上调downtime、检查网络、必要时中止迁移报LibvirtGuestError或internal error: process exited while connecting to monitorlibvirt版本不一致或目标机QEMU无法启动检查目标机libvirt和qemu版本查看目标机qemu日志报CPU does not support compatibilityCPU特性集不兼容改进CPU mode配置改为host-model或在目标机选择兼容CPU报No valid host foundscheduler找不到合适目标机检查主机聚合、资源过滤、是否共享存储条件不满足迁移时实例网络不通目标机网桥/OVS配置没同步、安全组规则没迁移检查目标机网桥重启neutron-agent手动排查虚拟端口迁移后原主机残留磁盘文件共享存储未正确清理手动移除源机残留目录注意先确认目标机已正常启动这个表是我踩坑经验的浓缩。有一次凌晨三点迁移一台核心业务虚拟机报错信息一直指向磁盘空间不足我以为是目标机空间不够反复清理了半个小时后来才发现是源机上一个老旧的虚拟机镜像文件占满了inode导致nova-compute写日志都写不进去。所以排查问题时别只看报错字面意思先看日志有没有写出来、时间戳是不是最新的。5.2 迁移卡住和失败时的排查路径遇到迁移卡住我的排查顺序是这样的先nova migration-list看当前迁移状态再检查源宿主机nova-compute.log最后100行。如果日志停在“waiting for event”或者“live migration - pre migration”之类的阶段说明还在等待目标机返回握手消息。接着检查目标宿主机的nova-compute日志看看有没有“receiving migration”等相关记录。如果目标机日志里完全没有动静大概率是网络问题或者libvirt连接没建立成功。测试libvirt连接可以手动在源宿主机上执行virsh -c qemussh://target-host/system list --all如果这条命令报错说明libvirt的认证、SSH密钥或TLS配置有问题。Nova计算节点之间的libvirt通信通常配置了SSH免密或者Salsify权限不对就会一直握手失败。很多“迁移卡住”的问题根源就是SSH密钥不互通。还有一种情况容易误判迁移实际上已经完成了但数据库里的状态没有更新。这时候用virsh list --all在目标机上看实例是否存在且running同时确认源机上实例已消失。如果两边状态对不上通常是nova-conductor的消息处理滞后等几分钟看看或者手动同步。5.3 避免迁移事故的实战经验迁移最怕什么最怕迁移中源宿主机突然宕机然后Nova从管理面看迁移还在进行实例状态变成ERROR业务两头落空。所以我给自己定了几条铁律第一条迁移前一定做好备份或快照。OpenStack原生支持openstack server backup create或Cinder卷快照再紧急也不省这一步。第二条批量迁移要有节奏。一次最多迁两三台迁完一台确认一台再继续下一台。不要图省事写个循环把所有实例一次性扔出去一旦目标机资源不足几十个实例集体进入ERROR就真变成事故了。第三条大内存实例一定要挑业务低峰期。热迁移大内存虚拟机本来就是IO密集内存密集的操作业务高峰期迁移脏页收敛慢迁移时间长对源机性能的影响也大。第四条迁移前先做一次目标机健康检查重点看内存、磁盘、网络和CPU型号。可以用nova hypervisor-show target-host看它各项资源使用率尤其确认vcpus和memory_mb是否满足新增实例的需求。这块如果检查不到位后续大概率会在迁移中途翻车。再说一个容易踩的坑使用共享存储时/var/lib/nova/instances下残留的旧目录。如果之前失败过源机上可能还有一份未清理的磁盘文件手动删的时候一定要确认目标机上的实例已经正常运行不然删错文件虚拟机起不来就麻烦了。另外热迁移虽然有“Live”字样但并不是绝对零风险。迁移过程中源机上的磁盘IO、内存带宽、CPU使用率都会有小幅波动对于超售严重的宿主机迁移行为本身就可能把宿主机拖垮。建议在迁移前看下宿主机load average和内存压力如果已经在临界值附近先手动把同机上的一些非核心实例迁走腾出资源再迁移目标实例。如果你用的是多架构虚拟机比如通过QEMU在x86宿主机上模拟ARM架构跑实例热迁移的难度会更大。架构模拟下的CPU特性检查、设备模型兼容性、固件配置都可能成为迁移失败的导火索。这类环境我建议先在小范围测试迁移别在正式生产环境里直接批量操作。多架构虚拟化本身是一个很有玩头的方向但迁移这块还没有x86原生虚拟化那么成熟稳妥优先。最后再分享一个我自己多年维持的习惯。每次迁移操作前我都会开一个终端窗口挂在journalctl -u nova-compute -f上再看一眼目标机的监控面板。迁移开始后我会同时盯着两件事迁移进度和业务侧告警。万一业务出现连接抖动或超时能第一时间在源机上取消迁移或者提前做回切。这套操作不复杂但能让每次迁移都稳得很。Migrate Instance这个功能说到底就是OpenStack把“计算资源可流动”这件事做成了标准能力。你把它用熟之后宿主机维护、资源调度、故障规避都会从容很多。这个系列后面还有不少内容下一期我打算继续往更深的虚拟化细节走把nova-compute、libvirt和QEMU之间那些交互原理掰开揉碎聊一聊。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →