KVM虚拟机的快照(snapshot)功能可以保存虚拟机运行时的内存状态,恢复快照后虚拟机即可恢复到创建快照时的运行时状态,所有的软件运行状态依旧,类似于游戏中的SL(save/load)大法。我们可以使用快照功能实现很多业务,例如快速恢复沙箱的运行状态,而不用清理环境或是重启虚拟机等待服务一一启动。
但是KVM虚拟机的快照功能却不是很好利用,当需要大规模使用快照时就会发现似乎快照没那么好复制,复制出来的快照往往启动后也会失效,无法恢复,让批量化部署变得很困难。本文介绍了复制KVM虚拟机快照方法,用较低的成本将一个虚拟机的快照复制出来,方便批量部署。
快照命令 快照功能实际上是qemu的功能,这个功能保存了虚拟机的运行时状态,要使用这个功能,要求虚拟机的镜像为qcow2格式,raw格式等格式不支持这个功能。
libvirt作为我们常用的虚拟机管理工具,提供了快捷的方式来创建及恢复快照,这些命令如下:
1 2 3 4 5 6 7 8 9 10 11 # 为kvm01虚拟机创建快照 virsh snapshot-create kvm01 # 列出kvm01虚拟机的快照 virsh snapshot-list kvm01 # 恢复kvm01虚拟机到最近的快照 virsh snapshot-revert kvm01 --current # 恢复kvm01虚拟机到指定的快照 virsh snapshort-revert kvm01 --snapshotname 1515143552
如果有虚拟机的话,可以尝试一把上面的命令,感受下虚拟机快照的效果。
openstack上的快照功能没有保存内存运行时的状态,仅仅保存了磁盘的状态,因此在恢复快照后虚拟机还是会重启,无法恢复到运行时的状态。
快照存储在哪儿? 快照的信息实际上是存到了镜像文件本身的,我们可以使用“qemu-img info”命令来获取到镜像的信息,我们对一个做了快照的镜像执行该命令,此时就可以看到快照的信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 [root@knktc snapshot]# qemu-img info source.img image: source.img file format: qcow2 virtual size: 20G (21474836480 bytes) disk size: 3.1G cluster_size: 65536 backing file: /opt/snapshot/base.img Snapshot list: ID TAG VM SIZE DATE VM CLOCK 1 1519990436 2.6G 2018-03-02 19:33:56 00:08:27.846 Format specific information: compat: 1.1 lazy refcounts: false
在上面的镜像信息中,“Snapshot list”的部分就标示出了当前这个镜像有一个快照。
看来,我们要复制快照,就只能把做了快照的镜像也给复制一份了。一般虚拟机的镜像都有几G到几十G之大,复制起来比较浪费空间,但qcow2格式的镜像支持backing file功能,即使用一个基础镜像来创建一个镜像,创建出来的镜像仅保存增量信息,这样就大幅度地降低了要复制的文件的体积了。
于是我们就有了这么一个思路:
创建基础虚拟机镜像;
使用这个基础镜像创建新的虚拟机,并制作快照;
复制这个新的虚拟机镜像,达到复制快照的效果。
下面就开始试试这个思路吧。
创建基础虚拟机镜像 这个步骤可以略过,找一个现有的虚拟机,或是重新创建一个虚拟机都可以。
我们假设我们现在已经有了一个虚拟机镜像,名称为“base.img”。
创建新的虚拟机和快照 我们使用基础的虚拟机镜像再创建一个虚拟机镜像,名为“source.img”,命令如下:
1 qemu-img create -b base.img -f qcow2 source.img
我们把这个虚拟机镜像启动起来(比如使用libvirt创建一个叫source的虚拟机),运行到一个状态,随后创建快照:
1 2 3 4 5 # 为source创建一个快照 virsh snapshot-create --domain source # 命令执行后将会反馈下面的内容 Domain snapshot 1519990436 created
此时快照已经创建好,名称为1519990436(使用时间戳来表示快照的名称)。
为了防止镜像体积持续变大,我们现在把虚拟机给强制关机:
为了确认镜像中已包含快照信息,可以使用以下的命令确认下:
1 qemu-img info source.img
或是直接使用snapshot-list命令来获取虚拟机source的快照信息:
1 2 3 4 [root@knktc ~]# virsh snapshot-list source Name Creation Time State ------------------------------------------------------------ 1519990436 2018-03-02 19:33:56 +0800 running
导出快照配置文件 使用”snapshot-dumpxml”命令可以将刚才的快照配置文件导出为一个xml文件,我们将这个导出的xml文件命名为snapshot.xml:
1 virsh snapshot-dumpxml --domain source --snapshotname 1519990436 > snapshot.xml
打开我们导出的快照配置文件,我们可以看到以下的内容:
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 <domainsnapshot> <name>1519990436</name> <state>running</state> <creationTime>1519990436</creationTime> <memory snapshot='internal'/> <disks> <disk name='vda' snapshot='internal'/> </disks> <domain type='kvm'> <name>source</name> <uuid>12d3271a-c683-44b2-8244-dd4b53818035</uuid> <memory unit='KiB'>4194304</memory> <currentMemory unit='KiB'>4194304</currentMemory> <vcpu placement='static'>2</vcpu> <resource> <partition>/machine</partition> </resource> <os> <type arch='x86_64' machine='rhel6.6.0'>hvm</type> <boot dev='hd'/> </os> <features> <acpi/> <apic/> <pae/> </features> <clock offset='utc'/> <on_poweroff>destroy</on_poweroff> <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> <devices> <emulator>/usr/libexec/qemu-kvm</emulator> <disk type='file' device='disk'> <driver name='qemu' type='qcow2' cache='writeback'/> <source file='/opt/snapshot/source.img'/> <target dev='vda' bus='virtio'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> </disk> <controller type='usb' index='0' model='piix3-uhci'> <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> </controller> <controller type='pci' index='0' model='pci-root'/> <interface type='network'> <mac address='52:54:00:15:ec:5b'/> <source network='default'/> <model type='virtio'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> </interface> <input type='tablet' bus='usb'> <address type='usb' bus='0' port='1'/> </input> <input type='mouse' bus='ps2'/> <input type='keyboard' bus='ps2'/> <graphics type='vnc' port='19000' autoport='no' listen='0.0.0.0'> <listen type='address' address='0.0.0.0'/> </graphics> <video> <model type='cirrus' vram='16384' heads='1' primary='yes'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> </video> <memballoon model='virtio'> <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> </memballoon> </devices> </domain> <cookie> </cookie> </domainsnapshot>
看着有点眼熟啊对不对?似乎就是在虚拟机的配置文件上面加了点东西嘛。
可以看到,这个配置文件中包含了快照的信息(名称、运行状态)和虚拟机的配置信息(几乎就是虚拟机的配置xml)。有了这个信息,我们可以考虑修 改这个配置文件,应用于我们复制出来的镜像中。
复制快照 要复制快照,我们先要复制镜像,将刚才的source.img复制为我们新的虚拟机需要使用的镜像(我们把它复制为test01.img文件):
1 cp source.img test01.img
随后我们再创建一个虚拟机test01,使用刚才复制出来的test01.img镜像文件。在define虚拟机后,我们获取下新创建的虚拟机的uuid和mac地址信息。这两个信息一般情况下我们是让libvirt随机创建的,因此需要提前获取到,使用以下命令即可查看新创建的虚拟机的配置:
然后,我们拿这个test01虚拟机的信息来修改刚才导出的快照配置文件snaphost.xml,我们需要修改的部分如下:
uuid
虚拟机名称
镜像的路径
mac地址
vnc端口
注意!注意!注意!如果以上的几个信息填写得和test01虚拟机的信息不符,将无法使用快照功能!
修改完成后,我们将这个修改完成的快照配置文件为test01虚拟机导入:
1 2 3 4 5 # 执行以下命令,让test01虚拟机也能感知到自己体内有个快照 virsh snapshot-create test01 snapshot.xml --redefine # 执行命令后将会返回以下的信息 Domain snapshot 1519990436 created from 'snapshot.xml'
导入完成!
测试快照 我们可以直接使用snapshot-list命令来列出test01虚拟机的快照信息,可以看到:
1 2 3 4 [root@knktc ~]# virsh snapshot-list test01 Name Creation Time State ------------------------------------------------------------ 1519990436 2018-03-02 19:33:56 +0800 running
确实是已经导入了一个快照,快照名称和上文中source虚拟机的快照是一模一样的。
我们尝试着恢复下快照:
1 virsh snapshot-revert --domain test01 --snapshotname 1519990436
此时连接到虚拟机上看看,刚才保存的运行时状态也都在跑着,成功!
其他 近期在pyajs上写一个libvirt的http wrapper,叫closestack,用于小型化的项目,但是各种事情太多,进度很慢,希望能慢慢搞完吧:https://github.com/pyajs/closestack
转载请注明出处:https://knktc.com/2018/06/12/how-to-duplicate-kvm-snapshot/