OpenStack虚拟机快照和增量备份实现方法

bangongJIAO1@c 发布于 2025-12-26 阅读(3)
目录
  • 1 快照的概念
  • 2 主流libvirt快照实现介绍
    • 2.1 libvirt的内部快照操作
    • 2.2 libvirt的外部快照操作
  • 3 OpenStack原生虚拟机快照和备份
    • 4 使用ceph实现OpenStack虚拟机快照功能
      • 5 使用ceph实现OpenStack虚拟机增量备份功能
        • 5.1 创建备份
        • 5.2 恢复备份

      1 快照的概念

      一般对快照的理解就是能够将系统还原到某个瞬间,这就是快照的作用。
      快照针对要保存的数据分为内存快照和磁盘快照,内存快照就是保存当前内存的数据,磁盘快照就是保存硬盘的数据。
      快照针对保存方式又分为内部快照和外部快照。
      内部快照:是指快照信息和虚拟机存在同一个qcow2镜像中,使用单个的 qcow2 的文件来保存快照和快照之后的改动。这种快照是 libvirt 的默认行为,现在的支持很完善(创建、回滚和删除),但是只能针对 qcow2 格式的磁盘镜像文件,而且其过程较慢等。
      外部快照:是指做快照时原虚拟机的disk将变为readonly的模板镜像,然后会新建一个qcow2文件来记录与原模板镜像的差异数据,外部快照的结果是形成一个qcow2文件链:original <- snap1 <- snap2 <- snap3

      2 主流libvirt快照实现介绍

      2.1 libvirt的内部快照操作

      以下是利用libvirt的virsh工具来创建一些内置快照:
      创建虚拟机快照:

      virsh snapshot-create-as --name test001 --description 'abc' instance-00000001

      列出虚拟机的快照:

      virsh snapshot-list instance-00000001

      查看某个快照信息:

      virsh snapshot-dumpxml instance-00000001 test001

      回滚到某个快照:

      virsh snapshot-revert instance-00000001 test001

      删除某个快照:

      virsh snapshot-delete instance-00000001 test001

      其实这些其实现的本质是在镜像内做一些标记,内存状态数据则保存到某一个磁盘镜像文件内,使用以下命令可以看到在该镜像做的标记:

      qemu-img info /var/lib/nova/instances/87985777-f83d-4fff-9723-025c2b889895/disk

      2.2 libvirt的外部快照操作

      可以使用 “--memspec” 和 “--diskspec” 参数来给内存和磁盘外部快照。这时候,在获取内存状态之前需要 Pause 虚机,就会产生服务的 downtime。
      比如:virsh snapshot-create-as instance-00000001 livesnap2 --memspec /home/livesnap2mem,snapshot=external --diskspec vda,snapshot=external
      virsh snapshot-dumpxml instance-00000001 livesnap2可以看到具体外置存放位置信息
      但是libvirt现在还不支持回滚和删除外置快照,如下
      virsh snapshot-revert instance-00000001 livesnap2
      error: unsupported configuration: revert to external snapshot not supported yet

      3 OpenStack原生虚拟机快照和备份

      OpenStack中对虚拟机的快照其实是生成一个完整的镜像,保存在glance服务中,并且可以利用这个快照镜像生成新的虚拟机,与原本的虚拟机并没有什么关系。而比较主流的快照实现应该是有快照链的,且包含内存快照和磁盘快照。
      OpenStack中的备份其实跟快照没啥区别,调用的都是同一个生成镜像的接口,更多的备份是cinder对磁盘的备份,没有对整个虚拟机进行备份的接口。

      4 使用ceph实现OpenStack虚拟机快照功能

      (1)首先是配置OpenStack的存储环境是Ceph存储,因为我们要借助ceph的一些特性来实现快照


      (2)从上面我们可以知道做快照,主要是对磁盘做快照和对内存数据进行保存,如果是ceph环境,那么OpenStack虚拟机的根磁盘和磁盘在ceph下就是一个块设备,比如根磁盘一般就是保存在vms池中,其路径是vms/<instance_id>_disk,而磁盘一般就是保存在volumes池中,其路径是volumes/volume-<volume_id>;对于块设备,ceph可以使用rbd命令来对块设备做快照,比如我们对虚拟机根磁盘做快照:

      rbd snap create vms/<instance_id>_disk@<snapshot_name>

      snapshot_name是快照名
      回滚时则执行:

      rbd snap rollback vms/<instance_id>_disk@<snapshot_name>

      这其实可以理解为是块设备的内部快照方式

      (3)对于内存数据,我们可以使用libvirt的save接口将内存状态数据保存到一个文件中,为了保存到块设备中,我们可以这样做:
      <1>新建一个块设备(这里假设在snapshots池中创建1G大小的名为test的块设备):

      rbd create --size 1024 snapshos/test

      <2>将块设备map到物理主机中

      rbd map snapshos/test
      /dev/rbd0

      可以看到会输出一个磁盘设备符,使用lsblk命令则能看到该设备

      <3>格式化该设备并挂载到某个目录下

      mkfs.xfs /dev/rbd0
      mkdir test_dir
      mount /dev/rbd0 test_dir

      然后我们就可以向save接口传入test_dir目录下的一个文件名,其会将内存状态数据保存到该文件中,接着umount掉该块设备:

      umount -f /dev/rbd0
      rbd unmap /dev/rbd0

      这样内存数据也一样保存到块设备中了,要使用时再挂载该块设备访问即可,回滚内存对应的是向libvirt的restore接口传入该内存数据文件

      注意点:
      (1)libvirt的save接口调用保存完内存状态数据后,虚拟机会关闭,这时可以执行restore接口虚拟机回滚回去
      (2)回滚虚拟机时,先将该虚拟机的vm_state状态置为ACTIVE,否则回滚会不成功

      5 使用ceph实现OpenStack虚拟机增量备份功能

      这里说两个备份名词,全量备份和增量备份。
      全量备份:保存的是整个虚拟机的完整的数据
      增量备份:保存的只是跟上一次相比有改动的数据
      需要先做一次全量备份后,后续才能做增量备份

      5.1 创建备份

      这里以虚拟机的根磁盘 vms/<instance_id>_disk为例子做增量备份的操作演示:
      (1)做一次全量备份
      先对该块设备做一次快照:

      rbd snap create vms/<instance_id>_disk@time1
      

      然后导出差异数据:

      rbd export-diff vms/<instance_id>_disk@time1 time1_diff_file
      

      (2)再做一次增量备份
      先对该块设备做一次快照:

      rbd snap create vms/<instance_id>_disk@time2 

      导出time1到time2之间这段时间该磁盘的差异数据:

      rbd export-diff vms/<instance_id>_disk@time2 --from-snap vms/<instance_id>_disk@time1 time2_diff_file

      5.2 恢复备份

      (1)如果该磁盘还存在,则直接用rbd snap rollback回滚就可以了,比如要回滚到time1这个时间点:

      rbd snap rollback vms/<instance_id>_disk@time1 
      

      (2)该磁盘已经被删掉了,要恢复该磁盘到time2的时间点:
      <1>创建一个块设备(大小跟删除的那块一样大小,这里以1G为例子)

      rbd create --size 1024 vms/restore_disk

      <2>导入差异数据,注意这里的导入顺序,先恢复到time1,再恢复到time2

      rbd import-diff time1_diff_file vms/restore_disk
      rbd import-diff time2_diff_file vms/restore_disk

      这时这块块设备就恢复回time2的状态了

      友情经验点:
      (1)上面的操作都是自己创建一个块设备然后进行回滚,那怎么把这块给到OpenStack的虚拟机使用呢?在OpenStack中添加一个磁盘是先调用api.cinder.volume_create接口创建一个卷,然后调用api.nova.instance_volume_attach将该卷连接到虚拟机中,其实我们只要将它创建的块设备替换成我们的就可以了,比如它生成的是volumes/volume-123,我们自己回滚好的是volumes/restore_disk,则先删掉它的块设备,然后重命名我们的块设备:

      rbd rm volumes/volume-123
      rbd rename volumes/restore_disk volumes/volume-123

      (2)同理,如果我们要从备份文件中恢复到一个新的虚拟机,那么就先创建一个虚拟机,然后将它的根磁盘替换为我们恢复过数据的根磁盘,然后接着是替换硬盘,这样我们便从备份文件中恢复到一个新的虚拟机了