本文系轉載,如需再次轉載,請注明原出處,尊重知識勞動;原位址
淺析snapshots, blockcommit,blockpull
作者:Kashyap Chamarthy <kchamart#redhat.com>
Date: Tue, 23 Oct 2012 15:28:06 +0530
這是一篇關于snapshots, blockpull, blockcommit的的介紹.作者和with Eric Blake, Jeff Cody,
Kevin Wolf以及很多IRC和mailing lists裡面的同學大量讨論以及作者大量的特向測試的基礎之上
總結出來的
作者也正在準備寫一些關于blockcopy部分的文檔,但這要等他完成blockcopy的測試之後.
作者歡迎評論歡迎拍磚.(我表示也歡迎)
- ---
- docs/snapshots-blockcommit-blockpull.rst
- ..--------------------------------------------------------------
-
注意: 所有測試都是在最新的 qemu-git,libvirt-git (as of
20-Oct-2012 在 Fedora-18 alpha系統上倒騰出來的
基礎知識
一個虛拟機快照可被看作是虛拟機的在某個指定時間的視圖(包括他的作業系統和所有的程式).
據此,某可以還原到一個之前的完整的狀态,或者在guest運作的時候做個備份.是以,在我們
繼續深入之前我們必須搞懂兩個名詞:backing files和overlays .
QCOW2 backing files 與 overlays
qcow2(qemu copy-on-write)具有建立一個base-p_w_picpath,以及在base-p_w_picpath(即backing file)
的基礎上建立多個copy-on-write overlays鏡像的能力.backing files和overlays十分有用,
可以迅速的建立瘦裝備虛拟機的執行個體,特别是在開發測試的時候可以讓你迅速的復原到之前的某個
已知狀态,丢棄overlay.
Figure-1
.--------------. .-------------. .-------------. .-------------.
| | | | | | | |
| RootBase |<---| Overlay-1 |<---| Overlay-1A <--- | Overlay-1B |
| (raw/qcow2) | | (qcow2) | | (qcow2) | | (qcow2) |
'--------------' '-------------' '-------------' '-------------'
上圖表明rootbase是overlay-1的backing file,以此類推.
Figure-2
.-----------. .-----------. .------------. .------------. .------------.
| | | | | | | | | |
| RootBase |<--- Overlay-1 |<--- Overlay-1A <--- Overlay-1B <--- Overlay-1C |
| | | | | | | | | (Active) |
'-----------' '-----------' '------------' '------------' '------------'
^ ^
| |
| | .-----------. .------------.
| | | | | |
| '-------| Overlay-2 |<---| Overlay-2A |
| | | | (Active) |
| '-----------' '------------'
|
|
| .-----------. .------------.
| | | | |
'------------| Overlay-3 |<---| Overlay-3A |
| | | (Active) |
'-----------' '------------'
上圖表明我們可以隻用單個backing file來建立多條鍊.
注意 : backing file 總是 隻讀 打開的. 換言之, 一旦新快照被建立,
他的後端檔案就不能被修改,(快照依賴于後端檔案的這種狀态).
了解更多參見後面的('blockcommit' 節) .
示例 :
[FedoraBase.img] ----- <- [Fed-guest-1.qcow2] <- [Fed-w-updates.qcow2] <- [Fedora-guest-with-updates-1A]
\
\--- <- [Fed-guest-2.qcow2] <- [Fed-w-updates.qcow2] <- [Fedora-guest-with-updates-2A]
(注意箭頭的方向,Fed-w-updates.qcow2 的backing file是 Fed-guest-1.qcow2)
上面的示例中可以看到 FedoraBase.img 安裝了一個fedora17系統,并作為我們的backing file.
現在這個backing file将作為模闆快速的建立兩個瘦裝備執行個體,和 Figure-2 道理是一樣的.
使用qemu-img為單個backing file來建立兩個fedora的瘦裝備克隆:# qemu-img create -b /export/vmp_w_picpaths/RootBase.img -f qcow2 \ /export/vmp_w_picpaths/Fedora-guest-1.qcow2 # qemu-img create -b /export/vmp_w_picpaths/RootBase.img -f qcow2 \ /export/vmp_w_picpaths/Fedora-guest-2.qcow2
現在,上面建立出來的兩個鏡像 Fedora-guest-1 & Fedora-guest-2 都可以用來
啟動一個虛拟機,繼續我們的示例,現在我們需要建立一個f17的執行個體,但是這次我們需要
建立的是具有完整的更新的執行個體,這時可以建立另外一個overlay(Fedora-guest-with-updates-1A)
而這個overlay的backing file是'Fed-w-updates.qcow2'(一個包含了完整更新的鏡像):
我們可以使用qemu-img指令來檢視鏡像的資訊,包括虛拟磁盤大小,使用大小,backing file指向:# qemu-img create -b /export/vmp_w_picpaths/Fed-w-updates.qcow2 -f qcow2 \ /export/vmp_w_picpaths/Fedora-guest-with-updates-1A.qcow2
注意: 最新版本的qemu-img可以遞歸查詢到整條完整的鍊:# qemu-img info /export/vmp_w_picpaths/Fedora-guest-with-updates-1A.qcow2
# qemu-img info --backing-chain /export/vmp_w_picpaths/Fedora-guest-with-updates-1A.qcow2
名詞解釋Snapshot:
- 内置快照(Internal Snapshots) -- 單個qcow2鏡像檔案存儲了包括資料以及快照的狀态資訊,
内置快照又可以細分一下:-
- Libvirt 使用'savevm' 指令來建立這種快照
- Libvirt 使用 'qemu-img' 指令建立關機狀态的磁盤快照.
- Libvirt 使用 'savevm' 指令建立運作狀态的磁盤快照.
内置磁盤快照(Internal disk snapshot):
快照點的磁盤狀态,資料和快照儲存在單個qcow2檔案中,虛拟機運作狀态和關閉狀态都
可以建立.
内置系統還原點(Internal system checkpoint):
記憶體狀态,裝置狀态和磁盤狀态,可以為運作中的虛拟機建立,所有資訊都存儲在
同一個qcow2檔案中,隻有在運作狀态才能建立内置系統還原點.
外置快照(External Snapshots) -- 當一個快照被建立時,建立時目前的狀态儲存在目前使用
的磁盤檔案中,即成為一個backing file.
此時一個新的overlay被建立出來儲存往後的資料.
這個也可以細分一下:-
- Libvirt 使用 'transaction' 指令來為運作狀态建立這種快照.
- Libvirt 使用'qemu-img' 指令為關閉狀态建立這種快照(截止目前功能還在開發中).
外置磁盤快照(External disk snapshot):
磁盤的快照被儲存在一個檔案中,建立時間點以後的資料被記錄到一個新的qcow2檔案中.
同樣可以在運作和關閉狀态建立.
外置系統還原點(External system checkpoint):
虛拟機的磁盤狀态将被儲存到一個檔案中,記憶體和裝置的狀态将被儲存到另外一個新的檔案中,
(這個功能也還在開發中).
VM狀态(VM state):
儲存運作狀态虛拟機的記憶體裝置狀态資訊至檔案,可以通過此檔案恢複到儲存時的狀态,有點類似系統
的休眠.(注意建立VM狀态儲存的時候VM磁盤必須是未發生寫入改動的)
- Libvirt使用 'migrate' (to file)指令來完成VM狀态轉儲.
建立snapshots
- 每次産生一個外置snapshot,一個 /new/ overlay 鏡像就會随之生成,而前一個鏡像就變成了一個快照.
- diskonly内置快照建立
disk-only外置快照建立 :
- 假如需要為名為'f17vm1'的虛拟機建立一個運作态或關閉态的内置快照snap1
# virsh snapshot-create-as f17vm1 snap1 snap1-desc
- 列出快照清單,使用*qemu-img*檢視info
# virsh snapshot-list f17vm1 # qemu-img info /home/kashyap/vmp_w_picpaths/f17vm1.qcow2
- 檢視虛拟機磁盤清單
# virsh domblklist f17-base Target Source --------------------------------------------- vda /export/vmp_w_picpaths/f17-base.qcow2 #
- 建立外置disk-only磁盤快照(VM*運作态*):
# virsh snapshot-create-as --domain f17-base snap1 snap1-desc \ --disk-only --diskspec vda,snapshot=external,file=/export/vmp_w_picpaths/sn1-of-f17-base.qcow2 \ --atomic Domain snapshot snap1 created # * 一旦上面的指令被執行,則原來的鏡像f17-base将變為backing file,一個新的鏡像被建立.
- 現在再清單檢視虛拟機磁盤,你會發現新産生的鏡像已經投入使用.
# virsh domblklist f17-base Target Source ---------------------------------------------------- vda /export/vmp_w_picpaths/sn1-of-f17-base.qcow2 #
快照復原
截止寫此文之時,復原至'内置快照'(system checkpoint或disk-only)是可以使用的.
虛拟機f17vm1復原至快照'snap1'# virsh snapshot-revert --domain f17vm1 snap1
使用 snapshot-revert 復原 '外置磁盤快照' 稍微複雜些,需要涉及到稍微複雜點的問題,
需要考慮的是合并'base'至'top'還是合并'top'至'base'.
也就是說,有兩種方式可以選擇,外置磁盤快照鍊的縮短可以使用 blockpull 或 blockcommit .
截止目前上遊社群仍然在努力完善這項功能.
合并快照檔案
外置快照非常有用,但這裡有一個問題就是如何合并快照檔案來縮短鍊的長度,如上所述這裡
有兩種方式:
- blockcommit: 從 top 合并資料到 base (即合并overlays至backing files).
- blockpull: 将backing file資料合并至overlay中.從 base 到 top .
blockcommit
blockcommit可以讓你将'top'鏡像(在同一條backing file鍊中)合并至底層的'base'鏡像.
一旦 blockcommit 執行完成,處于最上面的overlay鍊關系将被指向到底層的overlay或base.
這在建立了很長一條鍊之後用來縮短鍊長度的時候十分有用.
下面來個圖說明下:
我們現在有一個鏡像叫'RootBase',擁有4個外置快照,'Active'為目前VM寫入資料的,
使用'blockcommit'可以有以下多種case :
注: 合并'Active'層(最頂部的overlay)至backing_files的功能還在開發中.
- 合并Snap-1, Snap-2 and Snap-3 至 'RootBase'
- 隻合并Snap-1 and Snap-2 至 RootBase
- 隻合并Snap-1 至 RootBase
- 合并Snap-2 至 Snap-1
- 合并Snap-3 至 Snap-2
- 合并Snap-2 和 Snap-3 至 Snap-1
(下圖解釋case (6))
Figure-3
.------------. .------------. .------------. .------------. .------------.
| | | | | | | | | |
| RootBase <--- Snap-1 <--- Snap-2 <--- Snap-3 <--- Snap-4 |
| | | | | | | | | (Active) |
'------------' '------------' '------------' '------------' '------------'
/ |
/ |
/ commit data |
/ |
/ |
/ |
v commit data |
.------------. .------------. <--------------------' .------------.
| | | | | |
| RootBase <--- Snap-1 |<---------------------------------| Snap-4 |
| | | | Backing File | (Active) |
'------------' '------------' '------------'
舉個例子,有以下場景:
目前: [base] <- sn1 <- sn2 <- sn3 <- sn4(this is active)
目标: [base] <- sn1 <- sn4 (如此來丢棄sn2,sn3)
下面有兩種方式,method-a更快,method-b 慢些,但是sn2有效可用. (VM運作态).
(method-a):
# virsh blockcommit --domain f17 vda --base /export/vmp_w_picpaths/sn1.qcow2 \
--top /export/vmp_w_picpaths/sn3.qcow2 --wait --verbose
[OR]
- (method-b):
-
# virsh blockcommit --domain f17 vda --base /export/vmp_w_picpaths/sn2.qcow2 \
--top /export/vmp_w_picpaths/sn3.qcow2 --wait --verbose # virsh blockcommit --domain f17 vda --base /export/vmp_w_picpaths/sn1.qcow2 \
--top /export/vmp_w_picpaths/sn2.qcow2 --wait --verbose
注: 如果手工執行*qemu-img*指令完成的話, 現在還隻能用method-b.
Figure-4
.------------. .------------. .------------. .------------. .------------.
| | | | | | | | | |
| RootBase <--- Snap-1 <--- Snap-2 <--- Snap-3 <--- Snap-4 |
| | | | | | | | | (Active) |
'------------' '------------' '------------' '------------' '------------'
/ | |
/ | |
/ | |
commit data / commit data | |
/ | |
/ | commit data |
v | |
.------------.<----------------------|-------------' .------------.
| |<----------------------' | |
| RootBase | | Snap-4 |
| |<-------------------------------------------------| (Active) |
'------------' Backing File '------------'
上圖示範了case1的blockcommit走向,現在sn4的backing file指向rootbase.
blockpull
blockpull(qemu中也稱作'block stream')可以将backing合并至active,與blockcommit正好相反.
截止目前隻能将backing file合并至目前使用的active中,也就是說還不支援指定top的合并.
設想一個下面的場景:
Figure-5
.------------. .------------. .------------. .------------. .------------.
| | | | | | | | | |
| RootBase <--- Snap-1 <--- Snap-2 <--- Snap-3 <--- Snap-4 |
| | | | | | | | | (Active) |
'------------' '------------' '------------' '------------' '------------'
| | \
| | \
| | \
| | \ stream data
| | stream data \
| stream data | \
| | v
.------------. | '---------------> .------------.
| | '---------------------------------> | |
| RootBase | | Snap-4 |
| | <---------------------------------------- | (Active) |
'------------' Backing File '------------'
使用blockpull我們可以将snap-1/2/3中的資料合并至active層,最終rootbase将變成active的直接後端.
指令如下:
後續的工作是我們需要使用virsh來清理掉不用的快照
- 假設快照已經使用 建立Snapshots 小節中的方式完成:
- 如*Figure-5*中描述的-- [RootBase] <- [Active].
# virsh blockpull --domain RootBase \ --path /var/lib/libvirt/p_w_picpaths/active.qcow2 \ --base /var/lib/libvirt/p_w_picpaths/RootBase.qcow2 \ --wait --verbose
# virsh snapshot-delete --domain RootBase Snap-3 --metadata # virsh snapshot-delete --domain RootBase Snap-2 --metadata # virsh snapshot-delete --domain RootBase Snap-1 --metadata
Figure-6
.------------. .------------. .------------. .------------. .------------.
| | | | | | | | | |
| RootBase <--- Snap-1 <--- Snap-2 <--- Snap-3 <--- Snap-4 |
| | | | | | | | | (Active) |
'------------' '------------' '------------' '------------' '------------'
| | | \
| | | \
| | | \ stream data
| | | stream data \
| | | \
| | stream data | \
| stream data | '------------------> v
| | .--------------.
| '---------------------------------> | |
| | Snap-4 |
'----------------------------------------------------> | (Active) |
'--------------'
'Standalone'
(w/o backing
file)
上圖表示的是将所有backing file全部合并至active
如下執行指令:
(1) 在我們執行合并 *之前* 檢視一下快照的大小(注意觀察'Active'):
::
# ls -lash /var/lib/libvirt/p_w_picpaths/RootBase.img
608M -rw-r--r--. 1 qemu qemu 1.0G Oct 11 17:54 /var/lib/libvirt/p_w_picpaths/RootBase.img
# ls -lash /var/lib/libvirt/p_w_picpaths/*Snap*
840K -rw-------. 1 qemu qemu 896K Oct 11 17:56 /var/lib/libvirt/p_w_picpaths/Snap-1.qcow2
392K -rw-------. 1 qemu qemu 448K Oct 11 17:56 /var/lib/libvirt/p_w_picpaths/Snap-2.qcow2
456K -rw-------. 1 qemu qemu 512K Oct 11 17:56 /var/lib/libvirt/p_w_picpaths/Snap-3.qcow2
2.9M -rw-------. 1 qemu qemu 3.0M Oct 11 18:10 /var/lib/libvirt/p_w_picpaths/Active.qcow2
(2) 單獨檢查下 'Active' 所指向的backing file ::
# qemu-img info /var/lib/libvirt/p_w_picpaths/Active.qcow2
p_w_picpath: /var/lib/libvirt/p_w_picpaths/Active.qcow2
file format: qcow2
virtual size: 1.0G (1073741824 bytes)
disk size: 2.9M
cluster_size: 65536
backing file: /var/lib/libvirt/p_w_picpaths/Snap-3.qcow2
(3) 開始 **blockpull** 操作.
::
# virsh blockpull --domain ptest2-base --path /var/lib/libvirt/p_w_picpaths/Active.qcow2 --wait --verbose
Block Pull: [100 %]
Pull complete
(4) 再檢查下快照大小, 'Active'變得很大
::
# ls -lash /var/lib/libvirt/p_w_picpaths/*Snap*
840K -rw-------. 1 qemu qemu 896K Oct 11 17:56 /var/lib/libvirt/p_w_picpaths/Snap-1.qcow2
392K -rw-------. 1 qemu qemu 448K Oct 11 17:56 /var/lib/libvirt/p_w_picpaths/Snap-2.qcow2
456K -rw-------. 1 qemu qemu 512K Oct 11 17:56 /var/lib/libvirt/p_w_picpaths/Snap-3.qcow2
1011M -rw-------. 1 qemu qemu 3.0M Oct 11 18:29 /var/lib/libvirt/p_w_picpaths/Active.qcow2
(5) 檢查'Active'資訊,現在它已經不需要backing file了,正如*Figure-6*所示::
# qemu-img info /var/lib/libvirt/p_w_picpaths/Active.qcow2
p_w_picpath: /var/lib/libvirt/p_w_picpaths/Active.qcow2
file format: qcow2
virtual size: 1.0G (1073741824 bytes)
disk size: 1.0G
cluster_size: 65536
(6) 清理現場
::
# virsh snapshot-delete --domain RootBase Snap-3 --metadata
(7) 現在還可以使用下 guestfish **READ-ONLY** 模式來檢查下磁盤内容( *--ro* 選項)
::
# guestfish --ro -i -a /var/lib/libvirt/p_w_picpaths/Active.qcow2
快照删除 (and 'offline commit')
- 删除(live/offline)狀态的*内置快照*很友善 ::
-
# virsh snapshot-delete --domain f17vm --snapshotname snap6
# virsh snapshot-delete f17vm snap6
libvirt現在還沒有删除外置快照的功能,但是可以使用*qemu-img*指令來完成.
比如我們有這樣一條鍊(VM*offline*狀态): base <- sn1 <- sn2 <- sn3
現在删除第二個快照(sn2).有兩種方式:
- Method (1): base <- sn1 <- sn3 (by copying sn2 into sn1)
- Method (2): base <- sn1 <- sn3 (by copying sn2 into sn3)
Method (1)
(by copying sn2 into sn1)
注意: 必須保證sn1沒有被其他快照作為後端,不然就挂了!!
- offline commit
# qemu-img commit sn2.qcow2
現在把sn3的後端指向到sn1.
- 将會*commit*所有在sn2中的改動到sn2的backing file(sn1).
- qemu-img commit和virsh blockcommit類似
# qemu-img rebase -u -b sn1.qcow2 sn3.qcow2
現在可以直接删除sn2
- 注意: -u代表'Unsafe mode' -- 此模式下僅僅修改了指向到的backing file名字,必須謹慎操作.
# rm sn2.qcow2
Method (2)
(by copying sn2 into sn3)
- 合并資料,rebase後端:
backingfile(sn1)到舊的backingfile(sn2)之間發生的差異改動都将被合并到sn3中.# qemu-img rebase -b sn1.qcow2 sn3.qcow2
現在可以删除sn2了
- 未使用-u模式的rebase将把資料也一并合并過去,即sn2的資料寫入到sn3.
- 換言之: 這裡使用的'Safe mode',也是預設模式 --對sn3而言任何從
- qemu-img rebase(沒有-u)和和virsh blockpull類似.
# rm sn2.qcow2