随着openstack的广泛被采用,很多公司开始部署和运行openstack。 为提高效率,降低管理和维护成本,很多公司也需要将旧的虚拟化平台(如:VMware vSphere、Xenserver、cloudstack)上的业务迁移到openstack平台上。本文详细介绍一个从Xenserver平台将虚拟机迁移到openstack平台的方案。

将虚拟机从xenserver迁移到openstack平台(openstack平台上采用的最广泛的虚拟化技术是kvm,存储方案是ceph,所以本文中的openstack平台是基于kvm+ceph的方案)简单的来说就是将虚拟机的系统盘和数据盘导出,然后拷贝并导入到openstack平台,最后用导入的数据创建新的虚拟机。这个过程看似简单,但是,因为底层的虚拟化方案和存放方案都会发生变化,为了保证迁移之后,运行在虚拟机里面的业务不受影响,还是有很多细节需要注意,详见下面的介绍。

迁移过程简介

将虚拟机从xenserver迁移到openstack(kvm+ceph)平台的过程大致如下:

  • 调整虚拟机的系统配置,为迁移做准备;
    • 磁盘设备的路径会发生变化,挂载配置中不能写设备路径;最好能改成通过UUID进行挂载
    • 网卡设备的名称也可能发生变化,如果是linux系统,可以考虑修改udev规则来固定网卡设备的名称
  • 在xenserver上挂起虚拟机,然后导出虚拟机的系统盘和数据盘;
  • 将系统盘和数据盘拷贝到openstack平台,为了减少拷贝可以考虑使用NFS减少拷贝次数;
  • 对系统盘和数据盘进行适当的调整
    • 安装驱动(例如:windows虚拟机可能需要安装virtio驱动)
    • 修改网络配置(MAC地址可能发生变化,不能将MAC写到配置文件中)
  • 将修改后的系统盘和数据盘导入到openstack平台
    • 如果使用ceph作为存储方案,可以通过rbd import导入;
    • 将系统盘做成镜像,将数据盘做成volume;
  • 用导入的系统盘和数据盘创建虚拟机
  • 进入虚拟机,验证各项业务是否正常

迁移过程

上面简单的介绍了迁移的过程,下面通过一个具体的例子,详细的说明迁移的每个步骤如何实施。

准备工作

修改Linux虚拟机的磁盘挂载配置

虚拟机迁移到openstack平台之后,看到的磁盘路径会发生变化,在xenserver上,磁盘的路径是 /dev/xvda 这样的格式,迁移到openstack平台之后,路径会变为 /dev/vda,所以,在迁移之前,如果磁盘挂载配置文件里面写的是路径,需要将其改为UUID。具体见下面的例子。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# cat /etc/fstab
/dev/mapper/rhel-root                     /                       xfs     defaults        0 0
UUID=1af875f4-2986-4038-8328-38b5620780e3 /boot                   xfs     defaults        0 0
/dev/mapper/rhel-swap                     swap                    swap    defaults        0 0
/dev/xvdb2                                /data                   ext4    defaults        0 0

# 上面这个例子就是设置为磁盘路径,需要修改为UUID,和 boot分区一样
# 找到数据盘的UUID
# ls -l /dev/disk/by-uuid | grep xvdb2
lrwxrwxrwx. 1 root root 11 Sep 24 18:03 95ed42d0-17e4-43e1-96cf-0054e81e26f8 -> ../../xvdb2

# 命令输出的倒数第三个字段 95ed42d0-17e4-43e1-96cf-0054e81e26f8 就是磁盘的UUID,然后修改 /etc/fstab,将其改为如下的内容
/dev/mapper/rhel-root                     /                       xfs     defaults        0 0
UUID=1af875f4-2986-4038-8328-38b5620780e3 /boot                   xfs     defaults        0 0
/dev/mapper/rhel-swap                     swap                    swap    defaults        0 0
UUID=95ed42d0-17e4-43e1-96cf-0054e81e26f8 /data                   ext4    defaults        0 0

修改之后,磁盘路径发生了变化,也不影响磁盘的挂载和使用。

在openstack控制节点上安装nfs服务

为了减少数据传输,可以在openstack控制节点上安装nfs-server,将某个目录直接共享给xenserver,xenserver导出时直接导出到共享目录,这样就不需要将导出的文件再拷贝一份到openstack的控制节点上了。安装和配置nfs-server的命令如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#安装
yum -y install nfs-utils

# 配置
echo > /etc/exports <<EOF
/nfs/cloudstack *(rw,sync,no_root_squash)
EOF
mkdir -p /nfs/cloudstack
chown nfsnobody:nfsnobody -R /nfs/cloudstack/

#启动服务
systemctl enable nfs-server.service
systemctl start nfs-server.service

# 测试
showmount -e localhost

在xenserver上挂载nfs共享目录

1
2
3
4
5
6
# 查看openstack控制节点的NFS共享目录
showmount -e <openstack控制节点IP>

# 挂载NFS共享目录
mkdir -p /exports
mount -t nfs -o rw <openstack控制节点IP>:/nfs/cloudstack /exports/

迁移步骤

在xenserver上导出虚拟机的所有磁盘

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# 切换目录
cd /exports/
# 列出虚拟机的所有磁盘
VM_NAME=i-2-334-VM
mkdir ${VM_NAME}
cd ${VM_NAME}
xe vm-suspend vm=${VM_NAME}
for disk in $(xe vbd-list vm-name-label=${VM_NAME} | grep ^uuid | awk '{print $NF}')
do
    vdi_uuid=$(xe vbd-param-get param-name=vdi-uuid uuid=${disk})
    if [ "<not in database>" = "${vdi_uuid}" ]; then
        continue
    fi
    device_name=$(xe vbd-param-get param-name=device uuid=${disk})
    filename="${device_name}-${vdi_uuid}.vhd"
    xe vdi-export uuid=${vdi_uuid} filename=${filename} format=vhd --progress
done
xe vm-resume vm=${VM_NAME}

通过virt-v2v做格式转换,并上传到openstack平台

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 系统盘
# 1,格式转换
virt-v2v -i disk xvda-{UUID}.vhd -o local -of raw -os /nfs/cloudstack/

# 2,传递到ceph
rbd -p {pool-name} import --image-format 2 xvda-{UUID}.raw
rbd -p {pool-name} snap create xvda-{UUID}@snap
rbd -p {pool-name} snap protect xvda-{UUID}@snap

# 3,做成glance镜像
glance --os-image-api-version 1 image-create --id {UUID} --store rbd --disk-format raw --container-format  bare --location rbd://$(ceph fsid)/{pool-name}/xvda-{UUID}/snap

# 4, 如果虚拟机不支持virtio驱动(主要是window虚拟机和比较老版本的Linux虚拟机)
glance image-update --property hw_disk_bus=ide --property hw_qemu_guest_agent=no  --property hw_vif_model=e1000 {UUID}
  
# 数据盘
for disk in $(ls *.vhd | grep -v xvda)
do
   # 将VHD格式的镜像转换为raw之后,上传到ceph里面
   qemu-img convert -O raw ${disk} ${disk/.vhd/.raw}
   rbd -p {pool-name} --image-format 2 ${disk/.vhd/} ${disk/.vhd/.raw}

  
   # 从ceph镜像创建cinder volume
   cinder manage cinder@sata-ceph#sata ${disk/.vhd/}
done

在openstack平台上创建虚拟机

1
2
3
4
5
6
# 通过neutron创建port,在创建port的时候指定IP地址

# 通过nova创建虚拟机
nova boot --flavor 1C2G --nic port-id=xxxxxxx --image {UUID} \
          --block-device id={volume id},source=volume,dest=volume,bootindex=1 \  # 数据盘
          vm-xxx

验证工作

进入虚拟机验证各项功能是否正常

1
2
3
4
5
6
7
8
# 获取web vnc链接地址
nova get-vnc-console {虚拟机uuid} novnc

+-------+------------------------------------------------------------------------------+
| Type  | Url                                                                          |
+-------+------------------------------------------------------------------------------+
| novnc | http://xxx.com:6080/vnc_auto.html?token=49ce0ca2-cf14-491c-8488-e5218a8c0f1a |
+-------+------------------------------------------------------------------------------+

通过浏览器打开上面的链接地址,可以验证虚拟机的各项功能是否支持。

参考文档