作为一名运维工程师,我经常需要在不同服务器之间迁移KVM虚拟机。最近在将开发环境从旧服务器迁移到新硬件时,就遇到了需要批量转移20多个虚拟机的需求。经过多次实践,我总结出一套完整的KVM虚拟机导出导入方法,包括手动操作和自动化脚本方案。
KVM(Kernel-based Virtual Machine)作为Linux内核原生的虚拟化解决方案,相比VirtualBox等第三方工具具有更好的性能和资源利用率。但在虚拟机迁移方面,很多新手可能会觉得无从下手。其实只要掌握几个关键命令和文件位置,整个过程就会变得非常简单。
在开始迁移前,首先需要确认源主机和目标主机的KVM环境是否正常。执行以下命令检查libvirtd服务状态:
bash复制systemctl status libvirtd
如果服务未运行,需要先启动服务:
bash复制systemctl start libvirtd
systemctl enable libvirtd
使用virsh命令列出当前主机上的所有虚拟机:
bash复制virsh list --all
输出示例:
code复制 Id Name State
------------------------------------
- Ubuntu-Web shut off
- CentOS-DB shut off
- Debian-CI shut off
重要提示:迁移前请确保虚拟机处于关闭状态(shut off),运行中的虚拟机直接迁移可能导致数据不一致。
每个KVM虚拟机的配置信息都以XML格式存储,使用virsh dumpxml命令可以导出:
bash复制virsh dumpxml Ubuntu-Web > Ubuntu-Web.xml
这个XML文件包含了虚拟机的所有配置信息,包括CPU、内存、网络、磁盘等设置。建议用文本编辑器打开查看,了解各个配置项的含义。
虚拟机磁盘文件默认存放在/var/lib/libvirt/images/目录下,可以通过以下命令确认具体路径:
bash复制virsh dumpxml Ubuntu-Web | grep -i "source file"
输出示例:
code复制<source file='/var/lib/libvirt/images/Ubuntu-Web.qcow2'/>
如果使用了LVM或其他存储后端,磁盘路径会有所不同。这时需要特别注意,确保迁移时包含所有相关存储卷。
bash复制mkdir -p ~/vm_backup/Ubuntu-Web
bash复制virsh dumpxml Ubuntu-Web > ~/vm_backup/Ubuntu-Web/config.xml
bash复制sudo cp /var/lib/libvirt/images/Ubuntu-Web.qcow2 ~/vm_backup/Ubuntu-Web/
bash复制ls -lh ~/vm_backup/Ubuntu-Web/
在目标主机上,需要确保:
将备份文件从源主机传输到目标主机,可以使用scp或rsync:
bash复制scp -r ~/vm_backup/Ubuntu-Web user@newhost:/tmp/
在目标主机上,使用virsh define命令注册虚拟机:
bash复制virsh define /tmp/Ubuntu-Web/config.xml
成功后会有"Domain Ubuntu-Web defined from /tmp/Ubuntu-Web/config.xml"的提示。
将磁盘文件复制到目标主机的libvirt存储目录:
bash复制sudo cp /tmp/Ubuntu-Web/Ubuntu-Web.qcow2 /var/lib/libvirt/images/
注意:如果目标主机使用了不同的存储路径,需要先修改XML文件中的磁盘路径定义。
启动虚拟机并检查状态:
bash复制virsh start Ubuntu-Web
virsh list
手动操作适合单次迁移,但对于批量任务效率太低。我开发了一个Bash脚本来自动化整个过程,主要功能包括:
bash复制#!/bin/bash
# 检查root权限
if [[ $EUID -ne 0 ]]; then
echo "此脚本必须以root用户运行"
exit 1
fi
# 导出函数
function export_vms() {
read -p "请输入备份目录路径: " BACKUP_DIR
mkdir -p "$BACKUP_DIR"
# 获取所有虚拟机名称
VM_LIST=$(virsh list --name --all)
for VM in $VM_LIST; do
echo "正在备份虚拟机: $VM"
# 创建虚拟机专属目录
VM_DIR="$BACKUP_DIR/$VM"
mkdir -p "$VM_DIR"
# 导出XML配置
virsh dumpxml "$VM" > "$VM_DIR/config.xml"
# 获取磁盘路径并复制
DISK_PATH=$(virsh dumpxml "$VM" | grep -i "source file" | sed -n 's/.*file=.\(.*\)./\1/p')
if [[ -n "$DISK_PATH" ]]; then
echo "复制磁盘文件: $DISK_PATH"
cp "$DISK_PATH" "$VM_DIR/"
fi
done
echo "备份完成!所有文件保存在: $BACKUP_DIR"
}
# 导入函数
function import_vms() {
read -p "请输入备份目录路径: " BACKUP_DIR
if [[ ! -d "$BACKUP_DIR" ]]; then
echo "错误: 目录不存在"
exit 1
fi
# 处理每个子目录
for VM_DIR in "$BACKUP_DIR"/*; do
if [[ -d "$VM_DIR" ]]; then
VM_NAME=$(basename "$VM_DIR")
echo "正在恢复虚拟机: $VM_NAME"
# 复制磁盘文件
DISK_FILE=$(find "$VM_DIR" -name "*.qcow2" -o -name "*.img")
if [[ -n "$DISK_FILE" ]]; then
cp "$DISK_FILE" /var/lib/libvirt/images/
fi
# 定义虚拟机
virsh define "$VM_DIR/config.xml"
fi
done
echo "恢复完成!可以使用virsh list --all查看虚拟机"
}
导出所有虚拟机:
bash复制sudo ./kvm_migrate.sh export
导入虚拟机:
bash复制sudo ./kvm_migrate.sh import
权限问题:
磁盘路径不符:
网络配置差异:
bash复制rsync -avzP /var/lib/libvirt/images/ubuntu.qcow2 user@remote:/backup/
bash复制qemu-img convert -O qcow2 -c ubuntu.qcow2 ubuntu-compressed.qcow2
bash复制qemu-img create -f qcow2 -b ubuntu-base.qcow2 ubuntu-increment.qcow2
bash复制virt-sysprep -d Ubuntu-Web
bash复制gpg -c Ubuntu-Web.qcow2
scp Ubuntu-Web.qcow2.gpg user@remote:~/backup/
bash复制chmod 600 /backup/vm_images/*
当源和目标主机使用不同版本的libvirt时,可能需要调整XML格式。可以使用virt-xml工具进行转换:
bash复制virt-xml Ubuntu-Web.xml --update --output new_format.xml
将本地KVM虚拟机迁移到OpenStack等云平台:
bash复制qemu-img convert -f qcow2 -O raw Ubuntu-Web.qcow2 Ubuntu-Web.raw
bash复制openstack image create --disk-format raw --container-format bare --file Ubuntu-Web.raw Ubuntu-Web
使用virt-p2v工具将物理机转换为KVM虚拟机:
bash复制virt-p2v --server=192.168.1.100 --username=root --password=123456
在实际工作中,我发现定期备份虚拟机配置和磁盘是保证业务连续性的关键。特别是在进行系统升级或硬件更换时,一套可靠的迁移方案可以大大减少停机时间。