KVM虛擬機快照研究(一)

      KVM虛擬機的快照用來保存虛擬機在某個時間點的內存、磁盤或者設備狀態,如果將來有需要可以把虛擬機的狀態回滾到這個時間點。

根據被做快照的對象不同,快照可以分爲磁盤快照和內存快照,兩者加起來構成了一個系統還原點,記錄虛擬機在某個時間點的全部狀態;根據做快照時虛擬機是否在運行,快照又可以分爲在線快照和離線快照。

磁盤快照根據存儲方式的不同,又分爲內部快照和外部快照:內部快照只支持qcow2格式的虛擬機鏡像,把快照及後續變動都保存在原來的qcow2文件內;外部快照在創建時,快照被保存在單獨一個文件中,創建快照時間點之後的數據被記錄到一個新的qcow2文件中,原鏡像文件成爲新的qcow2文件的backing file(只讀),在創建多個快照後,這些文件將形成一個鏈——backing chain。外部快照同時支持raw和qcow2格式的虛擬機鏡像。

下文將分別具體介紹不同類型的KVM虛擬機快照。

操作環境:

l  操作系統:

[root@localhost ~]# cat   /etc/redhat-release

CentOS Linux release 7.4.1708 (Core)

l  Libvirt版本:

[root@localhost ~]# libvirtd --version

libvirtd (libvirt) 3.2.0

l  qemu版本:

[root@localhost ~]# rpm -qa|grep qemu-kvm

qemu-kvm-common-ev-2.3.0-29.1.el7.x86_64

qemu-kvm-ev-2.3.0-29.1.el7.x86_64

centos7.4的默認yum源中的qemu-kvm不支持在線創建外部快照,需要安裝Redhat的qemu-kvm-ev,安裝方法:

1.      配置yum源

[root@localhost ~]# cat   /etc/yum.repos.d/qemu-kvm-rhev.repo

[qemu-kvm-rhev]

name=oVirt rebuilds of qemu-kvm-rhev

baseurl=http://resources.ovirt.org/pub/ovirt-3.5/rpm/el7Server/

mirrorlist=http://resources.ovirt.org/pub/yum-repo/mirrorlist-ovirt-3.5-el7Server

enabled=1

skip_if_unavailable=1

gpgcheck=0

2.      安裝

[root@localhost ~]# yum install qemu-kvm-rhev -y

測試機上有一臺虛擬機

[root@localhost ~]# virsh list

 Id      Name                             State

----------------------------------------------------

10      vm                             running

虛擬機的磁盤文件爲系統盤/data/vm.img,數據盤/data/data.img。

內存快照

1.      創建快照

命令:virsh save vm vm.snapshot1

[root@localhost ~]# virsh save vm   vm.snapshot1

 

Domain vm saved to vm.snapshot1

創建完後虛擬機會關機:

[root@localhost ~]# virsh list --all

 Id      Name                             State

----------------------------------------------------

 -       vm                             shut off

2.      回滾快照

命令:virsh restore vm.snapshot1

[root@localhost ~]# virsh restore   vm.snapshot1

Domain restored from vm.snapshot1

 

[root@localhost ~]# virsh list

 Id      Name                             State

----------------------------------------------------

 11      vm                             running

注:

1.      只能對關機狀態的虛擬機進行回滾快照;

2.      內存快照做完後,如果虛擬機磁盤文件發生修改,可能會導致corruption。

磁盤內部快照

磁盤內部快照可以在虛擬機開機狀態創建,但是創建過程中虛擬機處於paused狀態,

1.      創建快照

命令:virsh snapshot-create-as --domain vm --name vm1

這條命令執行後,虛擬機會變成paused狀態

[root@localhost ~]# virsh list

 Id      Name                             State

----------------------------------------------------

 13      vm                             paused

等快照創建完成,會重新變回running。

2.      查看快照

命令:virsh snapshot-list –domain vm

[root@localhost ~]# virsh snapshot-list   --domain vm

 Name                 Creation Time             State

------------------------------------------------------------

 vm1                  2018-03-06 10:37:57 +0800   running

快照回滾:virsh snapshot-revert --domain vm --snapshotname vm1

快照刪除:virsh snapshot-delete --domain vm --snapshotname vm1

磁盤內部快照有2個缺點:

1.      只支持qcow2格式的鏡像文件;

2.      創建快照虛擬機會paused,有停機時間,對於不能停機的線上業務來說是無法接受的。

磁盤外部快照

原理

假設虛擬機磁盤鏡像文件爲base,創建一個外部快照snapshot1,這時候的鏡像之間的關係backing chain如下:

base<-snapshot1*

“*”表示目前active狀態的鏡像,base變爲只讀,snapshot1以base爲backing file,虛擬機所有寫入都發生在snapshot1,如果再創建一個外部快照snapshot2,backing chain會變成:

base<-snapshot1<-snapshot2*

snapshot2又以snapshot1爲backing file,現在base和snapshot1都變成了只讀。繼續創建快照會加長這個backing chain:

base<-snapshot1<-snapshot2<-snapshot3<-snapshot4*

如果要回滾某個快照,就要把虛擬機使用的鏡像指向該快照文件的backing file。例如,回滾到snapshot2,就要把虛擬機的鏡像改爲snapshot1;回滾到snapshot1,則要把虛擬機的鏡像改爲base。回滾到snapshot1會導致snapshot1之後的所有快照失效,因爲他們在backing chain上游的backing file發生了變化(backing file只能是隻讀,如果數據發生變化,下游鏡像也會失效)。

隨着快照數量變多,backing chain也會越來越長,變得難以維護。如果有些快照已經沒用了可以進行刪除。縮短這條鏈通常有兩種思路:

1.      blockcommit,從top文件合併數據到base(下游鏡像向backing file合併,稱爲“commit”);

2.      blockpull,從base文件合併數據到top(從backing file向下遊鏡像合併,稱爲“pull”)。截止目前只能將backing file合併至當前的active的鏡像中,也就是說還不支持指定top的合併。

在上面的backing chain中,如果我們要刪除snapshot2,方法如下:

1.      blockcommit:把snapshot2的數據合併到snapshot1,合併完後backing chain變成了

base<-snapshot1<-snapshot2(內容爲snapshot2+snapshot3)<-snapshot4*

2.      blockpull:把snapshot2的數據合併到snapshot3,合併完後backing chain變成了

base<-snapshot1<-snapshot3(內容爲snapshot2+snapshot3)<-snapshot4*

 

具體操作

1.      創建外部快照

命令:virsh snapshot-create-as --domain vm --name snapshot1 --disk-only --atomic --no-metadata

--disk-only 有這個參數,snapshot-create-as命令就會創建磁盤外部快照;

--atomic 如果虛擬機有多個磁盤,則把爲虛擬機所有磁盤創建快照的操作當做一個原子操作,要麼全部成功,要麼全部失敗;

--no-metadata 不讓libvirt記錄快照的元數據。這個參數不是必須的,但是強烈建議使用,目前libvirt對外部快照支持不完整,只能創建,不能刪除和回滾,如果要刪除一個有外部快照的虛擬機,會出現以下報錯:

[root@localhost ~]# virsh undefine vm

error: Failed to undefine domain test

error: Requested operation is not valid:   cannot delete inactive domain with 1 snapshots

加上這個參數後,libvirt不再管理外部快照,刪除和回滾都不會受影響了。

快照創建成功後,在虛擬機磁盤文件目錄下會多出2個新文件vm.snapshot1和data.snapshot1,分別是系統盤和數據盤的快照文件,查看鏡像信息可以看出,它們分別以原鏡像爲backing file,與之前原理中分析的一致:

[root@localhost data]# qemu-img info   vm.snapshot1

image: vm.snapshot1

file format: qcow2

virtual size: 20G (21474836480 bytes)

disk size: 3.4M

cluster_size: 65536

backing file: /data/vm.img

backing file format: qcow2

Format specific information:

      compat: 1.1

      lazy refcounts: false

      refcount bits: 16

      corrupt: false

[root@localhost data]# qemu-img info   data.snapshot1

image: data.snapshot1

file format: qcow2

virtual size: 1.0G (1073741824 bytes)

disk size: 196K

cluster_size: 65536

backing file: /data/data.img

backing file format: qcow2

Format specific information:

      compat: 1.1

      lazy refcounts: false

      refcount bits: 16

corrupt: false

創建完後,虛擬機xml文件中使用的磁盤文件會libvirt自動被改成這兩個新文件,這兩個新文件處於active狀態,原鏡像變爲只讀。

<disk type='file' device='disk'>

        <driver name='qemu' type='qcow2' cache='none' io='native'/>

        <source file='/data/vm.snapshot1'/>

        <target dev='vda' bus='virtio'/>

        <address type='pci' domain='0x0000' bus='0x00' slot='0x04'   function='0x0'/>

      </disk>

      <disk type='file' device='disk'>

        <driver name='qemu' type='qcow2' cache='none' io='native'/>

        <source file='/data/data.snapshot1'/>

        <target dev='vdb' bus='virtio'/>

        <address type='pci' domain='0x0000' bus='0x00' slot='0x07'   function='0x0'/>

      </disk>

2.      回滾快照

Libvirt目前不支持回滾外部快照,只能純手工操作。爲了證明在回滾快照後虛擬機確實回到了快照記錄的狀態,我們在虛擬機中在/root下新建一個空文件test。然後關閉虛擬機並把虛擬機的磁盤改回vm.img和data.img,開機後會發現/root/test不見了,可以證明虛擬機文件系統回到了創建快照的時間點。

由上面的操作我們可以得出結論:回滾到某個快照,就是把虛擬機當前磁盤文件改爲這個快照文件的backing file;快照名和快照文件名並不對應,例如創建snapshot1後產生的文件vm.snapshot1中記錄的並不是快照snapshot1的內容,它的backing file纔是。在下面介紹刪除快照時,牢記這點尤其重要。

3.      刪除快照

在原理中已經介紹過,刪除快照有blockcommit和blockpull兩種思路,由於blockpull不支持指定top的合併,下面將只介紹blockcommit方式。我們先爲虛擬機vm多創建幾個快照,現在快照鏈爲(以下操作都以系統盤爲例,數據盤同理):

base<-snapshot1<-snapshot2<-snapshot3<-snapshot4*

qemu-img命令也可以查看鏈關係:

[root@localhost   data]# qemu-img info --backing-chain vm.snapshot4

image:   vm.snapshot4

file format: qcow2

virtual size:   20G (21474836480 bytes)

disk size:   452K

cluster_size:   65536

backing file:   /data/vm.snapshot3

backing file   format: qcow2

Format   specific information:

    compat: 1.1

    lazy refcounts: false

    refcount bits: 16

    corrupt: false

 

image:   /data/vm.snapshot3

file format:   qcow2

virtual size:   20G (21474836480 bytes)

disk size:   196K

cluster_size:   65536

backing file:   /data/vm.snapshot2

backing file   format: qcow2

Format   specific information:

    compat: 1.1

    lazy refcounts: false

    refcount bits: 16

    corrupt: false

 

image:   /data/vm.snapshot2

file format:   qcow2

virtual size:   20G (21474836480 bytes)

disk size:   196K

cluster_size:   65536

backing file:   /data/vm.img

backing file   format: qcow2

Format   specific information:

    compat: 1.1

    lazy refcounts: false

    refcount bits: 16

    corrupt: false

 

image:   /data/vm.img

file format:   qcow2

virtual size:   20G (21474836480 bytes)

disk size:   1.5G

cluster_size:   65536

Format   specific information:

    compat: 0.10

    refcount bits: 16

現在我們要刪除snapshot2,根據回滾快照時得出的結論,要回滾到snapshot2就是把虛擬機磁盤指向vm.snapshot1,所以刪除snapshot2就要在不影響backing chain中其他文件的前提下,把vm.snapshot2的內容合併到vm.snapshot1,vm.snapshot1的內容發生了改變,也就不能回滾到snapshot2了,達到了刪除快照的目的。操作命令如下:

virsh blockcommit --domain vm vda --base /data/vm.snapshot1 --top /data/vm.snapshot2 --wait –verbose

virsh blockcommit --domain vm vdb --base /data/data.snapshot1 --top /data/data.snapshot2 --wait –verbose

合併完後,使用qemu-img命令再次查看文件信息可以發現,vm.snapshot2已經不在backing chain中了:

[root@localhost data]# qemu-img info --backing-chain vm.snapshot4

image: vm.snapshot4

file format: qcow2

virtual size: 20G (21474836480 bytes)

disk size: 1.1M

cluster_size: 65536

backing file: /data/vm.snapshot3

backing file format: qcow2

Format specific information:

    compat: 1.1

    lazy refcounts: false

    refcount bits: 16

    corrupt: false

 

image: /data/vm.snapshot3

file format: qcow2

virtual size: 20G (21474836480 bytes)

disk size: 388K

cluster_size: 65536

backing file: /data/vm.snapshot1

backing file format: qcow2

Format specific information:

    compat: 1.1

    lazy refcounts: false

    refcount bits: 16

    corrupt: false

 

image: /data/vm.snapshot1

file format: qcow2

virtual size: 20G (21474836480 bytes)

disk size: 1.5M

cluster_size: 65536

backing file: /data/vm.img

backing file format: qcow2

Format specific information:

    compat: 1.1

    lazy refcounts: false

    refcount bits: 16

    corrupt: false

 

image: /data/vm.img

file format: qcow2

virtual size: 20G (21474836480 bytes)

disk size: 1.5G

cluster_size: 65536

Format specific information:

    compat: 0.10

    refcount bits: 16

 

總結

三種快照中,只有磁盤外部快照可以不停機創建,所以這種快照最符合我們平時的需求,後續研究也重點關注外部快照。不幸的是libvirt對外部快照的支持太弱,大部分操作需要我們人腦思考、手工操作。接下來研究的重點有以下幾點:

1.      測試外部快照創建時是否真正零停機時間;

2.      虛擬機運行時進行快照文件合併對性能有何影響;

3.      利用Python腳本封裝外部快照的操作。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章