天天看點

KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)

學習 KVM 的系列文章:

<a href="http://www.cnblogs.com/sammyliu/p/4543110.html" target="_blank">(1)介紹和安裝</a>

<a href="http://www.cnblogs.com/sammyliu/p/4543597.html%20" target="_blank">(2)CPU 和 記憶體虛拟化</a>

<a href="http://www.cnblogs.com/sammyliu/p/4543657.html%20" target="_blank">(3)I/O QEMU 全虛拟化和準虛拟化(Para-virtulizaiton)</a>

<a href="http://www.cnblogs.com/sammyliu/p/4548194.html%20" target="_blank">(4)I/O PCI/PCIe裝置直接配置設定和 SR-IOV</a>

<a href="http://www.cnblogs.com/sammyliu/p/4558638.html%20" target="_blank">(5)libvirt 介紹</a>

<a href="http://www.cnblogs.com/sammyliu/p/4568188.html%20" target="_blank">(6)Nova 通過 libvirt 管理 QEMU/KVM 虛機</a>

<a href="http://www.cnblogs.com/sammyliu/p/4468757.html" target="_blank">(7)快照 (snapshot)</a>

<a href="http://www.cnblogs.com/sammyliu/p/4572287.html%20" target="_blank">(8)遷移 (migration)</a>

本文将梳理 QEMU/KVM 快照相關的知識,以及在 OpenStack Nova 中使用 libvirt 來對 QEMU/KVM 虛機做快照的過程。

QEMU/KVM 快照的定義:快照就是将虛機在某一個時間點上的磁盤、記憶體和裝置狀态儲存一下,以備将來之用。它包括以下幾類:

磁盤快照:磁盤的内容(可能是虛機的全部磁盤或者部分磁盤)在某個時間點上被儲存,然後可以被恢複。

磁盤資料的儲存狀态:

在一個運作着的系統上,一個磁盤快照很可能隻是崩潰一緻的(crash-consistent) 而不是完整一緻(clean)的,也是說它所儲存的磁盤狀态可能相當于機器突然掉電時硬碟資料的狀态,機器重新開機後需要通過 fsck 或者别的工具來恢複到完整一緻的狀态(類似于 Windows 機器在斷電後會執行檔案檢查)。(注:指令 qemu-img check -f qcow2 --output=qcow2 -r all filename-img.qcow2 可以對 qcow2 和 vid 格式的鏡像做一緻性檢查。)

對一個非運作中的虛機來說,如果上次虛機關閉的時候磁盤是完整一緻的,那麼其被快照的磁盤快照也将是完整一緻的。

磁盤快照有兩種:

内部快照 - 使用單個的 qcow2 的檔案來儲存快照和快照之後的改動。這種快照是 libvirt 的預設行為,現在的支援很完善(建立、復原和删除),但是隻能針對 qcow2 格式的磁盤鏡像檔案,而且其過程較慢等。

記憶體狀态(或者虛機狀态):隻是保持記憶體和虛機使用的其它資源的狀态。如果虛機狀态快照在做和恢複之間磁盤沒有被修改,那麼虛機将保持一個持續的狀态;如果被修改了,那麼很可能導緻資料corruption。

系統還原點(system checkpoint):虛機的所有磁盤的快照和記憶體狀态快照的集合,可用于恢複完整的系統狀态(類似于系統休眠)。

關于 崩潰一緻(crash-consistent)的附加說明:

應該盡量避免在虛機I/O繁忙的時候做快照。這種時候做快照不是可取的辦法。

vmware 的做法是裝一個 tools,它是個 PV driver,可以在做快照的時候挂起系統

快照還可以分為 live snapshot(熱快照)和 Clod snapshot:

Live snapshot:系統運作狀态下做的快照

Cold snapshot:系統停止狀态下的快照

libvit 做 snapshot 的各個 API:

snapshot

做快照的 libvirt API

從快照恢複的 libvirt API

virsh 指令

磁盤快照

virDomainSnapshotCreateXML(flags = <code>VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY</code> )

virDomainRevertToSnapshot

 virsh snapshot-create/snapshot-revert

記憶體(狀态)快照

virDomainSave

virDomainSaveFlags

virDomainManagedSave

virDomainRestore

virDomainRestoreFlags

virDomainCreate

virDomainCreateWithFlags

系統檢查點

virDomainSnapshotCreateXML

分别來看看這些 API 是如何工作的:

1. virDomainSnapshotCreateXML (virDomainPtr domain, const char * xmlDesc, unsigned int flags)

作用:根據 xmlDesc 指定的 snapshot xml 和 flags 來建立虛機的快照。

flags 包含

 虛機處于運作狀态時快照的做法

虛機處于關閉狀态時快照的做法

建立系統檢查點,包括磁盤狀态和記憶體狀态比如記憶體内容

保持關機時的磁盤狀态

VIR_DOMAIN_SNAPSHOT_CREATE_LIVE

做快照期間,虛機将不會被 paused。這會增加記憶體 dump file 的大小,但是可以減少系統停機時間。部分 Hypervisor 隻在做外部的系統檢查點時才設定該 flag,這意味着普通快照還是需要暫停虛機。

VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY

隻做指定磁盤的快照。對應運作着的虛機,磁盤快照可能是不完整的(類似于突然電源被拔了的情形)。

隻做指定磁盤的快照。

其内部實作根據虛機的運作狀态有兩種情形:

對運作着的虛機,API 使用 QEMU Monitor 去做快照,磁盤鏡像檔案必須是 qcow2 格式,虛機的 CPU 被停止,快照結束後會重新啟動。

對停止着的虛機,API 調用 qemu-img 方法來操作所有磁盤鏡像檔案。

KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)
KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)

2. virDomainSave 相關的幾個 API

這幾個API 功能都比較類似:

virDomainSave 

該方法會 suspend 一個運作着的虛機,然後儲存期記憶體内容到一個檔案中。成功調用以後,domain 将不會處于 running 狀态。使用 virDomainRestore 來恢複虛機。

virDomainSaveFlags 

virDomainManagedSave 

也類似于 virDomainSave API。主要差別是 libvirt 将其記憶體儲存到一個受 libvirt 管理的檔案中,是以libvirt 可以一直跟蹤 snapshot 的狀态;當調用 virDomainCreate/virDomainCreateWithFlags 方法重新開機該 domain的時候,libvirt 會使用該受管檔案,而不是一個空白的檔案,這樣就可以 restore 該snapshot。

對運作中的 domain d-2 運作 “virsh save” 指令。指令執行完成後,d-2 變成 “shut off” 狀态。

KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)

看看 domain 的磁盤鏡像檔案和 snapshot 檔案:

KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)

記憶體資料被儲存到 raw 格式的檔案中。

要恢複的時候,可以運作 “vish restore d-2.snap1” 指令從儲存的檔案上恢複。

先看看它的用法:

KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)
KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)

(1)預設的話,該指令建立虛機的所有磁盤和記憶體做内部快照,建立快照時虛機處于 paused 狀态,快照完成後變為 running 狀态。持續時間較長。

KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)
KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)
KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)

每個磁盤的鏡像檔案都包含了 snapshot 的資訊:

KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)
KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)

你可以運作 snapshot-revert 指令復原到指定的snapshot。

(2)可以使用 “--memspec” 和 “--diskspec” 參數來給記憶體和磁盤外部快照。這時候,在擷取記憶體狀态之前需要 Pause 虛機,就會産生服務的 downtime。

KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)
KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)

(3)可以使用 “--disk-only” 參數,這時會做所有磁盤的外部快照,但是不包含記憶體的快照。不指定快照檔案名字的話,會放在原來的磁盤檔案所在的目錄中。多次快照後,會形成一個外部快照鍊,新的快照使用前一個快照的鏡像檔案作為 backing file。

KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)
KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)

而第一個外部快照的鏡像檔案是以虛機的原始鏡像檔案作為 backing file 的:

KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)
KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)

[root@rh65 osdomains]# virsh snapshot-revert d-2 1434467974

error: unsupported configuration: revert to external disk snapshot not supported yet

(4)還可以使用 “--live” 參數建立系統還原點,包括磁盤、記憶體和裝置狀态等。使用這個參數時,虛機不會被 Paused(那怎麼實作的?)。其後果是增加了記憶體 dump 檔案的大小,但是減少了系統的 downtime。該參數隻能用于做外部的系統還原點(external checkpoint)。

KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)
KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)

注意到加 “--live” 生成的快照和不加這個參數生成的快照不會被鍊在一起:

KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)
KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)

不過,奇怪的是,使用 QEMU 2.3 的情況下,即使加了 --live 參數,虛機還是會被短暫的 Paused 住:

KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)
KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)

綜上所述,對于 snapshot-create-as 指令來說,

參數

結果

&lt;不使用額外的參數&gt;

所有磁盤和記憶體的内部的内部快照

磁盤和記憶體的外部快照,虛機需要被暫停

--live  --memspec snapshot=external --diskspec vda,snapshot=external

建立系統檢查點(包括磁盤和記憶體的快照),而且虛機不會被暫停(?測試結果顯示還是會暫停,隻是暫停時間比不使用 --live 要短一些)

--disk-only

建立所有或者部分磁盤的外部快照

 可以使用 sanpshot-revert 指令來復原到指定的系統還原點,不過得使用 “-force” 參數:

KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)
KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)

 OpenStack Snapshot 可分為下面的幾種情形:

(1)對從鏡像檔案啟動的虛機做快照

隻将運作當中的虛機的 Root disk (第一個vd 或者 hd disk) 做成 image,然後上傳到 glance 裡面

Cold Snapshot:對不能做 live snapshot 的虛機做 Cold snapshot。這種快照必須首先 Pause 虛機。

(2)對從卷啟動的虛機做快照

對虛機的每個挂載的 volume 調用 cinder API 做 snapshot。

Snapshot 出的 metadata 會儲存到 glance 裡面,但是不會有 snapshot 的 image 上傳到 Glance 裡面。

這個 snapshot 也會出現在 cinder 的資料庫裡面,對 cinder API 可見。

調用 cinder driver api,對 backend 中的 volume 進行 snapshot。

這個 snapshot 會出現在 cinder 的資料庫裡面,對 cinder API 可見。  

    嚴格地說,Nova 虛機的快照,并不是對虛機做完整的快照,而是對虛機的啟動盤(root disk,即 vda 或者 hda)做快照生成 qcow2 格式的檔案,并将其傳到 Glance 中,其作用也往往是友善使用快照生成的鏡像來部署新的虛機。Nova 快照分為 Live Snapshot (不停機快照)和 Clold Snapshot (停機快照)。

找到虛機的 root disk (vda 或者 hda)。

在 CONF.libvirt.snapshots_directory 指定的檔案夾(預設為 /var/lib/nova/instances/snapshots)中建立一個臨時檔案夾,在其中建立一個 qcow2 格式的 delta 檔案,其檔案名為 uuid 字元串,該檔案的 backing file 和 root disk 檔案的 backing file 相同 (下面步驟 a)。

調用 virDomainGetXMLDesc 來儲存 domain 的 xml 配置。

調用 virDomainBlockJobAbort 來停止對 root disk 的活動塊操作 (Cancel the active block job on the given disk)。

調用 virDomainUndefine 來将 domain 變為 transimit 類型的,這是因為 BlockRebase API 不能針對 Persistent domain 調用。

調用 virDomainBlockRebase 來将 root disk image 檔案中不同的資料拷貝到 delta disk file 中。(下面步驟 b)

步驟 6 是一個持續的過程,因為可能有應用正在向該磁盤寫資料。Nova 每隔 0.5 秒調用 virDomainBlockJobInfo API 來檢查拷貝是否結束。

拷貝結束後,調用  virDomainBlockJobAbort 來終止資料拷貝。

調用 virDomainDefineXML 将domain 由 transimisit 該回到 persistent。

調用 qemu-img convert 指令将 delta image 檔案和 backing file 變為一個 qcow2 檔案 (下面步驟 c)

将 image 的中繼資料和 qcow2 檔案傳到 Glance 中。

KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)
KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)

來看看其中的一個關鍵 API int virDomainBlockRebase (virDomainPtr dom, const char * disk, const char * base, unsigned long bandwidth,unsigned int flags)

簡單的示意圖:

KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)

當虛機不在運作中時或者不滿足 live snapshot 的條件的情況下,Nova 會執行 Cold snapshot。其主要過程如下:

(1)當虛機處于 running 或者 paused 狀态時:

detach PCI devices

detach SR-IOV devices

調用 virDomainManagedSave API 來将虛機 suspend 并且将記憶體狀态儲存到磁盤檔案中。

(2)調用 qemu-img convert 指令将 root disk 的鏡像檔案轉化一個相同格式的鏡像檔案。

(3)調用 virDomainCreateWithFlags  API 将虛機變為初始狀态

(4)将在步驟1 中解除安裝的 PCI 和 SR-IOV 裝置重新挂載回來

(5)将中繼資料和 qcow2 檔案傳到 Glance 中

(0)從卷啟動虛機,并且再挂載一個卷,然後運作 nova image-create 指令。

(1)從 DB 擷取該虛機的塊裝置( Block Devices Mapping)清單。

(2)對該清單中的每一個卷,依次調用 Cinder API 做快照。對 LVM Driver 的 volume 來說,執行的指令類似于 " lvcreate --size 100M --snapshot --name snap /dev/vg00/lvol1“。

KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)
KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)

(3)将快照的 metadata 放到 Glance 中。(注:該 image 隻是一些屬性的集合,比如 block device mapping, kernel 和 ramdisk IDs 等,它并沒有 image 資料, 是以其 size 為 0。)

KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)
KVM 介紹(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 執行個體的快照 (Nova Instances Snapshot Libvirt)

Nova snapshot 其實隻是提供一種創造系統盤鏡像的方法。不支援復原至快照點,隻能采用該快照鏡像建立一個新的虛拟機。

在虛機是從 image boot 的時候,隻對系統盤進行快照,不支援記憶體快照,不支援系統還原點 (blueprint:https://blueprints.launchpad.net/nova/+spec/live-snapshot-vms)

隻支援虛拟機内置(全量)快照,不支援外置(增量)快照。這與目前快照的實作方式有關,因為是通過 image 進行儲存的。

從 image boot 的虛機的快照以 Image 方式儲存到 Glance 中,而非以 Cinder 卷方式儲存。

過程較長(需要先通過存儲快照,然後抽取并上傳至 Glance),網絡開銷大。

那為什麼 Nova 不實作虛機的快照而隻是系統盤的快照呢?據說,社群關于這個功能有過讨論,讨論的結果是不加入這個功能,原因主要有幾點:

這應該是一種虛拟化技術的功能,不是雲計算平台的功能。

openstack 由于底層要支援多種虛拟化的技術,某些虛拟化技術實作這種功能比較困難。

建立的 VM state snapshot 會面臨 cpu feature 不相容的問題。

目前 libvirt 對 QEMU/KVM 虛機的外部快照的支援還不完善,即使更新到最新的 libvirt 版本,造成相容性比較差。

    本文轉自SammyLiu部落格園部落格,原文連結:http://www.cnblogs.com/sammyliu/p/4468757.html,如需轉載請自行聯系原作者

繼續閱讀