09-KVM虚拟机迁移
虚拟机迁移是虚拟化环境中的重要功能,允许将虚拟机从一台物理主机迁移到另一台,实现负载均衡、硬件维护和灾难恢复等目的。
迁移类型概述
迁移分类
| 迁移类型 | 停机时间 | 应用场景 | 优缺点 | 
|---|---|---|---|
| 冷迁移 | 需要停机 | 硬件维护、长期迁移 | 简单可靠,但有停机时间 | 
| 热迁移(在线迁移) | 几乎无停机 | 负载均衡、无缝迁移 | 复杂度高,需要共享存储 | 
| 存储迁移 | 视情况 | 存储设备更换 | 可独立迁移存储 | 
| P2V迁移 | 需要停机 | 物理机转虚拟机 | 可将物理服务器虚拟化 | 
迁移要求
冷迁移要求:
- 目标主机有足够资源
- 网络连通性
热迁移要求:
- 共享存储(NFS、iSCSI等)
- 相同的CPU架构
- 网络连通性良好
- 时间同步
冷迁移
方法一:复制磁盘文件
# 1. 关闭虚拟机
virsh shutdown web01
# 2. 导出虚拟机配置
virsh dumpxml web01 > /tmp/web01.xml
# 3. 复制磁盘文件到目标主机
scp /data/web01.qcow2 root@target-host:/data/
scp /tmp/web01.xml root@target-host:/tmp/
# 4. 在目标主机导入
# 登录目标主机
ssh root@target-host
# 导入虚拟机定义
virsh define /tmp/web01.xml
# 启动虚拟机
virsh start web01
方法二:使用virsh migrate(离线)
# 离线迁移到目标主机
virsh migrate --offline --persistent \
  --undefinesource \
  web01 qemu+ssh://root@target-host/system
方法三:导出导入方式
# 1. 导出虚拟机
virsh shutdown web01
virsh dumpxml web01 > web01.xml
cp /data/web01.qcow2 /backup/
# 2. 打包传输
tar czf web01-vm.tar.gz web01.xml /backup/web01.qcow2
scp web01-vm.tar.gz root@target-host:/tmp/
# 3. 在目标主机解压导入
tar xzf /tmp/web01-vm.tar.gz
virsh define web01.xml
热迁移(在线迁移)
环境准备
1. 配置共享存储
# 配置NFS共享存储(在存储服务器上)
mkdir -p /nfs/kvm
echo "/nfs/kvm *(rw,sync,no_root_squash)" >> /etc/exports
systemctl start nfs-server
systemctl enable nfs-server
exportfs -r
# 在所有KVM主机上挂载
mkdir -p /shared-storage
mount -t nfs storage-server:/nfs/kvm /shared-storage
echo "storage-server:/nfs/kvm /shared-storage nfs defaults 0 0" >> /etc/fstab
2. 配置主机间免密访问
# 在源主机生成密钥
ssh-keygen -t rsa -N ""
# 复制到目标主机
ssh-copy-id root@target-host
# 测试连接
ssh root@target-host hostname
3. 时间同步
# 配置NTP服务
yum install -y chrony
systemctl start chronyd
systemctl enable chronyd
# 验证时间同步
chronyc sources
执行热迁移
基本热迁移命令
# 简单热迁移
virsh migrate --live web01 \
  qemu+ssh://root@target-host/system
# 详细参数热迁移
virsh migrate --live \
  --persistent \
  --undefinesource \
  --verbose \
  --compressed \
  web01 qemu+ssh://root@target-host/system
高级迁移选项
# 指定迁移带宽(限制为100MB/s)
virsh migrate --live \
  --bandwidth 100 \
  web01 qemu+ssh://root@target-host/system
# 使用隧道加密
virsh migrate --live \
  --tunnelled \
  web01 qemu+ssh://root@target-host/system
# 自动收敛(加速迁移)
virsh migrate --live \
  --auto-converge \
  web01 qemu+ssh://root@target-host/system
监控迁移进度
# 查看迁移进度
virsh domjobinfo web01
# 取消迁移
virsh domjobabort web01
# 查看迁移统计
virsh domjobinfo web01 --completed
存储迁移
在线存储迁移
# 将虚拟机磁盘从本地迁移到共享存储
virsh blockcopy web01 vda \
  /shared-storage/web01.qcow2 \
  --wait --verbose --pivot
# 使用--blockdev选项进行块设备迁移
virsh blockcopy web01 vda \
  --dest /new-storage/web01.qcow2 \
  --wait --verbose --pivot --shallow
离线存储迁移
# 1. 关闭虚拟机
virsh shutdown web01
# 2. 转换并移动磁盘
qemu-img convert -f qcow2 -O qcow2 \
  /local-storage/web01.qcow2 \
  /shared-storage/web01.qcow2
# 3. 更新虚拟机配置
virsh edit web01
# 修改磁盘路径指向新位置
# 4. 启动虚拟机
virsh start web01
P2V迁移(物理机到虚拟机)
使用virt-p2v工具
# 1. 创建virt-p2v启动介质
# 下载virt-p2v ISO或创建
virt-p2v-make-disk -o /tmp/virt-p2v.img
# 2. 在物理机上启动virt-p2v
# 使用USB或网络启动
# 3. 配置转换参数
# - 目标KVM主机地址
# - SSH连接信息
# - 磁盘和网络映射
手动P2V迁移
# 1. 在物理机上创建磁盘镜像
dd if=/dev/sda | ssh root@kvm-host \
  "dd of=/data/physical-server.img"
# 2. 转换为qcow2格式
qemu-img convert -f raw -O qcow2 \
  /data/physical-server.img \
  /data/physical-server.qcow2
# 3. 创建虚拟机使用该磁盘
virt-install \
  --name physical-migrated \
  --memory 4096 \
  --vcpus 4 \
  --disk /data/physical-server.qcow2 \
  --import \
  --network bridge=br0 \
  --graphics vnc
跨版本迁移
CPU兼容性配置
# 查看CPU模型
virsh capabilities | grep -A5 "host"
# 配置CPU兼容模式
virsh edit web01
<!-- 修改CPU配置为兼容模式 -->
<cpu mode='custom' match='exact'>
  <model fallback='allow'>Westmere</model>
  <feature policy='disable' name='rdtscp'/>
</cpu>
使用CPU主机直通
<!-- 最大性能但限制迁移 -->
<cpu mode='host-passthrough'>
  <cache mode='passthrough'/>
</cpu>
<!-- 或使用host-model平衡性能和兼容性 -->
<cpu mode='host-model'>
  <model fallback='allow'/>
</cpu>
批量迁移
迁移脚本
#!/bin/bash
# batch-migrate.sh - 批量迁移虚拟机
TARGET_HOST="target-host"
VMS="web01 web02 db01"
for VM in $VMS; do
    echo "迁移虚拟机: $VM"
    
    # 检查虚拟机状态
    STATE=$(virsh domstate $VM)
    
    if [ "$STATE" == "running" ]; then
        # 热迁移
        virsh migrate --live --persistent \
          $VM qemu+ssh://root@$TARGET_HOST/system
    else
        # 冷迁移
        virsh migrate --offline --persistent \
          $VM qemu+ssh://root@$TARGET_HOST/system
    fi
    
    if [ $? -eq 0 ]; then
        echo "$VM 迁移成功"
    else
        echo "$VM 迁移失败"
    fi
done
并行迁移
# 使用GNU parallel并行迁移
parallel -j 3 virsh migrate --live {} \
  qemu+ssh://root@target-host/system ::: web01 web02 web03
迁移优化
网络优化
# 1. 使用专用迁移网络
virsh migrate --live \
  --migrate-uri tcp://migration-network:49152 \
  web01 qemu+ssh://root@target-host/system
# 2. 配置迁移端口范围
echo "migration_port_min = 49152" >> /etc/libvirt/qemu.conf
echo "migration_port_max = 49215" >> /etc/libvirt/qemu.conf
systemctl restart libvirtd
性能调优
# 1. 增加迁移并发度
virsh migrate-setmaxdowntime web01 500
# 2. 启用多线程压缩
virsh migrate --live \
  --compressed \
  --comp-methods mt \
  --comp-mt-level 5 \
  --comp-mt-threads 4 \
  web01 qemu+ssh://root@target-host/system
预拷贝优化
# 使用postcopy模式(减少停机时间)
virsh migrate --live \
  --postcopy \
  --postcopy-after-precopy \
  web01 qemu+ssh://root@target-host/system
故障处理
常见问题
- 
迁移失败:CPU不兼容 # 解决方案:使用CPU兼容模式
 virsh edit web01
 # 修改CPU mode为custom或host-model
- 
迁移超时 # 增加超时时间
 virsh migrate-setmaxdowntime web01 2000
 # 或调整迁移速度
 virsh migrate-setspeed web01 1000
- 
存储路径不一致 # 使用--migrate-disks指定磁盘
 virsh migrate --live \
 --migrate-disks vda,vdb \
 web01 qemu+ssh://root@target-host/system
迁移回滚
# 如果迁移失败,虚拟机仍在源主机
# 检查状态
virsh list --all
# 如果需要,重新启动
virsh start web01
# 清理目标主机的残留定义
ssh root@target-host "virsh undefine web01"
日志分析
# 查看迁移日志
tail -f /var/log/libvirt/qemu/web01.log
# 查看libvirtd日志
journalctl -u libvirtd -f
# 启用调试日志
echo 'log_level = 1' >> /etc/libvirt/libvirtd.conf
echo 'log_outputs = "1:file:/var/log/libvirt/libvirtd.log"' >> /etc/libvirt/libvirtd.conf
systemctl restart libvirtd
迁移验证
迁移后检查清单
#!/bin/bash
# post-migration-check.sh
VM_NAME=$1
echo "=== 迁移后验证:$VM_NAME ==="
# 1. 检查虚拟机状态
echo -n "虚拟机状态: "
virsh domstate $VM_NAME
# 2. 检查网络连接
echo -n "网络连接: "
virsh domifaddr $VM_NAME
# 3. 检查磁盘
echo "磁盘信息:"
virsh domblklist $VM_NAME
# 4. 检查性能
echo "性能统计:"
virsh domstats $VM_NAME
# 5. 连接测试
echo "控制台连接测试:"
timeout 5 virsh console $VM_NAME
自动化迁移
使用迁移策略
# migration-policy.yaml
migration_policy:
  load_threshold: 80
  target_hosts:
    - host1
    - host2
    - host3
  rules:
    - condition: "cpu_usage > 80%"
      action: "migrate_to_least_loaded"
    - condition: "memory_usage > 90%"
      action: "migrate_memory_intensive"
迁移调度脚本
#!/usr/bin/env python3
# auto-migrate.py - 自动迁移调度器
import libvirt
import statistics
def get_host_load(conn):
    """获取主机负载"""
    stats = conn.getCPUStats(libvirt.VIR_NODE_CPU_STATS_ALL_CPUS)
    return stats['user'] + stats['system']
def find_best_target(exclude_host):
    """找到负载最低的目标主机"""
    hosts = ['kvm1', 'kvm2', 'kvm3']
    loads = {}
    
    for host in hosts:
        if host != exclude_host:
            conn = libvirt.open(f'qemu+ssh://root@{host}/system')
            loads[host] = get_host_load(conn)
            conn.close()
    
    return min(loads, key=loads.get)
def migrate_vm(vm_name, source_host, target_host):
    """执行迁移"""
    source = libvirt.open(f'qemu+ssh://root@{source_host}/system')
    target = libvirt.open(f'qemu+ssh://root@{target_host}/system')
    
    vm = source.lookupByName(vm_name)
    vm.migrate(target, libvirt.VIR_MIGRATE_LIVE | 
               libvirt.VIR_MIGRATE_PERSIST_DEST |
               libvirt.VIR_MIGRATE_UNDEFINE_SOURCE)
    
    source.close()
    target.close()
最佳实践
迁移最佳实践
- 规划先行:评估网络带宽、存储性能和CPU兼容性
- 测试环境:先在测试环境验证迁移流程
- 监控为主:全程监控迁移进度和系统状态
- 备份重要:迁移前备份关键数据和配置
- 时间选择:选择业务低峰期进行迁移
- 回滚方案:准备好快速回滚计划
总结
本章详细介绍了KVM虚拟机迁移的各种方式:
- ✅ 冷迁移和热迁移的实施方法
- ✅ 存储迁移和P2V迁移技术
- ✅ 跨版本和批量迁移方案
- ✅ 迁移优化和故障处理
- ✅ 自动化迁移和最佳实践
掌握这些迁移技术,可以实现虚拟化环境的灵活管理和高可用性。下一章将介绍KVM图形化管理工具。