【KVM系列07】使用 libvirt 做 QEMU/KVM 快照和 Nova 实例的快照
?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?第七章 使用 libvirt 做 QEMU/KVM 快照和 Nova 實(shí)例的快照
1. QEMU/KVM 快照
1.1 概念
1.2 使用 virsh 實(shí)驗(yàn)
1.3 外部快照的刪除
2. OpenStack 中的快照
2.1 對(duì) Nova Instance 進(jìn)行快照
2.2 對(duì)卷做快照
3. 從鏡像文件啟動(dòng)的 Nova 虛機(jī)做快照
3.1 Nova Live Snapshot?
3.2 Nova Cold Snapshot
4. 從 volume 啟動(dòng)的 Nova 實(shí)例的快照
5. 當(dāng)前 Nova snapshot 的局限
【KVM系列文章】https://blog.csdn.net/baidu_37107022/article/details/88812463
?
本文將梳理 QEMU/KVM 快照相關(guān)的知識(shí),以及在 OpenStack Nova 中使用 libvirt 來對(duì) QEMU/KVM 虛機(jī)做快照的過程。
1. QEMU/KVM 快照
1.1 概念
QEMU/KVM 快照的定義:
- 磁盤快照:磁盤的內(nèi)容(可能是虛機(jī)的全部磁盤或者部分磁盤)在某個(gè)時(shí)間點(diǎn)上被保存,然后可以被恢復(fù)。
- 磁盤數(shù)據(jù)的保存狀態(tài):
- 在一個(gè)運(yùn)行著的系統(tǒng)上,一個(gè)磁盤快照很可能只是崩潰一致的(crash-consistent) 而不是完整一致(clean)的,也是說它所保存的磁盤狀態(tài)可能相當(dāng)于機(jī)器突然掉電時(shí)硬盤數(shù)據(jù)的狀態(tài),機(jī)器重啟后需要通過 fsck 或者別的工具來恢復(fù)到完整一致的狀態(tài)(類似于 Windows 機(jī)器在斷電后會(huì)執(zhí)行文件檢查)。
- 對(duì)一個(gè)非運(yùn)行中的虛機(jī)來說,如果上次虛機(jī)關(guān)閉的時(shí)候磁盤是完整一致的,那么其被快照的磁盤快照也將是完整一致的。
- 磁盤快照有兩種:
- 內(nèi)部快照 - 使用單個(gè)的 qcow2 的文件來保存快照和快照之后的改動(dòng)。這種快照是 libvirt 的默認(rèn)行為,現(xiàn)在的支持很完善(創(chuàng)建、回滾和刪除),但是只能針對(duì) qcow2 格式的磁盤鏡像文件,而且其過程較慢等。
- 外部快照 - 快照是一個(gè)只讀文件,快照之后的修改是另一個(gè) qcow2 文件中。外置快照可以針對(duì)各種格式的磁盤鏡像文件。外置快照的結(jié)果是形成一個(gè) qcow2 文件鏈:original <- snap1 <- snap2 <- snap3。http://wiki.libvirt.org/page/Qemu_guest_agent
快照還可以分為 live snapshot(熱快照)和 Clod snapshot:
- Live snapshot:系統(tǒng)運(yùn)行狀態(tài)下做的快照
- Cold snapshot:系統(tǒng)停止?fàn)顟B(tài)下的快照
libvit 做 snapshot 的各個(gè) API:
snapshot 做快照的 libvirt API 從快照恢復(fù)的 libvirt API virsh 命令 磁盤快照 virDomainSnapshotCreateXML(flags =?VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY?) virDomainRevertToSnapshot ?virsh snapshot-create/snapshot-revert 內(nèi)存(狀態(tài))快照 virDomainSave
virDomainSaveFlags
virDomainManagedSave
virDomainRestore
virDomainRestoreFlags
virDomainCreate
virDomainCreateWithFlags
virsh save/restore 系統(tǒng)檢查點(diǎn) virDomainSnapshotCreateXML virDomainRevertToSnapshot ?virsh snapshot-create/snapshot-revert 分別來看看這些 API 是如何工作的:
1.?virDomainSnapshotCreateXML?(virDomainPtr domain, const char * xmlDesc, unsigned int flags)
作用:根據(jù) xmlDesc 指定的 snapshot xml 和 flags 來創(chuàng)建虛機(jī)的快照。
flags 包含 ?虛機(jī)處于運(yùn)行狀態(tài)時(shí)快照的做法 虛機(jī)處于關(guān)閉狀態(tài)時(shí)快照的做法 0 創(chuàng)建系統(tǒng)檢查點(diǎn),包括磁盤狀態(tài)和內(nèi)存狀態(tài)比如內(nèi)存內(nèi)容 保持關(guān)機(jī)時(shí)的磁盤狀態(tài) VIR_DOMAIN_SNAPSHOT_CREATE_LIVE 做快照期間,虛機(jī)將不會(huì)被 paused。這會(huì)增加內(nèi)存 dump file 的大小,但是可以減少系統(tǒng)停機(jī)時(shí)間。部分 Hypervisor 只在做外部的系統(tǒng)檢查點(diǎn)時(shí)才設(shè)置該 flag,這意味著普通快照還是需要暫停虛機(jī)。 ? VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY 只做指定磁盤的快照。對(duì)應(yīng)運(yùn)行著的虛機(jī),磁盤快照可能是不完整的(類似于突然電源被拔了的情形)。 只做指定磁盤的快照。 其內(nèi)部實(shí)現(xiàn)根據(jù)虛機(jī)的運(yùn)行狀態(tài)有兩種情形:
- 對(duì)運(yùn)行著的虛機(jī),API 使用 QEMU Monitor 去做快照,磁盤鏡像文件必須是 qcow2 格式,虛機(jī)的 CPU 被停止,快照結(jié)束后會(huì)重新啟動(dòng)。
- 對(duì)停止著的虛機(jī),API 調(diào)用 qemu-img 方法來操作所有磁盤鏡像文件。
這里有其實(shí)現(xiàn)代碼,可見其基本的實(shí)現(xiàn)步驟:?
static virDomainSnapshotPtr qemuDomainSnapshotCreateXML{....call qemuDomainSnapshotCreateDiskActive{call qemuProcessStopCPUs # 停止 vCPUs for each disk call qemuDomainSnapshotCreateSingleDiskActive{call qemuMonitorDiskSnapshot # 調(diào)用 QEMU Monitor 去為每個(gè)磁盤做snapshot }call qemuProcessStartCPUs # 啟動(dòng) vCPUs } .... }2.?virDomainSave?相關(guān)的幾個(gè) API
這幾個(gè)API 功能都比較類似:
virDomainSave? 該方法會(huì) suspend 一個(gè)運(yùn)行著的虛機(jī),然后保存期內(nèi)存內(nèi)容到一個(gè)文件中。成功調(diào)用以后,domain 將不會(huì)處于 running 狀態(tài)。使用?virDomainRestore 來恢復(fù)虛機(jī)。 virDomainSaveFlags? 類似于?virDomainSave?API,可使用幾個(gè) ?flags。一些 Hypervisor 在調(diào)用該方法前需要調(diào)用??virDomainBlockJobAbort() 方法來停止 block copy 操作。 virDomainManagedSave? 也類似于?virDomainSave?API。主要區(qū)別是 libvirt 將其內(nèi)存保存到一個(gè)受 libvirt 管理的文件中,因此libvirt 可以一直跟蹤 snapshot 的狀態(tài);當(dāng)調(diào)用 virDomainCreate/virDomainCreateWithFlags 方法重啟該?domain的時(shí)候,libvirt 會(huì)使用該受管文件,而不是一個(gè)空白的文件,這樣就可以 restore 該snapshot。 Features/SnapshotsMultipleDevices?這篇文章討論同時(shí)對(duì)多個(gè)磁盤做快照的問題。
1.2 使用 virsh 實(shí)驗(yàn)
1.2.1 virsh save 命令
對(duì)運(yùn)行中的 domain d-2 運(yùn)行 “virsh save” 命令。命令執(zhí)行完成后,d-2 變成 “shut off” 狀態(tài)。
看看 domain 的磁盤鏡像文件和 snapshot 文件:
內(nèi)存數(shù)據(jù)被保存到 raw 格式的文件中。
要恢復(fù)的時(shí)候,可以運(yùn)行 “vish restore d-2.snap1” 命令從保存的文件上恢復(fù)。
1.2.2 virsh snapshot-create/snapshort-create-as
先看看它的用法:
virsh # help snapshot-create-asNAMEsnapshot-create-as - Create a snapshot from a set of argsSYNOPSISsnapshot-create-as [] [] [--print-xml] [--no-metadata] [--halt] [--disk-only] [--reuse-external] [--quiesce] [--atomic] [--live] [--memspec ] [[--diskspec] ]...DESCRIPTIONCreate a snapshot (disk and RAM) from argumentsOPTIONS[--domain] domain name, id or uuid[--name] name of snapshot[--description] description of snapshot--print-xml print XML document rather than create--no-metadata take snapshot but create no metadata--halt halt domain after snapshot is created--disk-only capture disk state but not vm state--reuse-external reuse any existing external files--quiesce quiesce guest's file systems--atomic require atomic operation--live take a live snapshot--memspec memory attributes: [file=]name[,snapshot=type][--diskspec] disk attributes: disk[,snapshot=type][,driver=type][,file=name]其中一些參數(shù),比如 --atomic,在一些老的 QEMU libary 上不支持,需要更新它到新的版本。根據(jù)?這篇文章,atomic 應(yīng)該是 QEMU 1.0 中加入的。
(1)默認(rèn)的話,該命令創(chuàng)建虛機(jī)的所有磁盤和內(nèi)存做內(nèi)部快照,創(chuàng)建快照時(shí)虛機(jī)處于 paused 狀態(tài),快照完成后變?yōu)?running 狀態(tài)。持續(xù)時(shí)間較長(zhǎng)。
<memory snapshot='internal'/><disk name='vda' snapshot='internal'/><disk name='vdb' snapshot='internal'/><disk name='vdc' snapshot='internal'/>每個(gè)磁盤的鏡像文件都包含了 snapshot 的信息:
root@compute1:/var/lib/nova/instances/eddc46a8-e026-4b2c-af51-dfaa436fcc7b# qemu-img info diskimage: diskfile format: qcow2virtual size: 1.0G (1073741824 bytes)disk size: 43Mcluster_size: 65536backing file: /var/lib/nova/instances/_base/fbad3d96a1727069346073e51d5bbb1824e76e34 Snapshot list:ID TAG VM SIZE DATE VM CLOCK1 1433950148 41M 2015-06-10 23:29:08 05:16:55.007 Format specific information:compat: 1.1lazy refcounts: false你可以運(yùn)行 snapshot-revert 命令回滾到指定的snapshot。
virsh # snapshot-revert instance-0000002e 1433950148根據(jù)?這篇文章,libvirt 將內(nèi)存狀態(tài)保存到某一個(gè)磁盤鏡像文件內(nèi) (”state is saved inside one of the disks (as in qemu's 'savevm'system checkpoint implementation). If needed in the future,we can also add an attribute pointing out _which_ disk saved the internal state; maybe disk='vda'.)
(2)可以使用 “--memspec” 和 “--diskspec” 參數(shù)來給內(nèi)存和磁盤外部快照。這時(shí)候,在獲取內(nèi)存狀態(tài)之前需要 Pause 虛機(jī),就會(huì)產(chǎn)生服務(wù)的 downtime。
virsh # snapshot-create-as 0000002e livesnap2 --memspec /home/s1/livesnap2mem,snapshot=external --diskspec vda,snapshot=externalDomain snapshot livesnap2 createdvirsh # snapshot-dumpxml 0000002e livesnap2 <driver type='qcow2'/><source file='/home/s1/testvm/testvm1.livesnap2'/>(3)可以使用 “--disk-only” 參數(shù),這時(shí)會(huì)做所有磁盤的外部快照,但是不包含內(nèi)存的快照。不指定快照文件名字的話,會(huì)放在原來的磁盤文件所在的目錄中。多次快照后,會(huì)形成一個(gè)外部快照鏈,新的快照使用前一個(gè)快照的鏡像文件作為 backing file。
virsh # snapshot-list instance-0000002e --tree 1433950148 #內(nèi)部快照 1433950810 #內(nèi)部快照 1433950946 #內(nèi)部快照 snap1 #第一個(gè)外部快照 |+- snap2 #第二個(gè)外部快照 |+- 1433954941 #第三個(gè)外部快照 |+- 1433954977 #第四個(gè)外部快照而第一個(gè)外部快照的鏡像文件是以虛機(jī)的原始鏡像文件作為 backing file 的:
root@compute1:/var/lib/nova/instances/eddc46a8-e026-4b2c-af51-dfaa436fcc7b# qemu-img info disk.snap1image: disk.snap1file format: qcow2virtual size: 30M (31457280 bytes)disk size: 196Kcluster_size: 65536backing file: /var/lib/nova/instances/eddc46a8-e026-4b2c-af51-dfaa436fcc7b/disk.swap #虛機(jī)的 swap disk 原始鏡像文件 backing file format: qcow2Format specific information:compat: 1.1lazy refcounts: false目前還不支持回滾到某一個(gè)extrenal disk snapshot。這篇文章?談到了一個(gè)workaround。
[root@rh65 osdomains]# virsh snapshot-revert d-2 1434467974
error: unsupported configuration: revert to external disk snapshot not supported yet(4)還可以使用 “--live” 參數(shù)創(chuàng)建系統(tǒng)還原點(diǎn),包括磁盤、內(nèi)存和設(shè)備狀態(tài)等。使用這個(gè)參數(shù)時(shí),虛機(jī)不會(huì)被 Paused(那怎么實(shí)現(xiàn)的?)。其后果是增加了內(nèi)存 dump 文件的大小,但是減少了系統(tǒng)的 downtime。該參數(shù)只能用于做外部的系統(tǒng)還原點(diǎn)(external checkpoint)。
virsh # snapshot-create-as 0000002e livesnap3 --memspec /home/s1/livesnap3mem,snapshot=external --diskspec vda,snapshot=external --live Domain snapshot livesnap3 createdvirsh # snapshot-dumpxml 0000002e livesnap3 <memory snapshot='external' file='/home/s1/livesnap3mem'/><disk name='vda' snapshot='external' type='file'><driver type='qcow2'/><source file='/home/s1/testvm/testvm1.livesnap3'/>注意到加 “--live” 生成的快照和不加這個(gè)參數(shù)生成的快照不會(huì)被鏈在一起:
virsh # snapshot-list 0000002e --tree livesnap1 #沒加 --live |+- livesnap2 #沒加 --live livesnap3 #加了 --live |+- livesnap4 #加了 --live不過,奇怪的是,使用 QEMU 2.3 的情況下,即使加了 --live 參數(shù),虛機(jī)還是會(huì)被短暫的 Paused 住:
[root@rh65 ~]# virsh snapshot-create-as d-2 --memspec /home/work/d-2/mem3,snapshot=external --diskspec hda,snapshot=external --liveDomain snapshot 1434478667 created[root@rh65 ~]# virsh list --allId Name State ---------------------------------------------------- 40 osvm1 running 42 osvm2 running 43 d-2 running[root@rh65 ~]# virsh list --allId Name State ---------------------------------------------------- 40 osvm1 running 42 osvm2 running 43 d-2 paused # 不是說好我用 --live 你就不pause 虛機(jī)的么?這是腫了么。。 [root@rh65 ~]# virsh list --allId Name State ---------------------------------------------------- 40 osvm1 running 42 osvm2 running 43 d-2 running綜上所述,對(duì)于?snapshot-create-as 命令來說,
參數(shù) 結(jié)果 ? 所有磁盤和內(nèi)存的內(nèi)部的內(nèi)部快照 --memspec snapshot=external --diskspec vda,snapshot=external 磁盤和內(nèi)存的外部快照,虛機(jī)需要被暫停 --live ?--memspec snapshot=external --diskspec vda,snapshot=external 創(chuàng)建系統(tǒng)檢查點(diǎn)(包括磁盤和內(nèi)存的快照),而且虛機(jī)不會(huì)被暫停(?測(cè)試結(jié)果顯示還是會(huì)暫停,只是暫停時(shí)間比不使用 --live 要短一些) --disk-only 創(chuàng)建所有或者部分磁盤的外部快照 ?可以使用 sanpshot-revert 命令來回滾到指定的系統(tǒng)還原點(diǎn),不過得使用 “-force” 參數(shù):
[root@rh65 ~]# virsh snapshot-revert d-2 1434478313 error: revert requires force: Target device address type none does not match source pci[root@rh65 ~]# virsh snapshot-revert d-2 1434478313 --force[root@rh65 ~]#1.3 外部快照的刪除
目前 libvirt 還不支持直接刪除一個(gè)外部快照,可以參考?這篇文章?介紹的 workaround。
2. OpenStack 中的快照
?OpenStack Snapshot 可分為下面的幾種情形:
2.1 對(duì) Nova Instance 進(jìn)行快照
(1)對(duì)從鏡像文件啟動(dòng)的虛機(jī)做快照
- 只將運(yùn)行當(dāng)中的虛機(jī)的 Root disk (第一個(gè)vd 或者 hd disk) 做成 image,然后上傳到 glance 里面
- Live Snapshot:對(duì)滿足特定條件(QEMU 1.3+ 和 Libvirt 1.0.0+,以及 source_format not in ('lvm', 'rbd') and not CONF.ephemeral_storage_encryption.enabled and not CONF.workarounds.disable_libvirt_livesnapshot,以及能正常調(diào)用 libvirt.blockJobAbort ,其前提條件可參考這文章)的虛機(jī),會(huì)進(jìn)行 Live snapshot。Live Snapshot 允許用戶在虛機(jī)處于運(yùn)行狀態(tài)時(shí)不停機(jī)做快照。
- Cold Snapshot:對(duì)不能做 live snapshot 的虛機(jī)做 Cold snapshot。這種快照必須首先 Pause 虛機(jī)。
(2)對(duì)從卷啟動(dòng)的虛機(jī)做快照
- 對(duì)虛機(jī)的每個(gè)掛載的 volume 調(diào)用 cinder API 做 snapshot。
- Snapshot 出的 metadata 會(huì)保存到 glance 里面,但是不會(huì)有 snapshot 的 image 上傳到 Glance 里面。
- 這個(gè) snapshot 也會(huì)出現(xiàn)在 cinder 的數(shù)據(jù)庫(kù)里面,對(duì) cinder API 可見。
2.2 對(duì)卷做快照
- 調(diào)用 cinder driver api,對(duì) backend 中的 volume 進(jìn)行 snapshot。
- 這個(gè) snapshot 會(huì)出現(xiàn)在 cinder 的數(shù)據(jù)庫(kù)里面,對(duì) cinder API 可見。??
3. 從鏡像文件啟動(dòng)的 Nova 虛機(jī)做快照
? ? 嚴(yán)格地說,Nova 虛機(jī)的快照,并不是對(duì)虛機(jī)做完整的快照,而是對(duì)虛機(jī)的啟動(dòng)盤(root disk,即 vda 或者 hda)做快照生成 qcow2 格式的文件,并將其傳到 Glance 中,其作用也往往是方便使用快照生成的鏡像來部署新的虛機(jī)。Nova 快照分為 Live Snapshot (不停機(jī)快照)和 Clold Snapshot (停機(jī)快照)。
3.1 Nova Live Snapshot
滿足 2.1.1 中所述條件時(shí),運(yùn)行命令 ?”nova image-create “ 后,Nova 會(huì)執(zhí)行 Live Snapshot。其過程如下:
- 找到虛機(jī)的 root disk (vda 或者 hda)。
- 在?CONF.libvirt.snapshots_directory 指定的文件夾(默認(rèn)為 /var/lib/nova/instances/snapshots)中創(chuàng)建一個(gè)臨時(shí)文件夾,在其中創(chuàng)建一個(gè) qcow2 格式的 delta 文件,其文件名為 uuid 字符串,該文件的 backing file 和 root disk 文件的 backing file 相同 (下面步驟 a)。
- 調(diào)用 virDomainGetXMLDesc 來保存 domain 的 xml 配置。
- 調(diào)用?virDomainBlockJobAbort 來停止對(duì) root disk 的活動(dòng)塊操作 (Cancel the active block job on the given disk)。
- 調(diào)用?virDomainUndefine 來將 domain 變?yōu)?transimit 類型的,這是因?yàn)?BlockRebase API 不能針對(duì) Persistent domain 調(diào)用。
- 調(diào)用?virDomainBlockRebase?來將 root disk image 文件中不同的數(shù)據(jù)拷貝到 delta disk file 中。(下面步驟 b)
- 步驟 6 是一個(gè)持續(xù)的過程,因?yàn)榭赡苡袘?yīng)用正在向該磁盤寫數(shù)據(jù)。Nova?每隔 0.5 秒調(diào)用?virDomainBlockJobInfo?API 來檢查拷貝是否結(jié)束。
- 拷貝結(jié)束后,調(diào)用 ?virDomainBlockJobAbort 來終止數(shù)據(jù)拷貝。
- 調(diào)用?virDomainDefineXML 將domain 由 transimisit 該回到 persistent。
- 調(diào)用?qemu-img convert 命令將?delta image 文件和 backing file 變?yōu)橐粋€(gè) qcow2 文件 (下面步驟 c)
- 將 image 的元數(shù)據(jù)和 qcow2 文件傳到 Glance 中。
- detach PCI devices
- detach SR-IOV devices
- 調(diào)用?virDomainManagedSave API 來將虛機(jī) suspend 并且將內(nèi)存狀態(tài)保存到磁盤文件中。
- Nova snapshot 其實(shí)只是提供一種創(chuàng)造系統(tǒng)盤鏡像的方法。不支持回滾至快照點(diǎn),只能采用該快照鏡像創(chuàng)建一個(gè)新的虛擬機(jī)。
- 在虛機(jī)是從 image boot 的時(shí)候,只對(duì)系統(tǒng)盤進(jìn)行快照,不支持內(nèi)存快照,不支持系統(tǒng)還原點(diǎn)?(blueprint:https://blueprints.launchpad.net/nova/+spec/live-snapshot-vms)
- Live Snapshot 需要用戶進(jìn)行一致性操作:http://www.sebastien-han.fr/blog/2012/12/10/openstack-perform-consistent-snapshots/
- 只支持虛擬機(jī)內(nèi)置(全量)快照,不支持外置(增量)快照。這與當(dāng)前快照的實(shí)現(xiàn)方式有關(guān),因?yàn)槭峭ㄟ^ image 進(jìn)行保存的。
- 從 image boot 的虛機(jī)的快照以 Image 方式保存到 Glance 中,而非以 Cinder 卷方式保存。
- 過程較長(zhǎng)(需要先通過存儲(chǔ)快照,然后抽取并上傳至 Glance),網(wǎng)絡(luò)開銷大。
- 這應(yīng)該是一種虛擬化技術(shù)的功能,不是云計(jì)算平臺(tái)的功能。
- openstack 由于底層要支持多種虛擬化的技術(shù),某些虛擬化技術(shù)實(shí)現(xiàn)這種功能比較困難。
- 創(chuàng)建的 VM state snapshot 會(huì)面臨 cpu feature 不兼容的問題。
- 目前 libvirt 對(duì) QEMU/KVM 虛機(jī)的外部快照的支持還不完善,即使更新到最新的 libvirt 版本,造成兼容性比較差。
?
(a)執(zhí)行 qemu-img create -f qcow2 (qemu-img create 創(chuàng)建一個(gè)基于鏡像1的鏡像2,鏡像2的文件將基于鏡像1,鏡像2中的文件將基于鏡像1中的。在鏡像2中所作的任何讀寫操作都不會(huì)影響到鏡像1. 鏡像1可以被其他鏡像當(dāng)做backing file. 但是要確保鏡像1不要被修改)。比如: qemu-img create -f qcow2 -o backing_file=/var/lib/nova/instances/_base/ed39541b2c77cd7b069558570fa1dff4fda4f678,size=21474836480 /var/lib/nova/instances/snapshots/tmpzfjdJS/7f8d11be9ff647f6b7a0a643fad1f030.delta (b)相當(dāng)于執(zhí)行 virsh blockjob [--abort] [--async] [--pivot] [--info] [] (c)執(zhí)行 'qemu-img convert -f qcow2 -o dest_fmt' 來將帶 backing file 的 qcow2 image 轉(zhuǎn)化成不帶 backing file 的 flat image。其中 dest_fmt 由 snapshot_image_format 決定,有效值是 raw, qcow2, vmdk, vdi,默認(rèn)值是 source image 的 format。比如: qemu-img convert -f qcow2 -O qcow2 /var/lib/nova/instances/snapshots/tmpzfjdJS/7f8d11be9ff647f6b7a0a643fad1f030.delta /var/lib/nova/instances/snapshots/tmpzfjdJS/7f8d11be9ff647f6b7a0a643fad1f030?
來看看其中的一個(gè)關(guān)鍵 API?int?virDomainBlockRebase?(virDomainPtr dom, const char * disk, const char * base, unsigned long bandwidth,unsigned int flags)
該 API 從 backing 文件中拷貝數(shù)據(jù),或者拷貝整個(gè) backing 文件到 @base 文件。 Nova 中的調(diào)用方式為:domain.blockRebase(disk_path, disk_delta, 0,libvirt.VIR_DOMAIN_BLOCK_REBASE_COPY |libvirt.VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT |libvirt.VIR_DOMAIN_BLOCK_REBASE_SHALLOW) 默認(rèn)的話,該 API 會(huì)拷貝整個(gè)@disk 文件到 @base 文件,但是使用 ?VIR_DOMAIN_BLOCK_REBASE_SHALLOW 的話就只拷貝差異數(shù)據(jù)(top data)因?yàn)?@disk 和 @base 使用相同的 backing 文件。?VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT 表示需要使用已經(jīng)存在的 @base 文件因?yàn)?Nova 會(huì)預(yù)先創(chuàng)建好這個(gè)文件。簡(jiǎn)單的示意圖:
這里?有個(gè)過程的 PoC 代碼描述該過程。
這里?有該過程的完整 libvirt 日志分析。
這里?有文章講 Libvirt?Features/SnapshotsMultipleDevices。
3.2 Nova Cold Snapshot
當(dāng)虛機(jī)不在運(yùn)行中時(shí)或者不滿足 live snapshot 的條件的情況下,Nova 會(huì)執(zhí)行 Cold snapshot。其主要過程如下:
(1)當(dāng)虛機(jī)處于 running 或者 paused 狀態(tài)時(shí):
(2)調(diào)用?qemu-img convert 命令將 root disk 的鏡像文件轉(zhuǎn)化一個(gè)相同格式的鏡像文件。
(3)調(diào)用 virDomainCreateWithFlags? API?將虛機(jī)變?yōu)槌跏紶顟B(tài)
(4)將在步驟1 中卸載的 PCI 和 SR-IOV 設(shè)備重新掛載回來
(5)將元數(shù)據(jù)和 qcow2 文件傳到 Glance 中
4. 從 volume 啟動(dòng)的 Nova 實(shí)例的快照
(0)從卷啟動(dòng)虛機(jī),并且再掛載一個(gè)卷,然后運(yùn)行 nova image-create 命令。
| image | Attempt to boot from volume - no image supplied || key_name | - || metadata | {} || name | vm10 || os-extended-volumes:volumes_attached | [{"id": "26446902-5a56-4c79-b839-a8e13a66dc7a"}, {"id": "de127d46-ed92-471d-b18b-e89953c305fd"}](1)從 DB 獲取該虛機(jī)的塊設(shè)備( Block Devices Mapping)列表。
(2)對(duì)該列表中的每一個(gè)卷,依次調(diào)用 Cinder API 做快照。對(duì) LVM Driver 的 volume 來說,執(zhí)行的命令類似于 " lvcreate --size 100M --snapshot --name snap /dev/vg00/lvol1“。
s1@controller:~$ cinder snapshot-list +--------------------------------------+--------------------------------------+-----------+------------------------+------+| ID | Volume ID | Status | Name | Size |+--------------------------------------+--------------------------------------+-----------+------------------------+------+| a7c591fb-3413-4548-abd8-86753da3158b | de127d46-ed92-471d-b18b-e89953c305fd | available | snapshot for vm10-snap | 1 || d1277ea9-e972-4dd4-89c0-0b9d74956247 | 26446902-5a56-4c79-b839-a8e13a66dc7a | available | snapshot for vm10-snap | 1 |+--------------------------------------+--------------------------------------+-----------+------------------------+------+(3)將快照的 metadata 放到 Glance 中。(注:該 image 只是一些屬性的集合,比如 block device mapping, kernel 和 ramdisk IDs 等,它并沒有 image 數(shù)據(jù), 因此其 size 為 0。)
s1@controller:~$ glance image-show e86cc562-349c-48cb-a81c-896584accde3 +---------------------------------+----------------------------------------------------------------------------------+| Property | Value |+---------------------------------+----------------------------------------------------------------------------------+| Property 'bdm_v2' | True || Property 'block_device_mapping' | [{"guest_format": null, "boot_index": 0, "no_device": null, "snapshot_id": || # 分別是該虛機(jī)掛載的兩個(gè)volume 的 | "d1277ea9-e972-4dd4-89c0-0b9d74956247", "delete_on_termination": null, || snapshot 的信息 | "disk_bus": "virtio", "image_id": null, "source_type": "snapshot", || | "device_type": "disk", "volume_id": null, "destination_type": "volume", || | "volume_size": null}, {"guest_format": null, "boot_index": null, "no_device": || | null, "snapshot_id": "a7c591fb-3413-4548-abd8-86753da3158b", || | "delete_on_termination": null, "disk_bus": null, "image_id": null, || | "source_type": "snapshot", "device_type": null, "volume_id": null, || | "destination_type": "volume", "volume_size": null}] || Property 'checksum' | 64d7c1cd2b6f60c92c14662941cb7913 || Property 'container_format' | bare || Property 'disk_format' | qcow2 || Property 'image_id' | bb9318db-5554-4857-a309-268c6653b9ff || Property 'image_name' | image || Property 'min_disk' | 0 || Property 'min_ram' | 0 || Property 'root_device_name' | /dev/vda || Property 'size' | 13167616 || created_at | 2015-06-10T05:52:24 || deleted | False || id | e86cc562-349c-48cb-a81c-896584accde3 || is_public | False || min_disk | 0 || min_ram | 0 || name | vm10-snap || owner | 74c8ada23a3449f888d9e19b76d13aab || protected | False || size | 0 # 這里 size 是 0,表明該 image 只是元數(shù)據(jù), || status | active || updated_at | 2015-06-10T05:52:24 |+---------------------------------+----------------------------------------------------------------------------------+?5. 當(dāng)前 Nova snapshot 的局限
那為什么 Nova 不實(shí)現(xiàn)虛機(jī)的快照而只是系統(tǒng)盤的快照呢?據(jù)說,社區(qū)關(guān)于這個(gè)功能有過討論,討論的結(jié)果是不加入這個(gè)功能,原因主要有幾點(diǎn):
?這里?也有很多的討論。
- 磁盤數(shù)據(jù)的保存狀態(tài):
總結(jié)
以上是生活随笔為你收集整理的【KVM系列07】使用 libvirt 做 QEMU/KVM 快照和 Nova 实例的快照的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【KVM系列06】Nova 通过 lib
- 下一篇: 【KVM系列08】使用 libvirt