ZFS/Virtual disks

出自 Arch Linux 中文维基
< ZFS

該篇文章涵蓋了關於 ZFS 的一些基本任務和用例。它與 ZFS 主文章有所不同,此處的案例使用了基於虛擬磁盤搭建的 zpool。因此,只要用戶不在創建出的磁盤中存放任何關鍵數據,他們就無需擔心任何的數據丟失問題。

在該文章的案例中使用了多個虛擬磁盤作為 ZFS 的 VDEV。用戶可以用現有物理磁盤創建 VDEV,也可以在空閒內存足夠時使用 tempfs(內存盤)創建 VDEV。

注意: 使用文件作為 VDEV 是測試 ZFS 的好方法,但不建議用於存放實際數據。

由於許可證的差異問題,ZFS 二進制文件和內核模塊可以很容易地以原始碼進行分發,但不容易以軟件包和預編譯集形式進行分發。詳細信息可參考 ZFS#安裝

創建和刪除 Zpools[編輯 | 編輯原始碼]

管理 ZFS 非常簡單,只需要用到兩個工具:

  • /usr/bin/zpool
  • /usr/bin/zfs

鏡像[編輯 | 編輯原始碼]

對於僅包含兩個磁盤的帶冗餘 zpool,建議使用類似 RAID1 對數據鏡像鏡像的 鏡像 模式。鏡像同時可以作為 Raidz 配置的替代,以獲得出人意料的結果。關於 vdev 鏡像的詳細信息可參考這裏

RAIDZ1[編輯 | 編輯原始碼]

RAIDZ1 的最低硬盤數需求為 3。為了優化存儲空間效率和達到性能最佳點,建議盤數遵頊「二次方加驗證盤」的規則。對於 RAIDZ-1,建議使用 3(2+1),5(4+1),或者 9(8+1)塊盤。下列示例將使用最簡單的(2+1)。

創建 3 個 2G 的文件作為虛擬硬盤:

$ for i in {1..3}; do truncate -s 2G /scratch/$i.img; done

創建 RAIDZ1:

# zpool create zpool raidz1 /scratch/1.img /scratch/2.img /scratch/3.img

注意已成功創建並掛載了一個 3.91G 的 zpool:

# zfs list
 NAME   USED  AVAIL  REFER  MOUNTPOINT
 test   139K  3.91G  38.6K  /zpool

可通過如下方式獲取設備信息:

# zpool status zpool
  pool: zpool
 state: ONLINE
  scan: none requested
config:

	NAME                STATE     READ WRITE CKSUM
	   zpool            ONLINE       0     0     0
	  raidz1-0          ONLINE       0     0     0
	    /scratch/1.img  ONLINE       0     0     0
	    /scratch/2.img  ONLINE       0     0     0
	    /scratch/3.img  ONLINE       0     0     0

errors: No known data errors

要刪除 zpool:

# zpool destroy zpool

RAIDZ2 和 RAIDZ3[編輯 | 編輯原始碼]

高階 ZRAID 的操作與上述步驟類似,只需調整 for 循環參數來調整創建的文件數、在創建 zpool 時指定「raidz2」或「raidz3」,並補充上額外添加的鏡像文件。

總結下 Toponce 的指南:

  • RAIDZ2 硬盤數應為 4(2+2),6(4+2),10(8+2)或 18(16+2)。
  • RAIDZ3 硬盤數應為 5(2+3),7(4+3),11(8+3)或 19(16+3)。

線性擴展[編輯 | 編輯原始碼]

This setup is for a JBOD, good for 3 or less drives normally, where space is still a concern and you are not ready to move to full features of ZFS yet because of it. RaidZ will be your better bet once you achieve enough space to satisfy, since this setup is NOT taking advantage of the full features of ZFS, but has its roots safely set in a beginning array that will suffice for years until you build up your hard drive collection.

Assemble the Linear Span:

# zpool create zpool san /dev/sdd /dev/sde /dev/sdf
# zpool status zpool
  pool: zpool
 state: ONLINE
  scan: scrub repaired 0 in 4h22m with 0 errors on Fri Aug 28 23:52:55 2015
config:

        NAME        STATE     READ WRITE CKSUM
        zpool       ONLINE       0     0     0
          sde       ONLINE       0     0     0
          sdd       ONLINE       0     0     0
          sdf       ONLINE       0     0     0

errors: No known data errors

創建與刪除數據集[編輯 | 編輯原始碼]

以下演示了如何創建帶壓縮的子數據集:

  • 創建數據集
# zfs create -p -o compression=on san/vault/falcon/snapshots
# zfs create -o compression=on san/vault/falcon/version
# zfs create -p -o compression=on san/vault/redtail/c/Users
  • 接下來列出數據集 (this was a linear span)
$ zfs list

Note, there is a huge advantage(file deletion) for making a 3 level dataset. 如果你存放了大量的數據,通過使用數據集進行切分,可使得刪除文件時只需刪除對應的數據集,而無需等待刪除遞歸操作完成。

顯示並設置屬性[編輯 | 編輯原始碼]

Without specifying them in the creation step, users can set properties of their zpools at any time after its creation using /usr/bin/zfs.

顯示屬性[編輯 | 編輯原始碼]

To see the current properties of a given zpool:

# zfs get all zpool

修改屬性[編輯 | 編輯原始碼]

Disable the recording of access time in the zpool:

# zfs set atime=off zpool

Verify that the property has been set on the zpool:

# zfs get atime
NAME  PROPERTY     VALUE     SOURCE
zpool  atime        off       local
提示:This option like many others can be toggled off when creating the zpool as well by appending the following to the creation step: -O atime-off

Add content to the Zpool and query compression performance[編輯 | 編輯原始碼]

Fill the zpool with files. For this example, first enable compression. ZFS uses many compression types, including, lzjb, gzip, gzip-N, zle, and lz4. Using a setting of simply 'on' will call the default algorithm (lzjb) but lz4 is a nice alternative. See zfsprops(7) § compression for more.

# zfs set compression=lz4 zpool

In this example, the linux source tarball is copied over and since lz4 compression has been enabled on the zpool, the corresponding compression ratio can be queried as well.

$ wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.11.tar.xz
$ tar xJf linux-3.11.tar.xz -C /zpool 

To see the compression ratio achieved:

# zfs get compressratio
NAME      PROPERTY       VALUE  SOURCE
zpool  compressratio  2.32x  -

Simulate a disk failure and rebuild the Zpool[編輯 | 編輯原始碼]

To simulate catastrophic disk failure (i.e. one of the HDDs in the zpool stops functioning), zero out one of the VDEVs.

$ dd if=/dev/zero of=/scratch/2.img bs=4M count=1 2>/dev/null

Since we used a blocksize (bs) of 4M, the once 2G image file is now a mere 4M:

$ ls -lh /scratch 
total 317M
-rw-r--r-- 1 facade users 2.0G Oct 20 09:13 1.img
-rw-r--r-- 1 facade users 4.0M Oct 20 09:09 2.img
-rw-r--r-- 1 facade users 2.0G Oct 20 09:13 3.img

The zpool remains online despite the corruption. Note that if a physical disc does fail, dmesg and related logs would be full of errors. To detect when damage occurs, users must execute a scrub operation.

# zpool scrub zpool

Depending on the size and speed of the underlying media as well as the amount of data in the zpool, the scrub may take hours to complete. The status of the scrub can be queried:

# zpool status zpool
  pool: zpool
 state: DEGRADED
status: One or more devices could not be used because the label is missing or
	invalid.  Sufficient replicas exist for the pool to continue
	functioning in a degraded state.
action: Replace the device using 'zpool replace'.
   see: http://zfsonlinux.org/msg/ZFS-8000-4J
  scan: scrub repaired 0 in 0h0m with 0 errors on Sun Oct 20 09:13:39 2013
config:

	NAME                STATE     READ WRITE CKSUM
	   zpool            DEGRADED     0     0     0
	  raidz1-0          DEGRADED     0     0     0
	    /scratch/1.img  ONLINE       0     0     0
	    /scratch/2.img  UNAVAIL      0     0     0  corrupted data
	    /scratch/3.img  ONLINE       0     0     0

errors: No known data errors

Since we zeroed out one of our VDEVs, let us simulate adding a new 2G HDD by creating a new image file and adding it to the zpool:

$ truncate -s 2G /scratch/new.img
# zpool replace zpool /scratch/2.img /scratch/new.img

Upon replacing the VDEV with a new one, zpool rebuilds the data from the data and parity info in the remaining two good VDEVs. Check the status of this process:

# zpool status zpool 
  pool: zpool
 state: ONLINE
  scan: resilvered 117M in 0h0m with 0 errors on Sun Oct 20 09:21:22 2013
config:

	NAME                  STATE     READ WRITE CKSUM
	   zpool              ONLINE       0     0     0
	  raidz1-0            ONLINE       0     0     0
	    /scratch/1.img    ONLINE       0     0     0
	    /scratch/new.img  ONLINE       0     0     0
	    /scratch/3.img    ONLINE       0     0     0

errors: No known data errors

快照和恢復已刪除的文件[編輯 | 編輯原始碼]

ZFS 是寫時複製文件系統,所有文件在寫入那一刻時就已存入。保存文件修改實際上創建了同一文件的拷貝及其修改記錄。快照實際上利用了這一特性,使得用戶可以訪問快照創建時的舊版本文件。

注意: 因 ZFS 使用快照方式較為特殊,當使用快照時,像 df 一類匯報文件系統空間的 Linux 應用會給出不準確的數據。/usr/bin/zfs list 會給出準確的 zpool 可用及剩餘空間數據。

為了簡化示例,我們將在 zpool 中創建數據集並創建快照,快照可以對整個 zpool 或者池中的單個數據集進行創建,區別只有命名方式:

快照目標 快照名
整個 zpool zpool@snapshot-name
數據集 zpool/dataset@snapshot-name

創建新數據集並獲取所有權:

# zfs create zpool/docs
# chown facade:users /zpool/docs
注意: 創建命令中缺少 / 是有意為之的,並不是缺漏!

Time 0[編輯 | 編輯原始碼]

添加一些文件到新數據集中(/zpool/docs):

$ wget -O /zpool/docs/Moby_Dick.txt  https://www.gutenberg.org/ebooks/2701.txt.utf-8
$ wget -O /zpool/docs/War_and_Peace.txt https://www.gutenberg.org/ebooks/2600.txt.utf-8
$ wget -O /zpool/docs/Beowulf.txt https://www.gutenberg.org/ebooks/16328.txt.utf-8
# zfs list
NAME           USED  AVAIL  REFER  MOUNTPOINT
zpool       5.06M  3.91G  40.0K  /zpool
zpool/docs  4.92M  3.91G  4.92M  /zpool/docs

這意味着下載的書籍佔用了 /zpool/docs 中 4.92M 的空間。

Time +1[編輯 | 編輯原始碼]

接下來為數據集創建快照:

# zfs snapshot zpool/docs@001

再運行一次 list 命令:

# zfs list
NAME           USED  AVAIL  REFER  MOUNTPOINT
zpool       5.07M  3.91G  40.0K  /zpool
zpool/docs  4.92M  3.91G  4.92M  /zpool/docs

注意,因為這三個文件沒有被修改,因此 USED 一列沒有變更,意味着快照不佔用 zpool 空間。

我們可以通過如下方式列出快照,並確認快照不佔用存儲空間,而是引用了原始文件,這些文件共佔用 4.92M:

# zfs list -t snapshot
NAME               USED  AVAIL  REFER  MOUNTPOINT
zpool/docs@001      0      -  4.92M  -

Time +2[編輯 | 編輯原始碼]

接下來添加些新文件,並創建新快照:

$ wget -O /zpool/docs/Les_Mis.txt https://www.gutenberg.org/ebooks/135.txt.utf-8
# zfs snapshot zpool/docs@002

再次使用 list 來查看空間變化:

# zfs list -t snapshot
NAME               USED  AVAIL  REFER  MOUNTPOINT
zpool/docs@001  25.3K      -  4.92M  -
zpool/docs@002      0      -  8.17M  -

可以看到 001 快照的元數據佔用了 25.3K 大小,並依舊引用了之前的 4.92M 數據;新快照不佔用任何空間,並引用了總共 8.17M 的數據。

Time +3[編輯 | 編輯原始碼]

接下來我們模擬下意外覆蓋文件導致的數據丟失:

$ echo "this book sucks" > /zpool/docs/War_and_Peace.txt

與之前一樣,再創建一個快照:

# zfs snapshot zpool/docs@003

接下來列出快照,可見被引用的數據減少了 3.1M:

# zfs list -t snapshot
NAME               USED  AVAIL  REFER  MOUNTPOINT
zpool/docs@001  25.3K      -  4.92M  -
zpool/docs@002  25.5K      -  8.17M  -
zpool/docs@003      0      -  5.04M  -

我們可以在一個或者多個舊快照中找到該文件的未損壞版本。ZFS 將快照存放在 zpool 中一個隱藏文件夾內:/zpool/files/.zfs/snapshot

$ ls -l /zpool/docs/.zfs/snapshot
total 0
dr-xr-xr-x 1 root root 0 Oct 20 16:09 001
dr-xr-xr-x 1 root root 0 Oct 20 16:09 002
dr-xr-xr-x 1 root root 0 Oct 20 16:09 003

我們可以從任意一個快照中複製一份未損壞版本的書到 zpool 內或外部的任意地址:

% cp /zpool/docs/.zfs/snapshot/002/War_and_Peace.txt /zpool/docs
注意: <TAB> 自動補全在默認情況下不可用,但可通過修改存儲池或數據集的 snapdir 屬性來啟用。
# zfs set snapdir=visible zpool/docs

接下來進入一個或各個快照文件夾:

$ cd /zpool/docs/.zfs/snapshot/001
$ cd /zpool/docs/.zfs/snapshot/002

重複 df 命令:

$ df -h | grep zpool
zpool           4.0G     0  4.0G   0% /zpool
zpool/docs      4.0G  5.0M  4.0G   1% /zpool/docs
zpool/docs@001  4.0G  4.9M  4.0G   1% /zpool/docs/.zfs/snapshot/001
zpool/docs@002  4.0G  8.2M  4.0G   1% /zpool/docs/.zfs/snapshot/002
注意: 通過將 zpool 設為離線並重新掛載,或是重啟伺服器,可以撤銷 .zfs 下所有文件夾可見。

例如:

# zpool export zpool
# zpool import -d /scratch/ zpool
$ df -h | grep zpool
zpool         4.0G     0  4.0G   0% /zpool
zpool/docs    4.0G  5.0M  4.0G   1% /zpool/docs

Time +4[編輯 | 編輯原始碼]

現在一切已恢復正常,我們可以為目前狀態再次創建一個快照:

# zfs snapshot zpool/docs@004

此時的 list 輸出為:

# zfs list -t snapshot
NAME               USED  AVAIL  REFER  MOUNTPOINT
zpool/docs@001  25.3K      -  4.92M  -
zpool/docs@002  25.5K      -  8.17M  -
zpool/docs@003   155K      -  5.04M  -
zpool/docs@004      0      -  8.17M  -

列出快照[編輯 | 編輯原始碼]

需要指出,這一簡單但十分重要的命令在同類文章中經常被忽略,因此有必要特別提一下。

使用如下命令列出系統中的所有快照:

$ zfs list -t snapshot

刪除快照[編輯 | 編輯原始碼]

可存放的快照數量最大為 2^64,用戶可以通過如下命令刪除快照:

# zfs destroy zpool/docs@001
# zfs list -t snapshot
NAME               USED  AVAIL  REFER  MOUNTPOINT
zpool/docs@002  3.28M      -  8.17M  -
zpool/docs@003   155K      -  5.04M  -
zpool/docs@004      0      -  8.17M  -

Troubleshooting[編輯 | 編輯原始碼]

If your system is not configured to load the zfs pool upon boot, or for whatever reason you want to manually remove and add back the pool, or if you have lost your pool completely, a convenient way is to use import/export.

If your pool was named <zpool>

# zpool import -d /scratch zpool

If you have any problems accessing your pool at any time, try export and reimport.

# zpool export zpool
# zpool import -d /scratch zpool