ZFS/虛擬磁碟 - Arch Linux 中文维基

跳至內容

# ZFS/虛擬磁碟

出自 Arch Linux 中文维基
< ZFS

相關文章

- ZFS
- 在 ZFS 上安裝 Arch Linux

翻譯狀態：

- 本文（或部分內容）譯自 ZFS/Virtual disks，最近一次同步於 2023-10-28，若英文版本有所更改，則您可以幫助同步與翻譯更改的內容。
- 您可以在 ArchWiki 的對應頁面找到本文翻譯的原始修訂歷史。
- 本文可能與英文原文存在出入。

該篇文章涵蓋了關於 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

分類：​

- 文件系統

ZFS/虛擬磁碟
新增話題