注意 encryptionroot:當 ZFS 出包時如何救回你的資料 (★ 101 分)
這篇文章記錄了一位工程師在使用 OpenZFS 原生加密功能時,幾乎失去 8.5 TiB 重要資料的驚險經驗。原本他有兩個 ZFS 儲存池,分別命名為 `old` 與 `new`,藉由第三個移動硬碟池 `sneakernet` 在兩地之間傳送快照進行備份。`new` 從一開始就啟用了原生加密,而 `old` 起初未加密,後來逐步轉換為加密資料集並銷毀未加密版本。然而,在更換加密金鑰的過程中,他未及時為加密根 (encryption root) 建立新快照,導致後續傳送的子資料集快照仍然參考舊的包裝金鑰 (wrapping key),最終造成備份檔案無法解密掛載。他在銷毀 `old/encrypted/foo` 資料集後,才驚覺連 `sneakernet` 與 `new` 上的副本都壞掉,陷入可能永久資料遺失的絕境。
經過冷靜分析,作者深入研究了 ZFS 的運作原理,包括副本寫入 (copy-on-write)、Merkle tree 結構、交易群組 (transaction groups) 與加密根的關係。他成功在測試環境重現問題:當改變加密根金鑰後,若只傳送子資料集快照、卻未傳送包含金鑰參數的加密根快照,就會讓子資料集變得不可解密。理論上只要補送一份加密根的最新快照即可修復,但實務上因為舊的快照已刪除,必須透過更複雜的方式解決。他最終修改了 ZFS 原始程式碼,手動建立一個帶有正確交易群組參數的書籤 (bookmark),以便產生所需的遞增快照串流,再利用調整系統參數暫時忽略 IV set GUID 驗證,才終於把資料恢復回來。這場一週的惡夢讓他總結出幾個教訓:持續測試備份、銷毀操作應集中處理、變更金鑰後務必備份加密根快照,以及在刪除快照前先建立書籤。
在 Hacker News 的討論中,許多使用者亦有類似經驗。有些人表示偏好不用原生加密,而是將 ZFS 建立在 LUKS (Linux Unified Key Setup) 或 FreeBSD 的 GELI 全碟加密上,因為這樣在跨系統、測試與修復上更直觀。有備份公司工程師則指出,ZFS 原生加密結合 Zstd 壓縮的效率比傳統 dm-crypt 更好,因為流程是「先壓縮再加密」,較省空間也更快。但使用者仍強調測試備份的重要性,僅靠自動化腳本往往不足,必須定期人工檢查,否則就可能在關鍵時刻才發現備份無法掛載。
也有評論者認為 ZFS 的這種行為雖然「照設計運作」,但缺乏清楚的工具與錯誤訊息。當使用者遇到「Permission denied」時,實際上是因為金鑰傳遞錯誤,但系統卻沒有明確提示,逼得人必須透過閱讀源碼來理解,這顯示文件與錯誤處理尚有待改善。另一派則指出這正是 ZFS 複雜性的副作用:它提供強大的功能,但也帶來更多失誤風險,因此不少人仍維持傳統的 mdadm + LUKS + ext4 或類似架構,以確保系統直觀且較少隱藏陷阱。
整體而言,這篇實錄被許多 ZFS 使用者形容為「加密 horror story」,但同時也提供了寶貴經驗:ZFS 原生加密仍有明顯的「銳利邊角」(sharp edges),需要使用者高度謹慎。對於追求資料可靠性的系統管理員來說,ZFS 無疑是一個強大工具,但在實務應用上,選擇較簡單、文件與工具更成熟的解決方案,仍是許多人採取的風險控管方式。
👥 31 則討論、評論 💬
https://news.ycombinator.com/item?id=45431167