Shell脚本如何迁移虚拟机到其他宿主机

wen 实用脚本 1

本文目录导读:

Shell脚本如何迁移虚拟机到其他宿主机

  1. 冷迁移
  2. 环境检查

在Shell脚本中迁移虚拟机到其他宿主机,主要取决于你使用的虚拟化平台(如KVM/libvirt、VMware、Hyper-V等),以下针对最常见的 KVM/libvirt 环境提供几种主流迁移方式的 Shell 脚本实现。

基于 libvirt 的在线迁移(热迁移)

适用于需要零停机时间的场景,要求源和目标宿主机共享存储(NFS、iSCSI、GlusterFS等)。

#!/bin/bash
# live_migration.sh - 虚拟机在线迁移脚本
# 参数配置
VM_NAME=$1          # 虚拟机名称
TARGET_HOST=$2      # 目标宿主机IP或主机名
TARGET_SSH_USER=${3:-"root"}  # 目标宿主机SSH用户
# 检查参数
if [ $# -lt 2 ]; then
    echo "用法: $0 <虚拟机名称> <目标宿主机> [SSH用户]"
    echo "示例: $0 web-server-01 192.168.1.102"
    exit 1
fi
# 确认虚拟机存在
if ! virsh dominfo "$VM_NAME" &>/dev/null; then
    echo "错误: 虚拟机 '$VM_NAME' 不存在"
    exit 1
fi
# 检查目标主机连通性
if ! ping -c 1 "$TARGET_HOST" &>/dev/null; then
    echo "错误: 无法连接到目标宿主机 $TARGET_HOST"
    exit 1
fi
# 检查源和目标是否共享存储(通过检查同一路径是否存在)
TEST_PATH="/var/lib/libvirt/images/test_shared.tmp"
if ssh "$TARGET_SSH_USER@$TARGET_HOST" "touch $TEST_PATH" && rm -f "$TEST_PATH"; then
    echo "存储共享检查通过"
else
    echo "警告: 无法确认存储共享,请确保使用共享存储"
fi
# 执行在线迁移
echo "开始迁移虚拟机 '$VM_NAME' 到 $TARGET_HOST ..."
virsh migrate --live \
              --verbose \
              --persistent \
              --undefinesource \
              --domain "$VM_NAME" \
              --desturi "qemu+ssh://$TARGET_SSH_USER@$TARGET_HOST/system" \
              --migrateuri "tcp://$TARGET_HOST:49152"
# 检查迁移结果
if [ $? -eq 0 ]; then
    echo "迁移成功完成!"
    echo "虚拟机 '$VM_NAME' 现在运行在 $TARGET_HOST"
else
    echo "迁移失败,请检查日志"
    exit 1
fi

使用前提:

  • 源和目标宿主机安装 libvirt 和 qemu-kvm
  • 配置 SSH 密钥认证(免密登录)
  • 启用 libvirt TCP 迁移(/etc/libvirt/libvirtd.conf 中设置 listen_tls=0, listen_tcp=1

离线迁移(冷迁移 + 文件复制)

适用于非关键业务,需要复制磁盘文件到目标宿主机。

#!/bin/bash
# cold_migration.sh - 虚拟机离线迁移脚本
VM_NAME=$1
TARGET_HOST=$2
TARGET_STORAGE=${3:-"/var/lib/libvirt/images"}
LOCAL_STORAGE=$(virsh dumpxml "$VM_NAME" | sed -n "s|.*source file='\([^']*\)'.*|\1|p")
# 关闭虚拟机
echo "正在关闭虚拟机 '$VM_NAME'..."
virsh shutdown "$VM_NAME"
while virsh domstate "$VM_NAME" | grep -q "running"; do
    sleep 2
    echo "等待虚拟机完全关闭..."
done
# 获取磁盘路径
echo "获取磁盘文件路径..."
DISK_FILES=()
while IFS= read -r line; do
    DISK_FILES+=("$line")
done < <(virsh dumpxml "$VM_NAME" | grep "source file" | sed "s/.*'\([^']*\)'.*/\1/")
# 复制磁盘文件到目标主机
for DISK in "${DISK_FILES[@]}"; do
    echo "复制磁盘文件: $DISK 到 $TARGET_HOST:$TARGET_STORAGE/"
    scp "$DISK" "root@$TARGET_HOST:$TARGET_STORAGE/"
    if [ $? -ne 0 ]; then
        echo "磁盘复制失败,请检查网络和权限"
        exit 1
    fi
done
# 导出并修改XML配置文件
echo "导出并修改XML配置..."
virsh dumpxml "$VM_NAME" > /tmp/${VM_NAME}_migrate.xml
# 修改磁盘路径为目标路径
for DISK in "${DISK_FILES[@]}"; do
    NEW_DISK_PATH="$TARGET_STORAGE/$(basename $DISK)"
    sed -i "s|$DISK|$NEW_DISK_PATH|g" /tmp/${VM_NAME}_migrate.xml
done
# 将XML复制到目标主机
scp /tmp/${VM_NAME}_migrate.xml "root@$TARGET_HOST:/etc/libvirt/qemu/${VM_NAME}.xml"
# 在目标主机上定义并启动虚拟机
ssh "root@$TARGET_HOST" "virsh define /etc/libvirt/qemu/${VM_NAME}.xml && virsh start $VM_NAME"
# 在源主机上清除虚拟机定义
virsh undefine "$VM_NAME"
# 清理临时文件
rm -f /tmp/${VM_NAME}_migrate.xml
echo "迁移完成!虚拟机 '$VM_NAME' 已迁移到 $TARGET_HOST"

使用 virt-v2v 迁移到其他宿主机(异构环境)

适用于 KVM 到 KVM 或不同虚拟化平台间迁移。

#!/bin/bash
# virt_v2v_migration.sh - 使用virt-v2v工具迁移
SOURCE_VM=$1
TARGET_HOST=$2
# 安装必要工具
if ! command -v virt-v2v &>/dev/null; then
    echo "安装 virt-v2v..."
    yum install -y virt-v2v  # 适用于 CentOS/RHEL
    # apt install virt-v2v   # 适用于 Ubuntu
fi
# 创建临时存储目录
TEMP_DIR="/tmp/v2v_${SOURCE_VM}"
mkdir -p "$TEMP_DIR"
# 执行转换迁移
echo "开始转换并迁移虚拟机..."
virt-v2v -i libvirt -ic "qemu:///system" \
         -o libvirt -oc "qemu+ssh://root@$TARGET_HOST/system" \
         -os "/var/lib/libvirt/images" \
         -on "$SOURCE_VM" \
         -of qcow2 \
         -b br0 \
         -n default \
         "$SOURCE_VM" 2>&1 | tee "$TEMP_DIR/migration.log"
# 检查迁移结果
if [ $? -eq 0 ]; then
    echo "迁移成功!请检查目标主机上的虚拟机状态"
else
    echo "迁移失败,请查看日志: $TEMP_DIR/migration.log"
    exit 1
fi
# 清理临时目录
rm -rf "$TEMP_DIR"

通用迁移检查脚本(先验证环境)

#!/bin/bash
# check_migration_env.sh - 迁移前环境检查
MIGRATION_METHOD=${1:-"live"}
SOURCE_HOST=$(hostname)
TARGET_HOST=$2
check_required_ports() {
    echo "检查必要端口..."
    for port in 22 16509 49152; do
        nc -zv "$TARGET_HOST" "$port" &>/dev/null && \
        echo "  ✓ 端口 $port 可达" || \
        echo "  ✗ 端口 $port 不可达"
    done
}
check_ssh_auth() {
    echo "检查SSH密钥认证..."
    ssh -o BatchMode=yes "root@$TARGET_HOST" "echo SSH_OK" &>/dev/null && \
    echo "  ✓ SSH密钥认证正常" || \
    echo "  ✗ SSH密钥认证失败,请配置免密登录"
}
check_shared_storage() {
    echo "检查共享存储..."
    if df -h | grep -qE "(nfs|glusterfs|ceph)"; then
        echo "  ✓ 检测到共享存储"
    else
        echo "  ! 未检测到共享存储,只能执行离线迁移"
    fi
}
# 主检查流程
echo "======= 迁移环境检查 ======="
echo "源宿主机: $SOURCE_HOST"
echo "目标宿主机: $TARGET_HOST"
echo "迁移方式: $MIGRATION_METHOD"
echo "============================"
check_required_ports
check_ssh_auth
check_shared_storage
echo "============================"
echo "环境检查完成"

使用注意事项

  1. 网络要求

    • 所有宿主机之间需要网络互通
    • 热迁移需要至少 1Gbps 网络带宽
    • 配置合适的防火墙规则
  2. 存储要求

    • 热迁移必须使用共享存储
    • 冷迁移需要足够磁盘空间和网络传输时间
  3. 版本兼容性

    • 源和目标宿主机libvirt版本尽量一致
    • CPU特性要兼容(可使用CPU模式host-model
  4. 调用示例

    # 热迁移
    ./live_migration.sh myvm 192.168.1.101

冷迁移

./cold_migration.sh myvm 192.168.1.101 /data/images

环境检查

./check_migration_env.sh live 192.168.1.101


根据实际环境选择合适的迁移方式,生产环境建议先在测试环境验证。

抱歉,评论功能暂时关闭!