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