
「備份的證據除了看到管理介面上的綠燈,更重要的是還原成功的那一刻。」
在 [Day 15] 中,我把核心 VM 遷移至 NAS 的 NFS 共享儲存,並透過 HA 故障轉移演練,測試出節點斷電後,VM 在另一台主機重啟前存在 205.8 秒 的寫入空窗。
但必須認清一個現實:HA(高可用性)處理的是節點硬體損毀,不處理磁碟內容損毀。
當 VM 內部的資料遭到勒索軟體加密、被工程師誤刪、或因錯誤的組態發布搞爛系統時,HA 只會忠實且迅速地在另一台節點上,把那個「已經壞掉的磁碟」重新跑起來。這一層災難必須仰賴備份,而備份只有在還原成功的那一刻,才算真正存在。
這個環節採用最近較熱門且新的 HDP (Hybrid Backup Center) for Business Beta,關鍵理由有三:
這篇文章聚焦專注三個問題:這個場域備什麼、原則表每個數字的依據、以及還原演練如何精確量化為 RTO 與 RPO。 文中所有資料,皆為本場域實測獲得。
📦 本篇實作程式碼: pve-backup-drill
內含兩支測試腳本與演練紀錄範本。腳本不依賴 HDP,是通用的,適合 IT 與維運人員應用在各種資訊環境中使用,無論底層採用 PBS、Veeam 還是自建 restic 皆可通用。
備份清單從 Day 15 的資源清單出發。在實際將 PVE 叢集接入 HDP 後,發現了預期之外的落差:
| 保護對象 | 虛擬磁碟所在 | HDP 備份支援 | 現況說明與處理策略 |
|---|---|---|---|
| 叢集上的 VM | NAS 的 NFS | 支援 | HDP 以 root 經 SSH 連上叢集,可自動列出並保護每一台 VM。 |
| 叢集上的 LXC 容器 | NAS 的 NFS | ❌ 無法 | 盤點缺口。 叢集有 5 台 VM、15 個容器,HDP 僅回報 vmCount: 5,LXC 完全不在清單內。 |
| QDevice VM | NAS 本機(Virtualization Station) | 不納入 | 無狀態仲裁節點,故障時可於 10 分鐘內依腳本重建(見 Day 15)。 |
| PVE 節點本身 | 實體節點本機 | 不納入 | 依 Day 11 基線重灌,/etc/pve 設定由叢集其餘在線節點自動同步。 |
LXC 不在保護名單:
本場域的容器負責內部 DNS 解析與過濾,雖然設定極輕量且具備組態腳本,但「無法被 HDP 保護」是既定事實。這件事必須白紙黑字寫進維運原則表,切忌給團隊「整個叢集都有備份」的錯覺。
自動保護規則(Auto-Protect)的地雷:
HDP 提供「自動將新發現的 VM 納入預設備份原則」的功能。實測新建一台 VM,重整後確實會自動納管,對動態環境很方便。
但它也會把不該動的正式 VM 強行排程: 在規則啟用下,場域內一台 488 GB 與一台 250 GB 的正式 VM 被自動排進每天 09:00 的預設原則。當我想停用該規則時,API 對 enabled: false 回傳 HTTP 200,後台狀態卻毫無改變。最後只能以手動方式把那幾個 Workload 逐一停用。
維運決策: 正式環境停用全域自動保護,所有納管項目一律依原則表逐台審查加入。此外,還原演練產生的測試 VM 也會被自動納管,演練結束後務必刪除對應 Workload,避免隔天排程對已刪除的 VM 報錯。
HDP for Business 的管理伺服器與備份儲存庫,與 Day 13、Day 14 的 AI 模型庫共用同一台 QuTS hero NAS(h6.0.2.3591),更關鍵的是,VM 運行中的 NFS 磁碟也在同一個儲存池(Storage Pool)。
┌────────────────────────────────────────────────────────┐
│ 單一 NAS (QuTS hero) │
│ ┌────────────────────────────────────────────────────┐ │
│ │ 同一個實體儲存池 (Pool 1) │ │
│ │ ┌───────────────────────┐ ┌───────────────────┐ │ │
│ │ │ VM 運行中磁碟 (NFS) │ │ HDP 備份儲存庫 │ │ │
│ │ │ [ 正本資料 ] │ │ [ WORM 不可變副本] │ │ │
│ │ └───────────┬───────────┘ └─────────▲─────────┘ │ │
│ └──────────────┼────────────────────────┼────────────┘ │
└────────────────┼────────────────────────┼──────────────┘
│ (故障/加密/誤刪) │ (還原路徑)
▼ │
┌─────────────┐ │
│ PVE Cluster ├─────────────────┘
└─────────────┘
風險揭露:
正本與備份在同一個儲存池,一旦實體磁碟群組(RAID)崩潰或硬體損毀,兩份資料會一起消失。
因此,本機這一份備份僅能防範三件事:客體內勒索軟體加密、人為誤刪、錯誤的程式與資料變更。
至於實體機房與硬體層級的容災,是 Day 17(NAS 快照與 3-2-1)與 Day 18(異地副本)的工作。
維運團隊在面對資安與維運稽核時,最怕被問「為什麼是這個數字呢?」答不出來的數字,在稽核時會很麻煩,因此我將規格梳理成 policy.md:
| 項目 | 設定值 | 具體依據與設計考量 |
|---|---|---|
| 原則類型 | 不可變(Immutable) | 建立後無法改回一般原則,必須一開始決定。啟用底層 WORM 機制。 |
| 排程頻率 | 每日 01:30(首次完整,其後增量) | 避開 NAS 自身維護作業:01:00 釋放快取、02:00 qfstrim、03:00 惡意程式掃描與 vs_refresh。01:30 夾在中間,32 GB 的 VM 增量備份不到 1 分鐘即可完成。 |
| 保留週期 | 30 天(每日一版,共 30 版) | 不可變原則僅支援依「天數」保留,設定「版本數」會被系統靜默忽略。30 天涵蓋一個月的變更單回溯期(Day 26),亦涵蓋勒索軟體常見的潛伏期。覺得太多就改成10天到14天。 |
| 不可變期間 | 30 天(與保留相同) | 每個版本寫入後強制鎖定 30 天,期間任何管理者權限皆無法刪除。天數也可以刪減改短一天的天數。 |
| 備份驗證 | 啟用,120 秒 | 每次備份後開機錄製畫面,作為 Day 27 的稽核證據。 |
| Airgap+ | ❌ 不啟用 | Airgap+ 會在非備份時段將備份伺服器關機。但該 NAS 同時承載 NFS、QDevice 與模型庫,關機將直接導致 PVE 叢集全面停擺(Day 15 演練 3)。 |
| 異地副本 | 預留欄位 | 留待 Day 18 異地不可變物件儲存整合。 |
備份完成後,HDP 會將該版本新寫入的檔案設為唯讀,並將檔案的存取時間(atime)改為到期時間。
但請務必注意:不可變鎖定的範圍僅限「該版本新寫入的 pack 檔案」。 實查整個 restic 儲存庫結構:
| 儲存庫目錄/範圍 | 檔案數量 | 佔用空間 | 鎖定狀態 |
|---|---|---|---|
| 演練 VM 3 個版本新寫入的資料 | 164 個 pack 檔 | 2,703.9 MiB | 唯讀(鎖定至 10/30) |
| 先前其他 Workload 共用的舊資料 | 4,208 個 pack 檔 | 69,781.2 MiB | 可讀寫(未鎖定) |
儲存庫核心:config、keys/、舊 index |
23 個檔案 | 約 6 MiB | 可讀寫(未鎖定) |
演練 VM 去重後的總佔用為 2,831.6 MiB,比新鎖定的空間多了約 128 MiB。這 128 MiB 是與先前其他工作負載共用的舊 pack,它們並不會被補鎖。更關鍵的是,restic 解鎖儲存庫必備的 config 與 keys/ 同樣保持可寫。
這代表本機不可變保護的是新增的資料區塊,而非整個儲存庫防毀。完整的防篡改防線必須仰賴 Day 18 的異地 Object Lock。
備份管理介面顯示綠燈,絕不代表系統能順利還原。之前的排程備份中,兩台正式 VM 在主控台回報失敗,原因在於 HDP API 連續回傳 500,備份工作根本沒能派送進 Bareos 核心。
要確認備份有效性,唯一的途徑就是實做還原,並客觀量化指標:
為了消除人工看錶估算的誤差,實作了兩支自動化驗證腳本:
[ 演練開始 (T0) ]
│
┌──────────────────┴──────────────────┐
▼ ▼
[ 原 VM 硬關機 ] [ restore-drill.sh ]
(模擬實體硬體損毀) │ (每 2 秒輪詢一次)
├─ 1. VM 出現在叢集設定中
├─ 2. VM 狀態轉為 running
├─ 3. 網路回應 ping
├─ 4. SSH 22 埠開放
▼
[ SSH 執行 canary.sh verify ]
│
├─ 補寫心跳 (消弭 60s 誤差)
├─ 尋找 >180s 之最後中斷點
├─ 計算精確 RPO
├─ 校驗 64MiB Payload SHA256
▼
[ 計算整體 RTO ]
fsync,確保快照前資料已確實刷入磁碟。canary.sh verify:
在按下還原的瞬間同步啟動。以 2 秒為週期依序偵測五大事件:
running 狀態canary.sh verify
RTO 的終點是 canary 驗證通過
若採用 HDP 即時還原(開在 NAS 的 Virtualization Station),則附加 --no-pve 參數略過 PVE 前置檢查。
演練 VM 規格:Debian 13、2 vCPU、2 GB RAM,32 GB 的 qcow2 格式虛擬磁碟置於 NFS 上,系統實體佔用約 3 GB(包含 1 GiB 隨機資料、0.9 GB 可壓縮文字與作業系統核心)。
| 版本 | 操作內容 | 備份類型 | Bareos 讀取量 | Bareos 耗時 | 工作總時間 | 去重後累計佔用 |
|---|---|---|---|---|---|---|
| Ver 1 | 初始基準版本 | 完整 | 32.75 GB | 5 分 06 秒(107 MB/s) | 6 分 01 秒 | 1.68 GB |
| Ver 2 | 客體內寫入 1 GiB 隨機檔 | 增量 | 1.084 GB | 14 秒 | 57 秒 | 2.76 GB |
| Ver 3 | 客體關機重開,寫入 200 MiB | 增量 | 324.2 MB | 7 秒 | 32 秒 | 2.97 GB |
| Ver 4 | 改為靜態 IP,重開機 | 增量 | 122.5 MB | 6 秒 | 32 秒 | 2.97 GB |
qcow2 關機後重開依然具備增量追蹤能力(CBT):qcow2 關機重開後,第三次備份依然維持增量備份(僅讀取 324.2 MB)。 透過 qemu-img info 檢驗虛擬磁碟,可以看到 dirty bitmap 是以 Bareos 工作名稱直接持久化在 qcow2 檔案結構內部,而 raw 映像檔則無此元數據結構。qcow2 格式。若使用 raw,每次關機後的備份都將面臨數十分鐘的漫長全備份。演練資料彙整自 drill-log.md,時間基準採 UTC,秒數從觸發模擬故障(按下還原)起算:
| 演練項目 | 精確還原點 | ping 通 | ssh 開 | 實測 RTO | 實測 RPO | 演練結果與關鍵備註 |
|---|---|---|---|---|---|---|
| 1. 即時還原(DHCP) | 15:05:02Z | 逾時 | 逾時 | 未完成 | 222 s | FAIL。IP 漂移,控制面失敗。 |
| 1'. 即時還原重做(靜態 IP) | 15:34:02Z | 113 s | 115 s | 118 s | 97 s | OK。118 秒恢復對外服務。 |
| 2. 即時還原轉為永久 | 15:34:02Z | 不中斷 | 不中斷 | 187 s (背景) | 97 s | OK。轉換過程 0 秒中斷。 |
| 3. 完整還原回 NFS 叢集 | 15:34:02Z | 568 s | 568 s | 569 s | 784 s | OK。全機回滾,抓出光碟依賴坑。 |
| 4. 還原第 1 版(最舊不可變) | 14:49:01Z | 527 s | 529 s | 530 s | 4,104 s | OK。證明鎖定版可還,資料點精確。 |
即時還原預設使用 IDE 磁碟與 VirtIO 網卡,沿用原 VM 的 MAC 位址還原最新版本。時間序如下:
[+0s] 原 VM 強制關機(模擬故障),發動即時還原
[+108s] HDP 介面回報「即時還原成功」
[+121s] 客體核心開機完畢
[+130s] sshd 服務啟動
[+132s] 客體自 DHCP 取得 IP —— 但拿到了不同的 IP 位址!
雖然 MAC、DHCP Client ID 與主機金鑰完全一致,DHCP 伺服器仍然指派了全新位址。控制腳本 restore-drill.sh 依原 IP 偵測不到回應而判定逾時。在真實災難中,這就是標準的「監控面板全是綠燈,外部連線全面中斷」。
事後透過 Console 登入客體執行 canary.sh verify:
15:05:02Z(備份開始前最後一筆心跳)。問題二:硬體時鐘(RTC)快 8 小時
分析心跳紀錄時,赫然發現一筆時間戳記為23:11:01Z,比真實世界快了整整 8 小時!
原來 Virtualization Station 將 NAS 本地時間當成 UTC 拋給客體虛擬機,導致客體開機初期使用錯誤時間寫入心跳,直到 41 秒後 NTP 校時完成才回歸正常。
由於canary.sh verify演算法採取「最後一個中斷點」,還原點並未失真,但斷層時間出現了偽造的 29,159 秒。這正是驗證工具必須納入 NTP 檢查的原因。
關鍵結論: 具備即時災備需求的 VM,絕對不能使用動態 DHCP,必須於作業系統層配置靜態 IP 或在路由器綁定 DHCP 靜態保留。
在 VM 內將 cloud-init 網路設定停用(network: {config: disabled}),改以 Netplan 配置 DHCP 範圍外的固定 IP,確認重開機組態未被覆蓋後,執行 Ver 4 備份並重做演練:
15:34:02Z,RPO 97 秒,RTO 118 秒!
洞察: HDP 主控台顯示成功是在第 87 秒,但服務實際可用是在第 118 秒,兩者存在 31 秒的空窗差。唯有 end-to-end 腳本驗證,才能抓出真正的 RTO。
即時還原出來的 VM 是以 FUSE 掛載備份映像檔、外掛 Overlay 層承接寫入運行。若要長期運作,必須「轉為永久」,因此要將其轉換至 NAS 上的獨立共用資料夾:
canary.sh 驗證還原點不變,客體無需重開機。維運隱患:
- 此 VM 落地於 NAS 的 Virtualization Station,不受 PVE HA 機制保護。
- 轉換後的 VM 在 Virtualization Station 預設為「自動啟動」,一旦 NAS 重開,它會開機並搶佔正式 VM 的 IP!演練驗證完畢必須立刻刪除。
- HDP 介面無法直接刪除轉為永久的 VM,需至 Virtualization Station 刪除,且其虛擬磁碟檔案會殘留在共用資料夾內,需手動清理。
選取最新備份版本,直接還原為 PVE 叢集上的新虛擬機,磁碟指回 NFS 儲存。
還原精靈設定避坑:
[+23s] VM 建立於叢集,HDP 指派新 VMID 104
[+555s] 32 GB 資料完整寫回 NFS 完畢
[+557s] VM 進入 running 狀態
[+568s] 通訊恢復(ping 通、22 埠開放)
[+569s] canary.sh 驗證通過,RTO 569 秒,RPO 784 秒
NFS 寫入吞吐量約為 64 MB/s(32 GiB 耗時 535 秒),遠慢於備份讀取時的 107 MB/s。據此推算,488 GB 的正式 VM 完整還原至少需要 2.1 小時。
發現 Cloud-Init 磁碟跨 VM 依賴陷阱
檢查還原出來的 VM 104 設定時發現:其 Cloud-Init 光碟磁碟機,竟然依然指向原 VM 920 的vm-920-cloudinit.qcow2!
如果在真正的災難中原 VM 磁碟已毀,或演練後管理者直接刪除原 VM,這台還原出來的虛擬機就會遺失開機磁碟。
更危險的是:若你在新 VM 上點擊「移除該光碟」,PVE 會直接把底層檔案刪掉,也就是直接把原 VM 的 Cloud-Init 磁碟幹掉!
處置SOP: 還原完成後,必須立刻執行qm cloudinit update <新VMID>重新生成獨立設定檔,嚴禁直接移除。
選取 Ver 1(首次完整備份,底層鎖定至30天後),驗證不可變限制是否會阻礙還原作業:
14:49:01Z。此數值恰好比演練 3 增加了 3,320 秒,完美吻合兩次備份的時間差。這證明了不可變備份在面臨勒索軟體全盤毀損時,確實能提供可信賴的時光回溯能力。
雖然 Ver 1、Ver 2 的自動開機影片驗證成功(耗時約 144 秒),但 Ver 3、Ver 4 卻在 4 秒內閃退失敗,報錯 Virtualization Station is not responding(但同一時間 VS 運作完全正常)。這再次印證:稽核不能單看「功能有開」,必須逐次檢視驗證結果,警惕無影片存證的空白版本。
每一次的還原演練,本質上都是對生產環境或共享儲存的高負載寫入,必須視同正式變更作業(符合 Day 26 規範):
drill-log.md 的演練數據記錄。drills.jsonl 的機器可讀自動化結果。在每台受保護的 VM 內部署金絲雀監控腳本:
git clone https://github.com/ivanusto/pve-backup-drill && cd pve-backup-drill
sudo ./canary.sh install
關閉原 VM 同時,在控制端啟動自動化量測腳本。
auto,透過 --name 比對新機名稱):
./restore-drill.sh auto 192.168.10.50 \
--name debian-drill-recovered \
--label "3. 完整還原" \
--failed-at 2026-10-02T03:10:00Z
--no-pve 略過 PVE 狀態檢查):
./restore-drill.sh vs 192.168.10.50 \
--no-pve \
--label "1. 即時還原" \
--failed-at 2026-10-02T03:10:00Z
退出碼定義:
0代表成功驗證無誤,2代表 Payload SHA256 校驗失敗(資料受損),3代表連線逾時。
Day 17 焦點拉回 儲存設備 本身。
今天的備份儲存庫、Day 13 的 AI 模型庫、以及 Day 8 建立的所有容器持久化卷,全都依託在同一台 NAS 上。當這台 NAS 本身遭遇浩劫時該如何應對? 將剖析 QuTS hero 的快照機制、HBS 3 的排程策略,並動手執行 NAS 端的 3-2-1 還原演練計時。