一、OpenStack之间跨集群迁移

1.1 迁移前准备与兼容性校验

1.1.1 环境信息全量采集

1.1.1.1 源集群 A 操作

  • 采集待迁移虚拟机全量信息,导出为清单文件
   # 1. 虚拟机基础信息
   openstack server show <INSTANCE_ID> -f json > vm_<INSTANCE_ID>_base.json
   # 2. 虚拟机规格(flavor)
   openstack flavor show <FLAVOR_ID> -f json > vm_<INSTANCE_ID>_flavor.json
   # 3. 数据盘信息(如果有挂载Cinder数据盘执行,无数据盘可跳过)
   openstack server volume list <INSTANCE_ID> -f json > vm_<INSTANCE_ID>_volumes.json
   # 4. 网络与端口信息
   openstack port list --server <INSTANCE_ID> -f json > vm_<INSTANCE_ID>_ports.json
   # 5. 安全组规则
   openstack security group show <SECURITY_GROUP_ID> -f json > vm_<INSTANCE_ID>_sg.json
  • 采集 Ceph 后端核心信息:
     # 查看存储池名称、RBD镜像名称与对应关系
     rbd ls vms | grep <INSTANCE_ID>  # 虚拟机系统盘(nova后端)
     rbd ls volumes | grep <VOLUME_ID>  # 数据盘(cinder后端)
     # 查看RBD镜像特性与格式兼容性
     rbd info <POOL>/<IMAGE_NAME>

1.1.1.2 目标集群 B 操作

  1. 确认 Ceph 存储池配置,创建与源端对应的 nova、cinder、glance 存储池,确保 PG 数、副本策略匹配业务需求
  2. 校验虚拟化层兼容性:
    • 确认目标集群 libvirt、QEMU 版本向下兼容源集群
    • 确认目标计算节点 CPU 指令集包含源端虚拟机使用的所有指令集,避免启动失败
      1. 提前创建与源端一致的租户、项目、用户、配额,确保权限匹配
      2. 【非 BFV 强制要求】提前创建和源端完全一致磁盘大小的 flavor(flavor 的disk字段必须等于源系统盘大小,否则 Nova 会自动扩容系统盘,可能导致分区表异常)

1.1.2 前置风险校验与处理

  1. 【非 BFV 核心】RBD 格式兼容性处理:
   # 源端禁用系统盘的不兼容特性,确保目标集群可正常识别
   rbd feature disable <NOVA_POOL_NAME>/instance-<INSTANCE_ID>_disk fast-diff,object-map,deep-flatten
   # 如果有数据盘,同步执行禁用操作
   rbd feature disable <CINDER_POOL>/volume-<VOLUME_ID> fast-diff,object-map,deep-flatten
  1. 虚拟机数据静默:关闭待迁移虚拟机,禁用开机自启,确保磁盘数据无写入,避免导出镜像数据不一致
   openstack server stop <INSTANCE_ID>
   # 【非BFV补充】确认虚拟机在计算节点无残留进程,避免RBD镜像被占用
   # 在源集群对应计算节点执行,确认无qemu-kvm进程占用该虚拟机
   ps aux | grep qemu| grep <OS-EXT-SRV-ATTR:instance_name>
   # 补充确认RBD镜像无锁
   rbd lock list <NOVA_POOL_NAME>/instance-<INSTANCE_ID>_disk
  1. 资源预留:目标集群预留足够的计算、存储、IP 资源,确保虚拟机重建无资源瓶颈

1.2 源集群 RBD 镜像离线导出

  1. 【非 BFV 核心】导出 Nova 管理的系统盘镜像
   # 导出系统盘为raw格式,确保数据完整
   rbd export -p <NOVA_POOL_NAME> instance-<INSTANCE_ID>_disk /data/export/vm_<INSTANCE_ID>_system.raw
  1. 数据盘导出(无数据盘可跳过,和 BFV 流程完全一致)
   rbd export -p <CINDER_POOL> volume-<VOLUME_ID> /data/export/vm_<INSTANCE_ID>_data_<VOLUME_ID>.raw
  1. 镜像压缩、格式转换与校验(大幅减少传输体积)
    # 转换为压缩qcow2格式,保留稀疏特性,减少70%+传输体积
    qemu-img convert -f raw -O qcow2 -c /data/export/vm_<INSTANCE_ID>_system.raw /data/export/vm_<INSTANCE_ID>_system.qcow2
    # 【关键校验】确认转换后的镜像文件系统正常,无损坏
    qemu-img check /data/export/vm_<INSTANCE_ID>_system.qcow2
    # 生成校验和,确保传输后数据完整性
    md5sum /data/export/vm_<INSTANCE_ID>_system.qcow2 > /data/export/vm_<INSTANCE_ID>_system.md5
    # 数据盘同步执行转换、校验、生成校验和
  2. 全量数据打包:将导出的镜像文件、元数据 JSON 文件、校验文件统一打包,通过离线介质传输至目标集群

1.3 目标集群镜像导入与资源重建

1.3.1 镜像完整性校验与导入

  1. 传输完成后,先校验镜像完整性
   md5sum -c vm_<INSTANCE_ID>_system.md5
   # 再次校验镜像文件系统正常
   qemu-img check vm_<INSTANCE_ID>_system.qcow2
  1. 【非 BFV 核心】将系统盘镜像导入 Glance 服务(跨版本无侵入重建的核心)

    核心逻辑:把源端导出的完整系统盘做成 Glance 镜像,后续创建虚拟机时直接用这个镜像启动,Nova 会自动把镜像内容写入到目标集群 Nova 池的新系统盘中,完美还原源系统所有数据,和你「选镜像 + 不创建新卷」的创建模式完全一致。

   openstack image create <name>  --file ./vm_<instance_id>.qcow2 --disk-format qcow2 --container-format bare --property usage_type=common --property hw_qemu_guest_agent=yes --property official_images=official_images --property os_type=linux --property os_distro=ubuntu

关键参数说明:添加hw_disk_bushw_vif_model属性,确保和源端虚拟机的磁盘 / 网卡驱动一致,避免启动失败

  1. 数据盘导入至 Cinder 池(无数据盘可跳过,和 BFV 流程完全一致)
   # 1. 创建与源端同规格的空白数据卷
   openstack volume create --size <VOLUME_SIZE> --project <TARGET_PROJECT_ID> vm_<INSTANCE_ID>_data_<VOLUME_ID>
   # 2. 导入数据至新卷
   rbd import /data/import/vm_<INSTANCE_ID>_data_<VOLUME_ID>.raw <CINDER_POOL>/volume-<NEW_VOLUME_ID>

1.3.2 目标集群基础资源重建

基于源端导出的元数据,在目标集群重建以下资源,确保与源端完全一致:

  1. 虚拟机规格(flavor):必须保证 flavor 的 disk 字段和源系统盘大小完全一致,vCPU、内存、CPU 架构、配额等完全匹配源端
  2. 网络资源:创建与源端一致的 VPC / 私有网络、子网、网关,预留固定 IP 地址
  3. 端口资源:重建虚拟机端口,绑定固定 IP、MAC 地址、安全组
  4. 安全组:完全复刻源端的入站 / 出站规则,避免业务网络不通
  5. 密钥对、浮动 IP 等配套资源,确保与源端配置一致

1.4 目标集群虚拟机重建与配置还原

1.4.1 虚拟机重建(完全匹配「选镜像 + 不创建新卷」的模式)

提供两种创建方式,和你源端的创建操作完全一致,重建后的虚拟机volumes_attached也会为空,和源端模式完全匹配。

方式 1:Horizon 界面创建(完全贴合你的操作习惯)

  1. 登录目标集群 Horizon 界面,进入对应项目→计算→实例→创建实例
  2. 「源」选项卡:
    • 选择源:镜像
    • 找到你导入的vm_<INSTANCE_ID>_system_image,点击「+」选中
    • 创建新卷:选择「否」(和你源端创建虚拟机的操作完全一致)
  3. 「口味」选项卡:选择你提前创建的、和源端完全一致的 flavor
  4. 「网络」选项卡:选择你重建的对应子网,或直接选择你提前创建的端口
  5. 「安全组」「密钥对」选项卡:选择和源端完全一致的配置
  6. 其余配置保持默认,点击「创建实例」即可

方式 2:CLI 命令行创建

openstack server create \
  --image vm_<INSTANCE_ID>_system_image \
  --flavor <TARGET_FLAVOR_ID> \
  --nic port-id=<TARGET_PORT_ID> \
  --security-group <TARGET_SECURITY_GROUP_ID> \
  --key-name <TARGET_KEYPAIR_NAME> \
  --availability-zone <TARGET_AZ> \
  --project <TARGET_PROJECT_ID> \
  --wait \
  <VM_NAME>

关键说明:这个命令创建的虚拟机,默认就是「镜像启动 + 不创建新卷」的模式,系统盘由 Nova 管理,volumes_attached为空,和源端虚拟机模式完全一致。

1.4.2 数据盘挂载与配置还原

1.4.2.1 基础方法

  1. 关闭新建的虚拟机,挂载导入的数据盘(无数据盘可跳过)
   openstack server stop <NEW_INSTANCE_ID>
   openstack server add volume <NEW_INSTANCE_ID> <NEW_VOLUME_ID>
  1. 启动虚拟机,进入系统内部验证:
    • 验证磁盘挂载点、fstab 配置与源端一致,无挂载失败
    • 验证网络配置(IP、网关、路由、防火墙规则)与源端一致
    • 验证业务服务自启正常,无依赖缺失

1.4.2.2 进阶高效方案:RBD 镜像直接导入法(适合超大系统盘场景)

如果你的系统盘超过 1TB,镜像转换和导入 Glance 耗时较长,可以用这个方案,但仅推荐对 OpenStack Nova 和 Ceph 非常熟悉的用户使用,跨版本场景有一定风险

核心逻辑

直接把源端导出的系统盘 raw 镜像,导入到目标集群的 Nova 池,命名为目标虚拟机的 instance 盘名,无需经过 Glance,效率更高。

精简操作步骤

  1. 阶段 1-2 和之前一致,导出系统盘为 raw 格式,无需转换 qcow2

  2. 目标集群先创建一个「空虚拟机」(用临时 cirros 镜像,flavor 和源端一致),获取新虚拟机的 INSTANCE_ID

   openstack server create --image cirros --flavor <TARGET_FLAVOR_ID> --nic net-id=<NET_ID> --wait temp_vm
   # 获取新虚拟机的INSTANCE_ID,记为NEW_INSTANCE_ID
  1. 关闭临时虚拟机,删除 Nova 池里的临时系统盘
   openstack server stop temp_vm
   rbd rm <NOVA_POOL>/instance-<NEW_INSTANCE_ID>_disk
  1. 直接导入源端系统盘 raw 镜像到目标 Nova 池,命名为新虚拟机的 instance 盘名
   rbd import /data/import/vm_<INSTANCE_ID>_system.raw <NOVA_POOL>/instance-<NEW_INSTANCE_ID>_disk
   # 禁用不兼容特性
   rbd feature disable <NOVA_POOL>/instance-<NEW_INSTANCE_ID>_disk fast-diff,object-map,deep-flatten
  1. 启动虚拟机,完成重建
   openstack server start temp_vm

风险提示:跨版本场景下,Nova 对 instance 盘的元数据、权限、属性要求可能有变化,可能导致 Nova 识别不了磁盘,虚拟机启动失败。生产环境优先推荐 Glance 镜像导入法,安全稳定

1.5 迁移验证与业务割接

1.5.1 全量验证清单
验证维度 验证内容
基础运行 虚拟机开机正常、无内核 panic、CPU / 内存 / 磁盘监控正常
存储完整性 系统盘 / 数据盘文件完整、md5 校验关键业务文件与源端一致
网络连通性 内网互通、外网访问正常、安全组规则生效、业务端口可访问
业务可用性 核心业务服务启动正常、数据库 / 中间件无数据丢失、业务流程可正常执行
兼容性 操作系统内核、驱动、软件包无兼容性报错,运行稳定
1.5.2 业务割接
  1. 验证无误后,将业务流量切换至目标集群虚拟机
  2. 源集群虚拟机保留 7 天以上,确认无异常后再执行删除操作

1.6 回滚方案

若迁移后出现无法解决的兼容性或业务问题,执行以下回滚操作:

  1. 关闭目标集群虚拟机,释放相关资源
  2. 源集群取消虚拟机禁用,重新开机启动
  3. 恢复源集群业务流量,确保业务快速恢复
  4. 排查迁移失败原因,修复后重新执行迁移

二、VMware虚拟机迁移到OpenStack

2.1 相关软件说明

2.1.1 VirtIO概述

从VMware超融合环境迁移到OpenStack时,为Windows、CentOS、Ubuntu虚拟机安装VirtIO驱动是必要且关键的步骤,核心原因在于底层虚拟化 架构的根本差异。

虚拟化技术架构差异:

平台 虚拟化技术 虚拟硬件标准 驱动要求
vSphere VMware专属虚拟化 VMware虚拟设备(SCSI控制器、vmxnet网卡) 依赖VMware Tools
OpenStack 通常为KVM/QEMU VirtIO半虚拟化标准 需要VirtIO驱动

根本问题:VMware虚拟机的操作系统内核只认VMware虚拟硬件,而OpenStack/KVM提供的是VirtIO虚拟设备,两者不兼容。没有正确驱动,虚拟机无法识别磁盘和网络设备,导致启动失败

2.1.2 Cloudinit概述

cloudinit是专为云环境中虚拟机的初始化而开发的工具,用于在创建虚拟机启动时从各种数据源读取相关数据并据此对虚拟机进行自定义配置。cloud-init的配置数据分为:metadata(主机名、密码、网络配置信息和SSH密钥)和user data(命令、脚本、文件和自定义数据等)。

2.1.3 QEMU Guest Agent概述

QEMU Guest Agent是运行在虚拟机内部的一个守护程序(qemu-guest-agent.service),用它来辅助Hypervisor实现对Guest的管理。QEMU为宿主机和虚拟机提供了一个数据通道(channel),这个通道的两端分别是在虚拟机内看到的串口和在宿主机上看到的unix socket文件。宿主机与虚拟机内的qga通讯就扩展了对虚拟机的控制能力,例如在宿主机上获取虚拟机的ip地址、修改虚拟机的密码等。

libvrit提供了专门的 virDomainQemuAgentCommand API(对应virsh qemu-agent-command命令)来和qemu-guest-agent通讯,另外有些libvirt内置api也可以支持qga,例如reboot、shutdown等。

2.2 关于下载vmdk文件

2.2.1 界面直接导出VMware虚拟机成镜像

关闭虚拟机,导出模板后作为VMDK类型的镜像上传到OpenStack后台

2.2.2 在中转机器使用virt-v2v命令导出系统盘成镜像

2.2.2.1 查看VMware ESXI宿主机上所有的虚拟机列表

开启ESXI宿主机ssh,在中转机上面执行:

# 输入密码后可以查看到所有虚拟机
virsh -c esx://root@宿主机IP?no_verify=1 list --all

2.2.2.2 创建用于存放文件的目录(可选)

# mkdir -p /data/esxi-vm
# cd /data/esxi-vm/

2.2.2.3 拷贝虚拟机到本地

拷贝完成后会在当前目录生成一个xml文件和disk1磁盘文件

# 命令 virt-v2v-copy-to-local -ic esx://root@宿主机IP?no_verify=1虚拟机名称
virt-v2v-copy-to-local -ic esx://root@10.10.233.11?no_verify=1 yum-[10.10.235.250]
# 会生成yum-[10.10.235.250]-disk1和yum-[10.10.235.250].xml文件

2.2.2.4 转换数据格式

virt-v2v -i libvirtxml yum-[10.10.235.250].xml.xml -o local -os /data/esxi-vm/ -of raw 
# 会生成yum-[10.10.235.250]-sda文件,文件格式是raw

2.3 转换raw

使用qemu-img 转换VMDK文件到RAW文件

# 将 vmdk 转换为 raw
qemu-img convert -f vmdk -O raw ./cailiao-07-1.vmdk cailiao-07.raw -p

2.4 CentOS操作系统迁移步骤

2.4.1 执行以下命令,确认当前内核是否支持 Virtio 驱动。

grep -i virtio /boot/config-$(uname -r)

返回类似如下结果:

根据输出信息中的参数CONFIG_VIRTIO_BLK(virtio的块设备驱动)和CONFIG_VIRTIO_NET(virtio的网络设备驱动)的取值判断:

  • 取值均为**y**:表示系统已正确安装virtio驱动,virtio驱动已编译进内核,开机会自动加载,无需继续执行本文内容。
  • 取值均为m或一个为y一个为m:表示virtio驱动以内核模块形式存在,只需将virtio驱动添加到临时文件系统]即可。
  • 没有这两个参数:表示系统未安装virtio驱动,需要手动安装virtio驱动。

2.4.2 检查virtio驱动是否已添加到临时文件系统

当内核启用了 CONFIG_VIRTIO_BLK=mCONFIG_VIRTIO_NET=m,但未将这些模块添加到临时文件系统(initramfs)时,系统启动时可能无法加载virtio驱动,导致虚拟机无法识别。

CONFIG_VIRTIO_BLKCONFIG_VIRTIO_NET参数的取值均为m或一个为y一个为m时,运行以下命令,判断virtio驱动是否已添加到临时文件系统。

# RHEL系列

lsinitrd /boot/initramfs-$(uname -r).img | grep virtio
  • 输出中包含 virtio_blk.kovirtio_net.ko信息,表示virtio驱动已经添加到临时文件系统中,无需继续执行本文内容。
  • 如果输出未包含virtio_blk.kovirtio_net.ko信息或仅包含virtio_blk.kovirtio_net.ko其中一个,则需要继续执行下一步将virtio驱动添加到临时文件系统。

2.4.3 将virtio驱动添加到临时文件系统

#CentOS 6/Anolis OS 7/AlmaLinux 8/Fedora 33及以上版本,且内核版本高于2.6.24(通过uname -r查询)时,执行如下操作将virtio驱动添加到临时文件系统。

# 安装qemu-guest-agent cloud-init

yum install -y qemu-guest-agent cloud-init
systemctl enable  qemu-guest-agent
systemctl enable   cloud-init

vim /etc/dracut.conf
add_drivers+="virtio_blk virtio_net"

# 备份

cp /boot/initramfs-$(uname -r).img /boot/initramfs-$(uname -r).img.bak
#执行以下命令,重新生成initrd
dracut -f /boot/initramfs-$(uname -r).img $(uname -r)

#再次检查
lsinitrd /boot/initramfs-$(uname -r).img | grep virtio

2.4.4 关闭虚拟机,导出CentOS虚拟机vmdk并上传到OpenStack后台

2.4.5 转换模板格式vmdk->raw

2.4.6 恢复虚拟机

# 根据原虚拟机配置选择上面生成的镜像来创建虚拟机实例;注意:项目、网络、安全组需要提前创建
# 关闭临时虚拟机,删除 Nova 池里的临时系统盘
openstack server stop temp_vm
rbd rm <NOVA_POOL>/instance-<NEW_INSTANCE_ID>_disk

# 直接导入源端系统盘 raw 镜像到目标 Nova 池,命名为新虚拟机的 instance 盘名
rbd import ./vm_<INSTANCE_ID>_system.raw  <NOVA_POOL>/instance-<NEW_INSTANCE_ID>_disk

# 禁用不兼容特性
 rbd feature disable <NOVA_POOL>/instance-<NEW_INSTANCE_ID>_disk fast-diff,object-map,deep-flatten

#启动虚拟机选择从0-rescue-xxx救援内核启动,重新生成initramfs
openstack server start temp_vm
dracut -f /boot/initramfs-$(uname -r).img $(uname -r)

#再次重启

2.5 Ubuntu操作系统迁移步骤

2.5.1 执行以下命令,确认当前内核是否支持 Virtio 驱动。

grep -i virtio /boot/config-$(uname -r)

返回类似如下结果:

根据输出信息中的参数CONFIG_VIRTIO_BLK(virtio的块设备驱动)和CONFIG_VIRTIO_NET(virtio的网络设备驱动)的取值判断:

  • 取值均为**y**:表示系统已正确安装virtio驱动,virtio驱动已编译进内核,开机会自动加载,无需继续执行本文内容。
  • 取值均为m或一个为y一个为m:表示virtio驱动以内核模块形式存在,只需将virtio驱动添加到临时文件系统]即可。
  • 没有这两个参数:表示系统未安装virtio驱动,需要手动安装virtio驱动。

2.5.2 检查virtio驱动是否已添加到临时文件系统

当内核启用了 CONFIG_VIRTIO_BLK=mCONFIG_VIRTIO_NET=m,但未将这些模块添加到临时文件系统(initramfs)时,系统启动时可能无法加载virtio驱动,导致虚拟机无法识别。

CONFIG_VIRTIO_BLKCONFIG_VIRTIO_NET参数的取值均为m或一个为y一个为m时,运行以下命令,判断virtio驱动是否已添加到临时文件系统。

# Debian系列
lsinitramfs /boot/initrd.img-$(uname -r) | grep virtio
  • 输出中包含 virtio_blk.kovirtio_net.ko信息,表示virtio驱动已经添加到临时文件系统中,无需继续执行本文内容。
  • 如果输出未包含virtio_blk.kovirtio_net.ko信息或仅包含virtio_blk.kovirtio_net.ko其中一个,则需要继续执行下一步将virtio驱动添加到临时文件系统。

2.5.3 将virtio驱动添加到临时文件系统

# Debain/Ubuntu系列
# 安装qemu-guest-agent cloud-init
apt install -y qemu-guest-agent cloud-init

# 备份
cp /boot/initrd.img-$(uname -r)   /boot/initrd.img-$(uname -r) .bak
#执行以下命令,重新生成initrd
echo -e 'xen-blkfront\nvirtio_blk\nvirtio_pci\nvirtio_console' >> /etc/initramfs-tools/modules
mkinitramfs -o /boot/initrd.img-$(uname -r) 

#再次检查
lsinitramfs /boot/initrd.img-$(uname -r) | grep virtio

2.5.4 关闭虚拟机,导出Ubuntu虚拟机vmdk并上传到OpenStack后台

2.5.5 转换模板格式vmdk->raw

2.5.6 恢复虚拟机

方法一:
# 根据原虚拟机配置选择上面生成的镜像来创建虚拟机实例;注意:项目、网络、安全组需要提前创建
# 关闭临时虚拟机,删除 Nova 池里的临时系统盘
openstack server stop temp_vm
rbd rm <NOVA_POOL>/instance-<NEW_INSTANCE_ID>_disk

# 直接导入源端系统盘 raw 镜像到目标 Nova 池,命名为新虚拟机的 instance 盘名
rbd import ./vm_<INSTANCE_ID>_system.raw  <NOVA_POOL>/instance-<NEW_INSTANCE_ID>_disk

# 禁用不兼容特性
 rbd feature disable <NOVA_POOL>/instance-<NEW_INSTANCE_ID>_disk fast-diff,object-map,deep-flatten

#启动虚拟机
openstack server start temp_vm

方法二:
# 在OpenStack集群上创建raw格式镜像,使用该镜像创建相同规格的虚拟机
        image_metadata="--property hw_qemu_guest_agent=yes --property official_images=official_images --property os_type=linux --property os_distro=ubuntu"

 openstack image create "<image_name>" \
        --file "<$image_file>" \
        --disk-format raw \
        --container-format bare \
        --property usage_type=common \
        $image_metadata

2.6 Windows操作系统迁移步骤

2.6.1 以下步骤是在VMware上的准备操作:

2.6.1.1 在VMware上给虚拟机打快照。

2.6.1.2 卸载VMware tools

vmware tools是针对于VMware平台深度定制的工具。 使用机操作系统控制面板的添加/删除程序项,

2.6.1.3 下载virtio驱动并安装

下载virtio驱动https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.229-1/virtio-win.iso。

双击virtio-win.iso挂载iso,然后进入挂载目录,双击运行virtio-win-guest-tools.exe,一直next并点击install。

2.6.1.4 安装qemu-guest-agent服务

在virtio iso挂载目录中,找到guest-agent目录,进入点击qemu-ga-x64.msi;鼠标右击开始按钮,进入计算机管理,在“服务和应用程序”的“服务”中检查qemu-guest-agent是否是自动开启。

2.6.1.5 安装cloud-init

稳定版本:推荐使用该版本安装包进行安装。
获取路径如下:

Windows 64位 操作系统:https://www.cloudbase.it/downloads/CloudbaseInitSetup_Stable_x64.msi

Windwos 32位 操作系统:https://www.cloudbase.it/downloads/CloudbaseInitSetup_Stable_x86.msi

安装过程中注意username,在安装完成的最后一步时,请勿勾选任何复选框,不运行 Sysprep。

2.6.2 关闭虚拟机,导出vmdk到OpenStack

2.6.3 转换模板格式vmdk->raw

2.6.4 上传镜像并创建虚拟机

# 将raw镜像上传至OpenStack平台,并创建虚拟机
# 注意暂时不支持hw_disk_bus=virtio
image_metadata="--property os_type=windows --property official_images=official_images --property hw_qemu_guest_agent=yes --property os_distro=windows --property hw_firmware_type=uefi --property hw_disk_bus=sata"

openstack image create "<image_name>" --file "<$image_file>" --disk-format raw --container-format bare --property usage_type=common $image_metadata

三、公有云(华为云为例)虚拟机迁移到OpenStack

3.1 相关软件说明

3.1.1 VirtIO概述

从华为云迁移到OpenStack时,为Windows、CentOS、Ubuntu虚拟机安装VirtIO驱动是必要且关键的步骤,核心原因在于底层虚拟化架构的根本差异,华为云底层也是使用的virtio驱动。

3.1.2 Cloudinit概述

cloudinit是专为云环境中虚拟机的初始化而开发的工具,用于在创建虚拟机启动时从各种数据源读取相关数据并据此对虚拟机进行自定义配置。cloud-init的配置数据分为:metadata(主机名、密码、网络配置信息和SSH密钥)和user data(命令、脚本、文件和自定义数据等)。

3.1.3 QEMU Guest Agent概述

QEMU Guest Agent是运行在虚拟机内部的一个守护程序(qemu-guest-agent.service),用它来辅助Hypervisor实现对Guest的管理。QEMU为宿主机和虚拟机提供了一个数据通道(channel),这个通道的两端分别是在虚拟机内看到的串口和在宿主机上看到的unix socket文件。宿主机与虚拟机内的qga通讯就扩展了对虚拟机的控制能力,例如在宿主机上获取虚拟机的ip地址、修改虚拟机的密码等。

libvrit提供了专门的 virDomainQemuAgentCommand API(对应virsh qemu-agent-command命令)来和qemu-guest-agent通讯,另外有些libvirt内置api也可以支持qga,例如reboot、shutdown等。

3.2 关于下载镜像文件

3.2.1 界面直接导出虚拟机成镜像

在镜像服务界面,点击“创建镜像”按钮,镜像类型分别选择系统镜像、数据盘镜像,选择镜像源后填写名称并点击下一步提交。

3.2.2 将虚拟机镜像导出到OBS存储中

可以选择导出成qcow2、vmdk格式的镜像文件。这里我们主要选择qcow2.

3.2.3 在OBS存储中点击下载

3.2.4 上传镜像到OpenStack后台

3.3 转换raw

使用qemu-img 转换QCOW2文件到RAW文件

# 将 vmdk 转换为 raw
qemu-img convert -f qcow2 -O raw  test1.qcow2 test1.raw -p

3.4 CentOS操作系统迁移步骤

3.4.1 执行以下命令,确认当前内核是否支持 Virtio 驱动。

grep -i virtio /boot/config-$(uname -r)

返回类似如下结果:

根据输出信息中的参数CONFIG_VIRTIO_BLK(virtio的块设备驱动)和CONFIG_VIRTIO_NET(virtio的网络设备驱动)的取值判断:

  • 取值均为**y**:表示系统已正确安装virtio驱动,virtio驱动已编译进内核,开机会自动加载,无需继续执行本文内容。
  • 取值均为m或一个为y一个为m:表示virtio驱动以内核模块形式存在,只需将virtio驱动添加到临时文件系统]即可。
  • 没有这两个参数:表示系统未安装virtio驱动,需要手动安装virtio驱动。

3.4.2 检查virtio驱动是否已添加到临时文件系统

当内核启用了 CONFIG_VIRTIO_BLK=mCONFIG_VIRTIO_NET=m,但未将这些模块添加到临时文件系统(initramfs)时,系统启动时可能无法加载virtio驱动,导致虚拟机无法识别。

CONFIG_VIRTIO_BLKCONFIG_VIRTIO_NET参数的取值均为m或一个为y一个为m时,运行以下命令,判断virtio驱动是否已添加到临时文件系统。

# RHEL系列

lsinitrd /boot/initramfs-$(uname -r).img | grep virtio
  • 输出中包含 virtio_blk.kovirtio_net.ko信息,表示virtio驱动已经添加到临时文件系统中,无需继续执行本文内容。
  • 如果输出未包含virtio_blk.kovirtio_net.ko信息或仅包含virtio_blk.kovirtio_net.ko其中一个,则需要继续执行下一步将virtio驱动添加到临时文件系统。

3.4.3 将virtio驱动添加到临时文件系统

#CentOS 6/Anolis OS 7/AlmaLinux 8/Fedora 33及以上版本,且内核版本高于2.6.24(通过uname -r查询)时,执行如下操作将virtio驱动添加到临时文件系统。
vim /etc/dracut.conf
add_drivers+="virtio_blk virtio_net"

# 备份
cp /boot/initramfs-$(uname -r).img /boot/initramfs-$(uname -r).img.bak
#执行以下命令,重新生成initrd
dracut -f /boot/initramfs-$(uname -r).img $(uname -r)

#再次检查
lsinitrd /boot/initramfs-$(uname -r).img | grep virtio

3.4.4 安装qemu-guest-agent和cloud-init

# 检查服务是否安装
systemctl status  qemu-guest-agent
systemctl status  cloud-init

# 安装qemu-guest-agent cloud-init
yum install -y qemu-guest-agent cloud-init
systemctl enable  qemu-guest-agent
systemctl enable   cloud-init

3.4.5 关闭虚拟机,创建CentOS虚拟机镜像,并导出qcow2格式并上传到OpenStack后台

3.4.6 转换格式qcow2->raw

3.4.7 恢复虚拟机

# 根据原虚拟机配置选择上面生成的镜像来创建虚拟机实例;注意:项目、网络、安全组需要提前创建
# 关闭临时虚拟机,删除 vms 池里的临时系统盘
openstack server stop temp_vm
rbd rm <NOVA_POOL>/instance-<NEW_INSTANCE_ID>_disk

# 直接导入源端系统盘 raw 镜像到目标 vms 池,命名为新虚拟机的 instance 盘名
rbd import ./vm_<INSTANCE_ID>_system.raw  <NOVA_POOL>/instance-<NEW_INSTANCE_ID>_disk

# 禁用不兼容特性
 rbd feature disable <NOVA_POOL>/instance-<NEW_INSTANCE_ID>_disk fast-diff,object-map,deep-flatten

3.5 Ubuntu操作系统迁移步骤

3.5.1 执行以下命令,确认当前内核是否支持 Virtio 驱动。

grep -i virtio /boot/config-$(uname -r)

返回类似如下结果:

根据输出信息中的参数CONFIG_VIRTIO_BLK(virtio的块设备驱动)和CONFIG_VIRTIO_NET(virtio的网络设备驱动)的取值判断:

  • 取值均为**y**:表示系统已正确安装virtio驱动,virtio驱动已编译进内核,开机会自动加载,无需继续执行本文内容。
  • 取值均为m或一个为y一个为m:表示virtio驱动以内核模块形式存在,只需将virtio驱动添加到临时文件系统]即可。
  • 没有这两个参数:表示系统未安装virtio驱动,需要手动安装virtio驱动。

3.5.2 检查virtio驱动是否已添加到临时文件系统

当内核启用了 CONFIG_VIRTIO_BLK=mCONFIG_VIRTIO_NET=m,但未将这些模块添加到临时文件系统(initramfs)时,系统启动时可能无法加载virtio驱动,导致虚拟机无法识别。

CONFIG_VIRTIO_BLKCONFIG_VIRTIO_NET参数的取值均为m或一个为y一个为m时,运行以下命令,判断virtio驱动是否已添加到临时文件系统。

# Debian系列
lsinitramfs /boot/initrd.img-$(uname -r) | grep virtio
  • 输出中包含 virtio_blk.kovirtio_net.ko信息,表示virtio驱动已经添加到临时文件系统中,无需继续执行本文内容。
  • 如果输出未包含virtio_blk.kovirtio_net.ko信息或仅包含virtio_blk.kovirtio_net.ko其中一个,则需要继续执行下一步将virtio驱动添加到临时文件系统。

3.5.3 将virtio驱动添加到临时文件系统

# Debain/Ubuntu系列
# 备份
cp /boot/initrd.img-$(uname -r)   /boot/initrd.img-$(uname -r) .bak
#执行以下命令,重新生成initrd
echo -e 'xen-blkfront\nvirtio_blk\nvirtio_pci\nvirtio_console' >> /etc/initramfs-tools/modules
mkinitramfs -o /boot/initrd.img-$(uname -r) 

#再次检查
lsinitramfs /boot/initrd.img-$(uname -r) | grep virtio

3.5.4 安装qemu-guest-agent和cloud-init

# 检查服务是否安装
systemctl status  qemu-guest-agent
systemctl status  cloud-init

# 安装qemu-guest-agent cloud-init
apt install -y qemu-guest-agent cloud-init
systemctl enable  qemu-guest-agent
systemctl enable  cloud-init

3.5.5 关闭虚拟机,创建Ubuntu虚拟机镜像,并导出qcow2格式并上传到OpenStack后台

3.5.6 转换格式qcow2->raw

3.5.7 恢复虚拟机

方法一:
# 根据原虚拟机配置选择上面生成的镜像来创建虚拟机实例;注意:项目、网络、安全组需要提前创建
# 关闭临时虚拟机,删除 vms 池里的临时系统盘
openstack server stop temp_vm
rbd rm <NOVA_POOL>/instance-<NEW_INSTANCE_ID>_disk

# 直接导入源端系统盘 raw 镜像到目标 vms 池,命名为新虚拟机的 instance 盘名
rbd import ./vm_<INSTANCE_ID>_system.raw  <NOVA_POOL>/instance-<NEW_INSTANCE_ID>_disk

# 禁用不兼容特性
 rbd feature disable <NOVA_POOL>/instance-<NEW_INSTANCE_ID>_disk fast-diff,object-map,deep-flatten

#启动虚拟机
openstack server start temp_vm

方法二:
# 在OpenStack集群上创建raw格式镜像,使用该镜像创建相同规格的虚拟机
        image_metadata="--property hw_qemu_guest_agent=yes --property official_images=official_images --property os_type=linux --property os_distro=ubuntu"

 openstack image create "<image_name>" \
        --file "<$image_file>" \
        --disk-format raw \
        --container-format bare \
        --property usage_type=common \
        $image_metadata

3.6 Windows操作系统迁移步骤

3.6.1 在公有云给虚拟机打快照。

3.6.2 下载virtio驱动并安装

检查virtio是否安装:打开设备管理器,检查网络适配器、存储控制器、磁盘驱动器、系统设置中是否有virtio驱动。

下载virtio驱动https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/

双击virtio-win.iso挂载iso,然后进入挂载目录,双击运行virtio-win-guest-tools.exe,一直next并点击install。

3.6.3 安装qemu-guest-agent服务

检查qemu-guest-agent服务是否安装:打开计算机管理器,进入服务和应用程序,进入服务,查看是否有qemu guest agent服务,并检查是否自动开启。

在virtio iso挂载目录中,找到guest-agent目录,进入点击qemu-ga-x64.msi;鼠标右击开始按钮,进入计算机管理,在“服务和应用程序”的“服务”中检查qemu-guest-agent是否是自动开启。

3.6.4 安装cloud-init服务

检查cloud-init服务是否安装:打开计算机管理器,进入服务和应用程序,进入服务,查看是否有cloud init服务,并检查是否自动开启。

稳定版本:推荐使用该版本安装包进行安装。
获取路径如下:

Windows 64位 操作系统:https://www.cloudbase.it/downloads/CloudbaseInitSetup_Stable_x64.msi

Windwos 32位 操作系统:https://www.cloudbase.it/downloads/CloudbaseInitSetup_Stable_x86.msi

安装过程中注意username,在安装完成的最后一步时,请勿勾选任何复选框,不运行 Sysprep。

3.6.5 关闭虚拟机,创建镜像,导出qcow2格式并上传到OpenStack后台

注意:部分使用第三方提供的镜像创建的虚拟机无法导出,这部分虚拟机无法迁移

3.6.6 转换格式qcow2->raw

3.6.7 上传镜像并创建虚拟机

# 方法一:
# 根据原虚拟机配置选择上面生成的镜像来创建虚拟机实例;注意:项目、网络、安全组需要提前创建
# 关闭临时虚拟机,删除 vms 池里的临时系统盘
openstack server stop temp_vm
rbd rm <NOVA_POOL>/instance-<NEW_INSTANCE_ID>_disk

# 直接导入源端系统盘 raw 镜像到目标vms池,命名为新虚拟机的 instance 盘名
rbd import ./vm_<INSTANCE_ID>_system.raw  <NOVA_POOL>/instance-<NEW_INSTANCE_ID>_disk

# 禁用不兼容特性
 rbd feature disable <NOVA_POOL>/instance-<NEW_INSTANCE_ID>_disk fast-diff,object-map,deep-flatten

#启动虚拟机
openstack server start temp_vm


# 方法二:
# 在OpenStack集群上创建raw格式镜像,使用该镜像创建相同规格的虚拟机
# 注意观察虚拟机的启动方式是uefi还是bios,如果uefi需要加上--property hw_firmware_type=uefi参数
image_metadata="--property os_type=windows --property official_images=official_images --property hw_qemu_guest_agent=yes --property os_distro=windows"

openstack image create "<image_name>" --file "<$image_file>" --disk-format raw --container-format bare --property usage_type=common $image_metadata
作者:束鹏  创建时间:2026-03-27 10:26
最后编辑:束鹏  更新时间:2026-04-02 16:23