2017年3月30日 星期四

zfs 檔案系統試水溫

zfs 檔案系統 當昇陽 (Sun Microsystems) 還沒有被 Oracle 併購時, 它曾是一家技術領先、 文化開放的公司。 他們在 2004 年時為 solaris 所開發的 zfs 檔案系統, 領先所有競爭者, 甚至到了 2017 年的今天, 似乎仍只有 linux 的 btrfs (還有微軟的 ReFS?) 勉強可與它相比。 恆逸資訊洪朝欽老師免費幫我上了好幾次個人家教課 :-) 可惜他沒在寫部落格。 所以我來轉述分享一下他教我的一小部分內容, 還有爬文及輕度使用幾個月之後的心得, 並建議一條簡單且小心翼翼的學習路徑。

[2020/01/11 Linus Torvalds建議不要使用ZFS (考量法律與 Oracle 興訟的習性)] ==> [2020/9/15 大推改用 btrfs 取代 zfs]

一、 新一代的檔案系統的特色

傳統的檔案系統 (例如 ext4) 就單純只是 「一長條儲存陣列 vs 樹狀結構目錄」 的翻譯器。 所以目前我們使用磁碟的方式, 大致類似左圖: 底層是實體硬碟或分割區、 上面是 mdadm 所建立的 RAID 磁碟陣列 (我不熟)、 再上去是 dm-crypt 所建立的加密裝置 (沒用過)、 再上去是 lvm2 (日常在用)、 再上去是 logical volumes、 最上面才是 ext2/3/4 或 vfat 等等傳統的檔案系統。

zfs 跟 btrfs 卻是從最上層的樹狀結構管到很下層的磁碟陣列, 中間還包含可以對檔案系統加密。

按照傳統的想法, 模組化 modular 才是好的設計 -- 軟體拆成一塊一塊的元件、 各自獨立運作、 透過簡單的介面彼此支援。 但是檔案系統的狀況比較特別: 當硬體出差錯時, 上層的檔案系統跟底層的 RAID 如果只是單純的呼叫/使用關係, 彼此不清處對方的需求及特性, 那麼有一些事處理起來就很麻煩。 zfs 跟 btrfs 因為從上管到下, 而且每個 block 都做 checksum, 所以能夠做到 "self healing" 之類、 傳統檔案系統加 RAID 做不到的功能。 當然, 現代的硬碟韌體本身就已有 SMART 自我檢測機制。 新一代檔案系統層級的 checksum 到底會在哪些清況下發生作用、 跟 SMART 機制如何合作或互補或無效重複, 這我也沒研究。

我自己最感興趣的功能, 是超低成本快照。 快照指令 (zfs snapshot ...) 對系統而言, 只是設定一些指標, 所以不用花半秒鐘、 花費的儲存空間也極少, 但卻相當於保留了目前系統的狀態, 未來隨時可將系統還原 (zfs rollback ...) 到目前狀態。 這也讓你可以把 (正在運作的!) 本機所安裝的 linux 的先前某時刻快照複製給別人 -- 例如開機隨身碟可以靠這個功能自我複製。 (待實驗)

因為 zfs 更新檔案內容時, 不會覆蓋舊的資料, 而是在新的未用空間寫資料, 所以想要徹底刪除舊資料會變得很困難。 解決方式是 加密

zfs (及 btrfs) 還有壓縮、 去除重複、 備份、 超大容量、 非同步複製等等其他功能。 與它類似的 「新一代檔案系統」 包含: zfs, btrfs, refs, apfs 等等。 詳見 Bitrot and atomic COWs: Inside “next-gen” filesystems [但也請見 吐槽文] 及討論串: Next gen filesystems (ZFS, BtrFS, ReFS, APFS, etc)

二、 linux 版 zfs 的現況、 使用心得、 行前重要提醒

因為 zfs 歷史悠久, 所以它的穩定性比 btrfs 要高; 但是 Linux 版的 zfs 的加密功能 還在上游整合當中。 此外, 較晚推出的 btrfs 還有更多有趣的新功能 (見 arstechnica 連結)。

Ubuntu 從 16.04 版開始, 就已將 zfs 套件放進套件庫, 所以現在使用起來很簡單。 Canonical 公司本身可能需要處理一些 法律疑慮; 不過對我們終端用戶沒什麼影響。

我自己的使用心得是: 它吃記憶體吃很兇! 一部記憶體只有 2G、 沒有 swap 的 lubuntu 機器 (對,以前從來沒在用 swap), 如果開了一個 firefox 看網頁, 一旦開始操作 zfs 指令, 很可能會死當。 最少最少要有 200MB 的 swap, 當系統開始氣喘吁吁時, 你才有機會把 firefox 視窗關掉。 我的經驗是 1GB 的 swap 就很夠緩衝了; 如果還是不夠用, 應該加記憶體才能徹底解決問題。 也請參考 更多人的 swap 大小配置經驗分享

開 kvm 虛擬機要特別小心: Host 跟 (支援 zfs 的) guest 不能同時看見同一個 pool, 不然會打架。 另外, 不太確定是我先前做錯什麼還是它真的 cache 到關機前的最後一刻才寫出去, 總之即使 host 或 guest 已經 zpool export ... 從另一方可能還是會看到舊的資料。 所以現在我要開虛擬機之前, 都會先徹底地把 zfs 核心模組整個移除掉:

zpool export ...
systemctl stop zed
rmmod zfs

待開虛擬機用完之後, 如果需要再從 host 裡面查看或使用 zfs, 才再反過來重新載入:

modprobe zfs
systemctl start zed
zpool import ...

這麼做以後, 就沒再出現過兩者打架的問題, 而且也比較省記憶體。

使用 zpool destro... 指令要超級小心! 完全沒有再次確認的機會, 所有資料直接就毀了!

三、 建議的學習起步

我自己是因為架設 proxmox server 時選用 zfs, 所以不必煩惱底層及初始的設定, 直接就開始享用最輕鬆好用的 zfs snapshot ...

如果沒有 proxmox 的 zfs 可玩, 那麼當然就用 ubuntu 系列, 16.04 或更新的版本最簡單。 我會建議先在硬碟上切兩個邏輯分割區給 zfs 用。 練習用的, 每個 20G 就夠了 (夠裝兩三套完整版的 linux); 兩個分割的目的, 是為了以後可以練習 send 跟 receive。 只需要 apt-get install zfsutils-linux 就可以開始 zpool create zlab /dev/sda99。 如果是外接硬碟, 用完後必須先 zpool export zlab 才能移除; 下次接上後, 可能要先 zpool import zlab 才能開始用。 如果忘記 zpool 的名字, 可用 「不加參數」 的 zpool import 查詢。

再來就可以參考以下文章, 從 zfs list ...zfs create ... 玩起。 (因為我們用 ubuntu 16.04, 所以可以省略這些文章前面設定環境的部分。)

  1. ZFS 檔案系統筆記(1)
  2. ZFS 真是一個上帝賜給IT人員的好禮物!!!
  3. zfs 管理 (FreBSD 社群很完整的中文指令教學)
  4. Run ZFS on Linux (英文, 很清楚扼要的概觀介紹, 加上一些指令教學)
  5. Aaron Toponce's zpool and zfs admin guide (英文, zfs 超詳盡的觀念加指令完全教學手冊, 我想要有系統地學習某一主題時就來看這份講義)

等你略懂略懂 zfs 操作之後, 下一步就是 把 *ubuntu 整個搬到 zfs 裡面去, 超多好處﹗

後記: 編譯提醒

[2020/3/4] 升級 kernel 時, 系統需要重新編譯配合版本的 zfs 模組。 因此建議同時安裝以下幾個套件, 以便它自動編譯 (以 4.18.0-17 為例) apt install zfsutils-linux spl-dkms zfs-dkms zfs-initramfs linux-image-4.18.0-17-generic linux-headers-4.18.0-17-generic linux-modules-4.18.0-17-generic

但是編譯經常失敗 orz 因為程式原始碼一直在改。 偶爾編譯成功的話, 趕快把 /lib/modules/4.18.0-17 備份起來! 編譯失敗之後, 每次開機都會出現 「偵測到系統錯誤」 之類的訊息。 請到 /var/crash 把兩個 log 檔搬到別的地方研究, 就可以免除錯誤訊息。

9 則留言:

  1. ZFS 的軟體授權用的是 CDDL,與Linux的GPL2不相容。
    此外,我之前用BTRFS都有遇過一個問題:莫名其妙多出ZFS的signature,結果只能用手動 mount -t btrfs 掛載。

    回覆刪除
  2. 老師說到的開機隨身碟可以靠(ZFS)這個功能自我複製,感覺到很有趣還記得老師之前提到的finnix的自我無性生殖,到現在我的隨身碟裡一定放這finnix真的是輕巧又方便,ZFS我現在都是用在記憶體多的電腦,看到老師的方法好像比較省記憶體,那我把zfs 記憶體限制大小,不知道會不會有什麼影響呀?(變慢嗎?)這樣snapshot依然可以使用!!我有在antix16裡面灌zfs可是不是整個都放進去~再來試看看OK不OK!!謝謝老師了!

    回覆刪除
  3. > 把zfs 記憶體限制大小
    可以這樣做哦? 要下什麼指令呢?

    回覆刪除
    回覆
    1. 我不清楚有沒有指令 我只會改設定檔 cat /etc/modprobe.d/zfs.conf
      # 4G
      #options zfs zfs_arc_max=4299967296
      # 3G
      #options zfs zfs_arc_max=3224975472
      # 2G
      #options zfs zfs_arc_max=2149983648
      # 1G
      #options zfs zfs_arc_max=1074991824
      # 756M
      # options zfs zfs_arc_max=792723456
      # 256M
      # options zfs zfs_arc_min=268435456
      # 128M
      #options zfs zfs_arc_max=134217728
      # 100M
      #options zfs zfs_arc_min=104857600

      這個檔案是設定限制 zfs 最大記憶體使用量。

      刪除
  4. 老師在文中提到zfs很耗記憶體,我剛好在讀ReFS的介紹時,有看到他說zfs耗用記憶體是因為他有啟用線上重複資料消除的功能:
    https://zh.wikipedia.org/zh-tw/ReFS
    不知道是否有幫助

    回覆刪除
    回覆
    1. 謝謝分享! 不過... 哇, linux 版的相關資訊好難搜尋。 我用 「zpool status -D pool名稱」 查看, 看到 「dedup: no DDT entries」 , 好像預設並沒有啟用 dedup 功能耶?

      刪除
  5. 除了 ubuntu 外,可以嘗試 antergos (base on Arch linux)
    使用iso開機安裝系統,可以選擇zfs檔案系統,就能有 zfs on root(像是 freebsd 一樣)
    目前遇到的問題,就是當系統有升級新版的linux核心,若沒有先做幾個動作就reboot,會發生開機無法讀取zfs模組,造成無法開機的冏境
    但解法也很簡單,antergos論壇就有解法
    https://forum.antergos.com/topic/5418/zfs-on-root-and-kernel-upgrade-process/5
    我也依照這個解法,把系統救援回來
    目前快樂使用中

    回覆刪除
  6. 2020/10/111 是未來時間喔~~

    回覆刪除

因為垃圾留言太多,現在改為審核後才發佈,請耐心等候一兩天。