LVM : 快照

sparkdev發表於2019-01-08

LVM 機制還提供了對 LV 做快照的功能,也就是說可以給檔案系統做一個備份,這也是設計 LVM 快照的主要目的。LVM 的快照功能採用寫時複製技術(Copy-On-Write,COW),這比傳統的備份技術的效率要高很多。建立快照時不用停止服務,就可以對資料進行備份。說明:LVM 還支援 thin 型別的快照,但是本文中的快照都是指 COW 型別的快照。

LVM 採用的寫時複製,是指當 LVM 快照建立的時候,僅建立到實際資料的 inode 的硬連結(hark-link)而已。只要實際的資料沒有改變,快照就只包含指向資料的 inode 的指標,而非資料本身。快照會跟蹤原始卷中塊的改變,一旦你更改了快照對應的檔案或目錄,這個時候原始捲上將要改變的資料會在改變之前拷貝到快照預留的空間。說明:本文的演示環境為 ubuntu 16.04。

LVM 快照的原理

建立快照實際上也是建立了一個邏輯卷,只不過該卷的屬性與普通邏輯卷的屬性有些不一樣。我們可以通過下圖來理解快照資料卷(圖中的實線框表示快照區域,虛線框表示檔案系統):

左圖為最初建立的快照資料卷狀況,LVM 會預留一個區域 (比如左圖的左側三個 PE 區塊) 作為資料存放處。 此時快照資料卷內並沒有任何資料,而快照資料卷與源資料卷共享所有的 PE 資料, 因此你會看到快照資料卷的內容與源資料卷中的內容是一模一樣的。 等到系統執行一陣子後,假設 A 區域的資料被更新了(上面右圖所示),則更新前系統會將該區域的資料移動到快照資料卷中, 所以在右圖的快照資料卷中被佔用了一塊 PE 成為 A,而其他 B 到 I 的區塊則還是與源資料卷共享!

由於快照區與原本的 LV 共享很多 PE 區塊,因此快照區與被快照的 LV 必須要在同一個 VG 上頭,下面兩點非常重要:

  • VG中需要預留存放快照本身的空間,不能全部被佔滿。
  • 快照所在的 VG 必須與被備份的 LV 相同,否則建立快照會失敗。

建立 LVM 快照

在建立快照前讓我們先檢視一下系統當前的基本情況:

資料卷 nicklv00 大小為 15G,在卷組 nickvg 中。

卷組 nickvg 的容量為 70G,其中有 55G 為空閒容量,所以我們有足夠的資源為資料卷 nickvg/nicklv00 建立快照。
其實快照就是一個特殊型別的資料卷,所以建立快照的命令和建立資料卷的命令相同,也是 lvcreate:

$ sudo lvcreate -L 15G --snapshot --name nicksnap00 nickvg/nicklv00

其實就是新增了一個特殊型別的 LV:

此時如果把 LV nicksnap00 掛載到系統中,裡面的內容和 LV nicklv00 中的內容是一樣的。
建立的快照的大小可以比源資料卷小,但是當源資料卷中的資料更新過多時會導致快照容量不足而引起的錯誤並丟失資料。

建立快照後,如果源資料卷中的檔案被更新了,快照系統中則儲存著其建立快照時的版本。

還原部分資料

如果我們明確的知道需要還原某個檔案,可以掛載快照資料卷,直接拷貝其中舊版本的檔案即可。下面以 /home/doc/hello.txt 檔案為了進行演示。hello.txt 檔案原本的內容為 "hello world",先更新一下 hello.txt 檔案:

我們在檔案中加入了一句話:"I changed you!"。接下來我們開始通過快照來還原這個檔案。

掛載快照資料卷

檢視快照中的檔案內容:

驗明正身後直接通過 cp 命令覆蓋原檔案就可以了:

還原整個資料捲上的資料

如果資料捲上有很多小檔案,並且都可能會被更新,這種情況下就不適合用上面的方法了。此時一把還原所有的資料會效率更高些,接下來我們介紹還原整個資料捲上所有資料的方式。

掛載快照資料卷
這一步與之前的操作相同,掛載點也同樣為 /home/nick/bak 目錄。

把快照中的資料匯出到另外一個資料捲上
建立一個新的目錄 /home/nick/backup,注意這個目錄所在的檔案系統既不是源資料卷也不是快照資料卷。然後把快照資料卷中的內容建立為壓縮檔案儲存在 /home/nick/backup 目錄中:

為什麼要把資料備份到其它的資料卷呢?為什麼不可以直接格式化 nickvg/nicklv00 然後將快照 nickvg/nicksnap00 直接複製給 nickvg/nicklv00 呢? 原因是因為 nickvg/nicksnap00 是 nickvg/nicklv00 的快照,如果格式化整個 nickvg/nicklv00,那麼nickvg/nicklv00 上的所有資料都會被搬移到 nickvg/nicksnap00。 如果 nickvg/nicksnap00 的容量不夠大,那麼部分資料將無法複製到 nickvg/nicksnap00 內!

解除安裝並刪除快照資料卷

$ sudo umount /home/nick/bak
$ sudo lvremove nickvg/nicksnap00

解除安裝源資料卷,格式化後重新掛載

$ sudo umount /home/doc
$ sudo mkfs.ext4 /dev/nickvg/nicklv00
$ sudo mount /dev/mapper/nickvg-nicklv00 /home/doc

把資料還原到源資料卷

$ sudo tar -xf /home/nick/backup/lvm.tar.gz -C /home/doc

這樣就把建立快照時刻的資料完全還原出來了。

合併快照(merge snapshot)

前面介紹的方法可以恢復整個資料捲上的資料,但是操作起來實在是太繁瑣了,其實我們可以通過 lvconvert 命令配合其 --merge 選項一把搞定整個資料卷的還原。下面演示該方法的主要步驟。

建立快照
由於前面的演示刪除了快照資料卷,這裡我們重新建立名稱為 nicksnap00 的快照資料卷:

$ sudo lvcreate -L 15G --snapshot --name nicksnap00 nickvg/nicklv00

然後更新一下檔案 /home/doc/hello.txt:

$ echo "I changed you!" >> /home/doc/hello.txt 

解除安裝源資料卷
合併快照的操作也需要解除安裝源資料卷:

$ sudo umount /home/doc

合併快照
確認源資料卷和快照資料卷都沒有被掛載後就可以執行合併快照的操作了:

$ sudo lvconvert --merge nickvg/nicksnap00

 

注意,合併快照的操作會自動刪除快照資料卷:

上圖顯示快照資料卷 nicksnap00 已經被刪除了。

重新掛載源資料卷
現在我們來重新掛載源資料卷並檢視檔案 hello.txt 的內:

$ sudo mount /dev/mapper/nickvg-nicklv00 /home/doc
$ cat /home/doc/hello.txt

hello.txt 檔案中沒有字串 "I changed you!",說明整個資料捲上的內容已經被還原到了建立快照的時刻。

利用快照建立測試環境

如果我們需要在測試環境中不斷的修改檔案,就可以利用快照來建立這樣的測試環境。想想看,對一個資料卷建立快照,然後把這個快照資料卷掛載到系統中並作為測試環境任意地修改上面的資料;當測試完成時直接解除安裝並刪除這個快照就可以了;如果還需要這樣的測試環境,再建立一個新的快照就行了,是不是很方便呢!

總結

快照是 LVM 中的一個稍微高階一點的話題,但僅就日常的使用來說,本文介紹的常見用法足夠大家愉快的開啟探索之旅了。

參考:
LVM 快照
LVM 的系統快照
lvm 邏輯卷的快照及備份 還原
在 LVM中 錄製邏輯卷快照並恢復
LVM Snapshot Merging

相關文章