
前情提要:
Day 16 結尾留了一個重大的架構風險揭露:HDP 的備份儲存庫、Day 13 的 AI 模型庫、Day 2 到 Day 8 的容器持久化卷(Persistent Volumes),以及 PVE 的 VM 虛擬磁碟,全部集中在同一台 NAS 的同一個儲存池中。這意味著儲存設備本身就是最大的單點故障(SPOF)。今天要正面解決「整台儲存設備出事」時的災難復原問題。使用工具為 QuTS hero 的 ZFS 快照與 Hybrid Backup Sync 3(HBS 3),目標是落實 3-2-1 備份架構中的前兩個數字,最後的異地與雲端「1」則留待 Day 18 處理。
很多維運事故的根源,不在於沒有設計備份,而在於「以為系統有在備份」。
為了掌握真實狀態,使用唯讀腳本 nas-audit.sh 進行體檢。該腳本無須 root 權限,透過 SSH 執行 zfs list、zfs get、解析快照排程設定檔、檢查 HBS 3 套件狀態及 rsync 模組組態。分別對主 NAS 與作為備份標的的次要 NAS 進行全面盤點:
| 項目 | 主 NAS (Production) | 次要 NAS (Backup Target) |
|---|---|---|
| 儲存池配置 | zpool1 23 TB,已用容量 26% |
zpool1 432 GB(單顆 2.5 吋筆電硬碟,無備援)zpool2 562 GB(雙碟 Mirror),各使用 1% |
| 快照排程 | 無(設定檔大小為 0 位元組) | 無 |
| 現有快照 | 僅存 7 個資料集建立時系統自動生成的 :init: |
僅存 :init: 快照 |
| 快照保留空間 | 儲存池層級設定 5%,實際保留空間為 0 位元組 | 未設定 |
| HBS 3 工作 | 存在 2 個工作:手動觸發、未加密、目的地離線。- 工作 A:執行過 - 工作 B 需要改善 | 未安裝套件 |
| 快照複本 (Replica) | 無任何排程工作 | 無 |
⚠️ 維運警示
主 NAS 上遺留的兩個 HBS 3 備份目的地,指向早前已除役的設備。控制台上的備份卡片寫著「備份前先建快照」與「快速檢查」,看似處於受保護狀態,實際上需要再強化過。
這種「看似有備份」的假象比完全沒有備份更危險,因為它提供了致命的安全錯覺。
此外,檢查主 NAS 的 Public 資料集時,發現屬性 qnap:zfs_snapshot_maxid 的值為 7,這代表過去手動建立過快照隨後又手動刪除。這證明快照機制在系統中是可行的,只是從未被制度化納入自動排程。
受限於硬體條件,次要 NAS 的兩個儲存池可用容量加總僅約 0.9 TB,而主 NAS 實際已使用 4.8 TB。不可能進行全機 1:1 鏡像,必須進行資料分級(Data Classification)。
分級的判斷標準只有兩個:
| 共享資料夾 / 目錄 | 容量大小 | 唯一副本? | 快照保護策略 | 複製到次要 NAS 決策 |
|---|---|---|---|---|
| Container | 22.5 GB | 是 | 每小時保留 24 份 + 每日保留 7 份 | 是,寫入 zpool2 (Mirror) |
| HDP_Business | 262 GB | 是 | 每日保留 7 份 | 是,寫入 zpool2 (Mirror) |
| Public/images(VM 磁碟) | 99 GiB | 否(HDP 已有備份版本) | 隨 Public 資料集,每日保留 7 份 | 是,寫入 zpool2 (Mirror) |
| homes, Wordpress, Music | 22 MB / 10 GiB / 4.7 GiB | 是 | 隨所屬資料集自動拍快照 | 是,寫入 zpool2 (Mirror) |
| vzdump | 258 GB | 否(HDP 為第一套) | 每日保留 3 份 | 是,寫入 zpool1(單碟池) |
| Public/AIModels, comfyui | 合計約 2.9 TiB | 否(可自上游重新下載) | 隨 Public 資料集(內容變動極低) | 否(不複製) |
qcow2 實體磁碟,PVE 只要將次要 NAS 掛載為 NFS 儲存節點,即可直接開機掛載(演練 4 將進行量測)。HDP_Business 與容器組態放進具備雙碟 Mirror 的 zpool2。容量精算後,zpool2 承載約 407 GB 資料(佔比 72%),剩餘空間全數預留給次要 NAS 本地的 ZFS 快照增量空間。| 配置項目 | 主 NAS (Production) | 次要 NAS (Replica Target) | 設計依據 |
|---|---|---|---|
| 排程頻率 | Container 每小時整點,其餘資料集每日 00:30 |
每日 05:00 | 主 NAS 刻意錯開系統維護任務(01:00 釋放快取、02:00 qfstrim、03:00 惡意程式掃描,以及 01:30 的 HDP 備份),次要 NAS 快照則必須落在 04:00 同步完成之後。 |
| 保留週期 | Container 保留 24 小時 + 7 日份,Public 與 HDP_Business 保留 7 份, |
所有副本資料集一律保留 14 份 | 次要 NAS 的保留時間必須長於主 NAS,確保主端遭受勒索軟體加密或靜默損壞時,對端仍有未受污染的時間點可供回溯。 |
| 快照保留空間 | 儲存池層級設定 5%(約 1.1 TB) | zpool2 設定 10% |
Public 的每日資料異動量主要來自虛擬機磁碟寫入。 |
| 快照目錄可見性 | snapdir visible (開啟) |
snapdir visible (開啟) |
NAS 本地端可直接自 @Recently-Snapshot 讀取歷史狀態。 |
機制剖析:快照不等於備份
- 快照不能計入 3-2-1 的獨立副本:主 NAS 只有一個儲存池,快照與即時資料存放在同一組實體磁碟上。一旦整個儲存池壞軌或控制器故障,兩者同步毀滅。快照的職責是解決人為誤刪、客體端勒索軟體攻擊與應用程式錯誤變更。
- NFS 客戶端的快照盲區:在 QuTS hero 架構下,NFS 客戶端無法直接進入快照目錄取檔。因為
@Recently-Snapshot實際上是另一個內部掛載資料集,掛載後對 NFS 而言為空目錄,且其內部符號連結指向 NAS 本地絕對路徑,.zfs亦未直接匯出。單檔還原必須由 NAS 本地 Shell、File Station 或透過 SMB 的「以前的版本」進行。- 快照回滾(Revert)的非預期代價:演練 2 實測顯示,回復一個 20 GB 的目錄,會導致整台 NAS 的 NFS 服務全面凍結近 6 分鐘。因此:單一檔案救急用 Copy-out 取回,整目錄回滾必須安排停機維護窗口。
| 參數項目 | 設定值 | 架構考量與實務依據 |
|---|---|---|
| 工作類型 | RTRR 單向同步(主 NAS $\to$ 次要 NAS) | 產出實體可直接讀取的原始檔案。若使用 QuDedup 產生 .qdff 封裝檔,還原時強烈依賴 HBS 專用解鎖工具,增加災難復原時的變數。 |
| 目的地規劃 | 次要 NAS 專用目錄 | 次要 NAS 必須先安裝 HBS 3 並啟用 RTRR 服務。嚴禁將來源目錄平鋪在目的地既有共享資料夾根目錄下,否則還原時將無法整批拉回(演練 3 踩坑驗證)。 |
| 網路介面綁定 | 手動指定 10GbE 網卡 | 主 NAS 具備多張同網段網卡(含 2.5GbE 與 10GbE)。HBS 3 預設會自動選擇虛擬交換器,必須調閱工作日誌確保流量走在 10GbE 高速通道上。 |
| 執行排程 | 每日 04:00 | 等待 01:30 的 HDP 備份完全落盤後,同步副本才能包含當天最新的 HDP 備份版本。 |
| 備份前先建快照 | 強制開啟 | 非開不可。同步過程抓取快照版本,才能保證 VM 磁碟在複製時具備 Crash-Consistent。演練 4 證實:未勾選此項時,複製出來的 qcow2 存在 54 處內部元數據損壞。 |
| 偵測疏鬆檔案 (Sparse File) | 開啟 | VM 虛擬磁碟規格配置為 477 GiB、實際使用 70 GiB,未開啟此項會導致數百 GB 的無效空區塊經由網路全量傳輸。 |
| 刪除多餘檔案 | 開啟 | 保持目的地為來源端的鏡像副本,多版本保存工作全面轉交給次要 NAS 的 ZFS 排程快照。 |
| 傳輸加密 | 關閉 | 兩台設備皆位於內部受信任專用 VLAN,開啟傳輸層加密將大幅消耗 TS-464 較弱的 CPU 資源,影響 10GbE 吞吐效能。 |
| 完整性檢查 | 每週日執行完整檢查 | 摒棄僅校驗屬性的「快速檢查」,落實全量校驗以確保區塊一致性。 |
架構設計精髓:解耦「同步」與「版本」
本設計將「多版本管理」的責任從備份軟體層抽離,轉移到底層 ZFS 快照。即使主端不幸在清晨被勒索軟體加密,單向同步在 04:00 將受損檔案同步過去,次要 NAS 在前一天 05:00 建立的底層唯讀快照依然完好無損。這也是次要 NAS 快照保留期設定為 14 份的原因。
面對資料安全,摒棄口號式的宣稱,透過嚴格的標準實事求是地審視目前架構:
| 3-2-1-1-0 準則 | 標準要求 | 本地 Homelab 場域現況 | 達成狀態 |
|---|---|---|---|
| 3 | 保留 3 份完整資料副本 | 1. 主 NAS 原始資料2. 次要 NAS 鏡像副本3. 雲端物件儲存(Day 18 規劃) | 🟡 本日達成 2 份 |
| 2 | 存放在 2 種不同儲存媒體 | 兩台設備本質皆為旋轉磁頭傳統硬碟(HDD)。雖擁有獨立機箱、獨立電源、獨立 RAID/ZFS 控制器,但嚴格定義上並非異質媒體。 | 🟡 部分達成 |
| 1 | 1 份異地保存備份 | 預計於 Day 18 透過外移至 Google Cloud Storage / AWS S3 實現。 | 🔴 未達成 |
| +1 | 具備 1 份離線或不可變備份 | Day 16 的 Linux 本地不可變屬性僅能保護新 pack 檔,唯有 Day 18 導入 S3 Object Lock 才能真正防禦內部提權攻擊。 | 🔴 未達成 |
| +0 | 還原驗證 0 錯誤 | 演練 1 至 3 資料校驗全數通過,演練 4 首度同步出的虛擬磁碟出現 54 個 qcow2 錯誤,啟用快照重跑後降至 0。 | 🟡 部分達成(需驗證才算) |
不同於虛擬機可以透過監控「VM 進入 running 狀態」來判定復原成功,共享目錄的還原需要量測資料一致性、屬性維持度與客戶端掛載反應。為此客製了三支量測工具:
share-canary.sh(金絲雀探針):
fsync,內部維持一個 64 MiB 的測試負載檔(Payload)及其 SHA256 校驗碼。verify 模式支援快照目錄、副本目錄或原地回滾後的即時目錄,不進行寫入。replica-verify.sh(副本一致性校驗器):
restore-drill.sh(自動化計時與審計引擎):
beats.log 出現 $\to$ Canary 驗證通過 $\to$ Manifest 全量校驗無誤。本次演練建立獨立的共享資料夾 Drill(配置 100 GB Thin Provisioning),內含金絲雀探針與 20 個 1 GB 的隨機二進位資料檔,配置每小時快照,並排入 HBS 3 同步工作。
環境隔離的盲點
演練 2 證實:建立獨立共享目錄僅隔離了資料內容,並沒有隔離儲存控制層的衝擊。 當執行整個共享目錄快照回滾時,NAS 核心會暫停 NFS 守護程序,導致同台 NAS 上其他無關的 Production 業務一同中斷。
| 演練項目 | 觸發時間 (T0) | 判定還原點 | 檔案出現 | Canary 通過 | Manifest 通過 | 實測 RTO | 實測 RPO | 傳輸速率 | 結果 |
|---|---|---|---|---|---|---|---|---|---|
| 1. 快照目錄取回單檔 | 14:00:32Z | 14:00:01Z | 0s | 31s | 69s | 31s | 31s | - | PASS |
| 2. 整體目錄快照回滾 | 13:38:49Z | 13:00:01Z | 0s | 653s | 694s | 694s | 1799s | - | PASS |
| 3. 次要 NAS 逆向拉回 | 14:22:55Z | 14:14:01Z | - | 99s | 684s | 684s | 534s | 47.7 MiB/s | PASS |
| 4. 副本磁碟即刻開機 | 15:35:24Z | 15:14:14Z | - | - | - | 33s | 1270s | - | PASS |
Drill/canary/payload.bin。cp -p 將檔案自快照目錄 @Recently-Snapshot/GMT+08_2026-10-01_2200/canary/ 複製回原處。[22:00:32] 用戶端刪除檔案,觸發監控計時 -------------------+ (T0)
[22:00:42] NAS 本地完成 cp -p 與 sync (耗時 10 秒) |
[22:01:03] 用戶端 Canary 通過驗證 (耗時 31 秒) ------------+--> 實質 RTO = 31s
[22:01:41] 22 份檔案全量 Manifest 通過 (耗時 69 秒)
actimeo)前持續認定檔案不存在。向業務端承諾 RTO 時,必須以客戶端真正能存取的時間為準,不能以儲存端命令執行結束為準。
CANARY_KIND=frozen 環境變數。| 時間 (UTC+8) | 距操作時間 | 系統事件與客戶端實測反應 |
|---|---|---|
| 21:38:49 | 0s | 儲存總管記錄開始回滾,系統提示「回復期間將暫停相關服務」。 |
| 21:38:49 ~ 21:42:00 | 0 ~ 191s | 用戶端讀取依然正常(約 500 MB/s),Canary 探針仍正常寫入心跳。 |
| 21:42:01 | 192s | 客戶端 I/O 突然凍結,O_DIRECT 讀取迴圈連續三次觸發 120 秒逾時中斷。 |
| 21:45:01 | 372s | 客戶端 Linux 核心印出警告:nfs: server <主 NAS> not responding。 |
| 21:47:57 | 548s | 核心印出 nfs: server OK,連線自動復原,此時讀取到的已是還原後檔案。 |
| 21:48:01 | 552s | NAS 事件日誌標記快照回滾作業完成。 |
| 21:50:23 | 694s | 全量 Manifest 校驗無誤,5 個被刪除的舊檔全數歸位,新寫入的 5 GB 檔案消失。 |
實測指標結算:
- 實際復原時間 (RTO):694 秒(約 11.5 分鐘)
- 資料遺失窗口 (RPO):1,799 秒(約 30 分鐘,即 21:30 - 21:00)
Drill,卻同樣在 21:45 噴出 nfs server not responding。這證實 QuTS hero 在重啟 NFS 服務時是全域停止,導致其他掛載 Public 的運作中虛擬機與容器連帶陷入約 6 分鐘的 I/O 停頓。任何共享目錄的回滾操作,都必須視為全機維護等級的重大事件!
Drill/data 與 Drill/canary,模擬全損。[22:22:55] 刪除主 NAS 資料目錄 (T0)
[22:23:16] 觸發次要 NAS 逆向同步
[22:23:20] ❌ 任務失敗中斷!報錯:Folder pairs are invalid or inaccessible
[22:23:56] 手動登入主 NAS,建立空的 data/ 與 canary/ 目錄結構
[22:24:28] 重新啟動同步作業
[22:32:51] 資料傳輸完畢 (傳輸 429 秒,平均速率 47.7 MiB/s)
[22:34:19] Manifest 完整性驗證通過 (總 RTO = 684s,RPO = 534s)
vm:100(Windows 11 工作站,磁碟實際佔用 70.3 GiB),驗證直接利用次要 NAS 副本開機的可行性。VM 9100,將磁碟路徑指向該副本並觸發開機。在首次同步時,刻意關閉「備份前先建快照」選項,檔案傳輸順利結束且 HBS 3 標記綠色打勾。隨後在 PVE 上使用 qemu-img check 對該副本進行底層結構校驗:
qemu-img check /mnt/pve/secondary-nas/images/100/vm-100-disk-0.qcow2
| 檢查對象 | 內部結構錯誤 (Errors) | 洩漏叢集 (Leaked Clusters) | 狀態判定 |
|---|---|---|---|
運作中原檔(使用 -U 強制唯讀檢視) |
0 | 3 | 結構正常 |
| 未開快照同步之副本 | 54 | 3 | ❌ 映像檔損毀 (Corrupted) |
| 開啟快照同步之副本 | 0 | 3 | ✅ 結構完全一致 |
技術剖析:為什麼備份軟體顯示成功,磁碟卻壞了?
第一次同步耗時 20 分鐘,虛擬機在運作中持續向記憶體與磁碟寫入。qcow2格式包含分配對應表(L1/L2 Table)與參考計數表(Refcount Table)。
當 HBS 3 直接以傳統檔案層級進行讀取時,這兩張元數據表是在不同時間點被複製的,導致副本內部產生自相矛盾的指標(refcount=0 reference=1)。此時拿該磁碟開機,作業系統一旦配置新區塊,QEMU 將發生重疊覆蓋寫入,造成災難性的靜默資料損壞。
結論:同步運作中的虛擬機磁碟,備份軟體必須具備底層快照能力,確保鏡像具備崩潰一致性(Crash-Consistent)。
開啟快照重新同步後,校驗結果為 0 錯誤。隨後執行正式開機演練:
[23:34:57] vm:100 透過 Guest Agent 正常關機 (耗時 26 秒)
[23:35:24] 寫入 VM 9100 虛擬硬體設定並點擊開機 ------------+ (T0)
[23:35:26] PVE qm start 命令成功返回 (耗時 2 秒) |
[23:35:34] Windows 核心記錄 Boot 啟動事件 (耗時 10 秒) |
[23:35:41] NTFS 日誌校驗完畢,宣告檔案系統健康健全 |
[23:35:59] QEMU Guest Agent 回應,成功取得原 IP 位址 -------+--> 實質 RTO = 33s
指標結算:
- 復原時間目標 (RTO):33 秒(Day 16 HDP 全量還原需 569 秒,大幅縮減 94%)
- 資料復原點 (RPO):1,270 秒(約 21 分鐘,取決於前一次快照同步時間點)
Windows 事件檢視器記錄了預期的 Kernel-Power 41 與 EventLog 6008,這正是典型的 Crash-Consistent 狀態。此方案能在 33 秒內拉起服務,但代價是該 VM 隨後的所有 I/O 都承載在次要 NAS 的 2.5 吋硬碟上,效能將顯著受限。
經歷實戰演練,簡單提出五項維運的原則:
qemu-img check。演練 4 驗證了資料層級的掛載,但尚未模擬「主 NAS 硬體實體燒毀」的場景。相關準備工作已納入 outage-checklist.md,幾個不可忽略的架構依賴包含:
share-canary.sh verify,心跳日誌的斷層區間就是最精確的業務停機時間。所有量測工具已開源並整理於專案倉庫中,可依照以下流程進行驗收:
# 取得維運檢驗工具包
git clone https://github.com/ivanusto/nas-backup-drill && cd nas-backup-drill
# 1. 執行唯讀安全性盤點(產出 Markdown 審計報告)
NAS=user@primary-nas ./nas-audit.sh > audit-primary.md
NAS=user@secondary-nas ./nas-audit.sh > audit-secondary.md
# 2. 在掛載了 NFS 的工作節點部署監控探針
sudo ./share-canary.sh install /mnt/drill/canary
# 3. 演練前生成全量校驗 Manifest
./replica-verify.sh manifest /mnt/drill > drill.sha256
# 4. 在按下儲存端還原的瞬間,啟動自動化計時與完整性檢驗
./restore-drill.sh /mnt/drill/canary \
--label "3. 從次要 NAS 還原" \
--failed-at 2026-10-02T03:10:00Z \
--manifest drill.sha256
# 5. NAS 本地端快照點精確時間驗證(避開 NFS 盲區,剛建立之快照指定 frozen)
ssh user@primary-nas "CANARY_KIND=frozen sh -s verify /share/Drill/@Recently-Snapshot/GMT+08_2026-10-01_2200/canary" < share-canary.sh
0:驗證完全通過(PASS)2:Canary Payload 校驗碼不符(Data Corruption)3:輪詢逾時,檔案未能在時限內出現(Timeout)4:Manifest 檔案數量或內容比對失敗(Incomplete Restore)已經在兩台實體設備間打通了具備 Crash-Consistent 的備份機制,但目前的架構依然無法防禦整座機房的實體災難。
Day 18|3-2-1 的最後一步:異地物件儲存、S3 Object Lock 與冷熱資料成本精算
明天將媒體庫外移至 Google Cloud Storage 與 AWS S3,利用真正的 Object Lock 實現無法篡改的「WORM 不可變性」,同時深入計算雲端儲存的 API 請求與傳輸隱藏成本,並制定具備成本效益的異地重建計畫。