天天看點

kvm+libvirt虛拟機快照淺析 淺析snapshots, blockcommit,blockpull 基礎知識 建立snapshots 快照復原 合并快照檔案 快照删除 (and 'offline commit')

from:   http://itxx.sinaapp.com/blog/content/130

Create time:01/27/2013 11:43   degree:6549   comments: 0

淺析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-image,以及在base-image(即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/vmimages/RootBase.img -f qcow2 \
  /export/vmimages/Fedora-guest-1.qcow2

# qemu-img create -b /export/vmimages/RootBase.img -f qcow2 \
  /export/vmimages/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 create -b /export/vmimages/Fed-w-updates.qcow2 -f qcow2 \
   /export/vmimages/Fedora-guest-with-updates-1A.qcow2
      
我們可以使用qemu-img指令來檢視鏡像的資訊,包括虛拟磁盤大小,使用大小,backing file指向:
# qemu-img info /export/vmimages/Fedora-guest-with-updates-1A.qcow2
      
注意: 最新版本的qemu-img可以遞歸查詢到整條完整的鍊:
# qemu-img info --backing-chain /export/vmimages/Fedora-guest-with-updates-1A.qcow2
      

名詞解釋Snapshot:

  • 内置快照(Internal Snapshots) -- 單個qcow2鏡像檔案存儲了包括資料以及快照的狀态資訊,
    内置快照又可以細分一下:-
    1. 内置磁盤快照(Internal disk snapshot):

      快照點的磁盤狀态,資料和快照儲存在單個qcow2檔案中,虛拟機運作狀态和關閉狀态都

      可以建立.

      • Libvirt 使用 'qemu-img' 指令建立關機狀态的磁盤快照.
      • Libvirt 使用 'savevm' 指令建立運作狀态的磁盤快照.
    2. 内置系統還原點(Internal system checkpoint):

      記憶體狀态,裝置狀态和磁盤狀态,可以為運作中的虛拟機建立,所有資訊都存儲在

      同一個qcow2檔案中,隻有在運作狀态才能建立内置系統還原點.

      • Libvirt 使用'savevm' 指令來建立這種快照
  • 外置快照(External Snapshots) -- 當一個快照被建立時,建立時目前的狀态儲存在目前使用

    的磁盤檔案中,即成為一個backing file.

    此時一個新的overlay被建立出來儲存往後的資料.

    這個也可以細分一下:-

    1. 外置磁盤快照(External disk snapshot):

      磁盤的快照被儲存在一個檔案中,建立時間點以後的資料被記錄到一個新的qcow2檔案中.

      同樣可以在運作和關閉狀态建立.

      • Libvirt 使用 'transaction' 指令來為運作狀态建立這種快照.
      • Libvirt 使用'qemu-img' 指令為關閉狀态建立這種快照(截止目前功能還在開發中).
    2. 外置系統還原點(External system checkpoint):

      虛拟機的磁盤狀态将被儲存到一個檔案中,記憶體和裝置的狀态将被儲存到另外一個新的檔案中,

      (這個功能也還在開發中).

  • VM狀态(VM state):

    儲存運作狀态虛拟機的記憶體裝置狀态資訊至檔案,可以通過此檔案恢複到儲存時的狀态,有點類似系統

    的休眠.(注意建立VM狀态儲存的時候VM磁盤必須是未發生寫入改動的)

    • Libvirt使用 'migrate' (to file)指令來完成VM狀态轉儲.

建立snapshots

  • 每次産生一個外置snapshot,一個 /new/ overlay 鏡像就會随之生成,而前一個鏡像就變成了一個快照.
  • diskonly内置快照建立
    1. 假如需要為名為'f17vm1'的虛拟機建立一個運作态或關閉态的内置快照snap1
      # virsh snapshot-create-as f17vm1  snap1 snap1-desc
            
    2. 列出快照清單,使用*qemu-img*檢視info
      # virsh snapshot-list f17vm1
      # qemu-img info /home/kashyap/vmimages/f17vm1.qcow2
            
  • disk-only外置快照建立 :
    1. 檢視虛拟機磁盤清單
      # virsh domblklist f17-base
      Target     Source
      ---------------------------------------------
      vda        /export/vmimages/f17-base.qcow2
      
      #
            
    2. 建立外置disk-only磁盤快照(VM*運作态*):
      # virsh snapshot-create-as --domain f17-base snap1 snap1-desc \
      --disk-only --diskspec vda,snapshot=external,file=/export/vmimages/sn1-of-f17-base.qcow2 \
      --atomic
      Domain snapshot snap1 created
      #
      
          * 一旦上面的指令被執行,則原來的鏡像f17-base将變為backing file,一個新的鏡像被建立.
            
    3. 現在再清單檢視虛拟機磁盤,你會發現新産生的鏡像已經投入使用.
      # virsh domblklist f17-base
      Target     Source
      ----------------------------------------------------
      vda        /export/vmimages/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 :

  1. 合并Snap-1, Snap-2 and Snap-3 至 'RootBase'
  2. 隻合并Snap-1 and Snap-2 至 RootBase
  3. 隻合并Snap-1 至 RootBase
  4. 合并Snap-2 至 Snap-1
  5. 合并Snap-3 至 Snap-2
  6. 合并Snap-2 和 Snap-3 至 Snap-1
注: 合并'Active'層(最頂部的overlay)至backing_files的功能還在開發中.

(下圖解釋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/vmimages/sn1.qcow2  \

               --top /export/vmimages/sn3.qcow2 --wait --verbose

[OR]

            (method-b):
# virsh blockcommit --domain f17 vda  --base /export/vmimages/sn2.qcow2  \      
--top /export/vmimages/sn3.qcow2 --wait --verbose
# virsh blockcommit --domain f17 vda  --base /export/vmimages/sn1.qcow2  \      
--top /export/vmimages/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的直接後端.

指令如下:

  1. 假設快照已經使用 建立Snapshots 小節中的方式完成:
  2. 如*Figure-5*中描述的-- [RootBase] <- [Active].
    # virsh blockpull --domain RootBase  \
      --path /var/lib/libvirt/images/active.qcow2  \
      --base /var/lib/libvirt/images/RootBase.qcow2  \
      --wait --verbose
          
後續的工作是我們需要使用virsh來清理掉不用的快照
# 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/images/RootBase.img
        608M -rw-r--r--. 1 qemu qemu 1.0G Oct 11 17:54 /var/lib/libvirt/images/RootBase.img

        # ls -lash /var/lib/libvirt/images/*Snap*
        840K -rw-------. 1 qemu qemu 896K Oct 11 17:56 /var/lib/libvirt/images/Snap-1.qcow2
        392K -rw-------. 1 qemu qemu 448K Oct 11 17:56 /var/lib/libvirt/images/Snap-2.qcow2
        456K -rw-------. 1 qemu qemu 512K Oct 11 17:56 /var/lib/libvirt/images/Snap-3.qcow2
        2.9M -rw-------. 1 qemu qemu 3.0M Oct 11 18:10 /var/lib/libvirt/images/Active.qcow2

(2) 單獨檢查下 'Active' 所指向的backing file ::

        # qemu-img info /var/lib/libvirt/images/Active.qcow2
        image: /var/lib/libvirt/images/Active.qcow2
        file format: qcow2
        virtual size: 1.0G (1073741824 bytes)
        disk size: 2.9M
        cluster_size: 65536
        backing file: /var/lib/libvirt/images/Snap-3.qcow2

(3) 開始 **blockpull** 操作.
    ::

        # virsh blockpull --domain ptest2-base --path /var/lib/libvirt/images/Active.qcow2 --wait --verbose
        Block Pull: [100 %]
        Pull complete

(4) 再檢查下快照大小, 'Active'變得很大
    ::

        # ls -lash /var/lib/libvirt/images/*Snap*
         840K -rw-------. 1 qemu qemu 896K Oct 11 17:56 /var/lib/libvirt/images/Snap-1.qcow2
         392K -rw-------. 1 qemu qemu 448K Oct 11 17:56 /var/lib/libvirt/images/Snap-2.qcow2
         456K -rw-------. 1 qemu qemu 512K Oct 11 17:56 /var/lib/libvirt/images/Snap-3.qcow2
        1011M -rw-------. 1 qemu qemu 3.0M Oct 11 18:29 /var/lib/libvirt/images/Active.qcow2


(5) 檢查'Active'資訊,現在它已經不需要backing file了,正如*Figure-6*所示::

        # qemu-img info /var/lib/libvirt/images/Active.qcow2
        image: /var/lib/libvirt/images/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/images/Active.qcow2
      

快照删除 (and 'offline commit')

删除(live/offline)狀态的*内置快照*很友善 ::

# virsh snapshot-delete --domain f17vm --snapshotname snap6

[OR]

# 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沒有被其他快照作為後端,不然就挂了!!

  1. offline commit
    # qemu-img commit sn2.qcow2      
    • 将會*commit*所有在sn2中的改動到sn2的backing file(sn1).
    • qemu-img commit和virsh blockcommit類似
  2. 現在把sn3的後端指向到sn1.
    # qemu-img rebase -u -b sn1.qcow2 sn3.qcow2
          
    • 注意: -u代表'Unsafe mode' -- 此模式下僅僅修改了指向到的backing file名字,必須謹慎操作.
  3. 現在可以直接删除sn2
    # rm sn2.qcow2
          

Method (2)

(by copying sn2 into sn3)

  1. 合并資料,rebase後端:
    # qemu-img rebase -b sn1.qcow2 sn3.qcow2
          
    • 未使用-u模式的rebase将把資料也一并合并過去,即sn2的資料寫入到sn3.
    • 換言之: 這裡使用的'Safe mode',也是預設模式 --對sn3而言任何從
    • qemu-img rebase(沒有-u)和和virsh blockpull類似.
    backingfile(sn1)到舊的backingfile(sn2)之間發生的差異改動都将被合并到sn3中.
  2. 現在可以删除sn2了
    # rm sn2.qcow2      

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

原創内容,如需轉載,保留署名

繼續閱讀