MON Migration Runbook
本文件提供跨資料中心 Ceph 遷移的 MON / control-plane 切換手冊,聚焦於 quorum 驗證、Rook external mode client endpoint coordination、ceph-csi behavior,以及 KubeVirt / VM 在 MON endpoint 變更期間的驗證。
關於遷移策略的分析與決策依據,請參考 Solutions Overview。關於 OSD bulk data migration 的詳細步驟,請參考 OSD Migration Runbook。關於場景與架構概述,請參考 主文件。
High-Level Flow
flowchart LR
subgraph CEPH["Ceph cluster"]
direction LR
A[備份設定與健康檢查] --> B[新增 dc2 MON 節點]
E[移除 dc1 MON 節點]
F[最終健康確認]
end
subgraph K8S["K8s cluster"]
direction LR
C["⏳ 等待 Rook Operator<br/>自動同步 ConfigMap"] -.1-2分鐘.-> D[驗證 csi-rbdplugin logs]
H[驗證 VM I/O 正常]
end
B --> C
D --> H
H --> E
E --> F
style CEPH fill:#e6ffed,stroke:#2f855a,stroke-width:1.5px
style K8S fill:#e8f1ff,stroke:#3b82f6,stroke-width:1.5px
style C fill:#fff4e6,stroke:#ed8936,stroke-width:2px
預期耗時:8-10 分鐘
核心原則
- Add-Before-Remove Strategy
- 先新增 dc2 MON 節點,擴大 quorum(暫時從 3 增至 4、5、6)
- 驗證新 MON 節點在 quorum 中且穩定
- 確認 client 端已使用新 endpoint 後,再移除 dc1 MON 節點
- Quorum Safety
- MON quorum 需多數決(3 個中至少 2 個,5 個中至少 3 個)
- 新增 MON 時,quorum 容錯能力提升(暫時可容忍更多節點失效)
- 移除 MON 前必須確認剩餘節點數仍能滿足 quorum 要求
- Client Endpoint Coordination
- Rook-Ceph external mode 透過
rook-ceph-mon-endpointsConfigMap 與 Secret 傳遞 MON 地址 rook-ceph-config/mon_host必須反映新 MON endpoint 集合- Rook Operator Auto-Sync (v1.14+): 當 Ceph cluster 的 MON 拓撲變更時,Rook operator 會自動更新 ConfigMaps,無需手動編輯
- 切換策略:先加後減,再提早切到 dc2-only(先讓 client 吃到 dc1 + dc2,再於 Ceph 側移除前先清理 dc1 endpoints)
- 兩者(
rook-ceph-mon-endpoints與rook-ceph-config/mon_host)都應先完成 dc2-only 收斂,再執行 Ceph cluster 的 dc1 MON 移除 - ceph-csi / librbd 通常能透過 Ceph 的 monmap gossip 學到新 MON;ConfigMap 變更則主要影響 pod 啟動或 reconnect 時讀取到的
ceph.conf - 若自動更新失效,則採用分批重啟 CSI pods 而非全面重啟
- Rook-Ceph external mode 透過
- 最小化業務影響
- MON failover 通常在數秒內完成,對 RBD I/O 的影響極小
- KubeVirt VM 通常能透過 librbd 內建的 MON failover 機制自動恢復
- 重點驗證:VM 在 MON endpoint 切換期間是否持續正常 I/O
- Timeout 調整屬於環境特定的驗證項目,非預設強制要求
2. Rook-Ceph External Mode / KubeVirt Notes
Rook-Ceph External Mode 連線架構
在本場景中,KubeVirt VM 透過以下路徑連線至 Ceph cluster:
KubeVirt VM (guest OS)
↓
virt-launcher pod (KubeVirt operator)
↓
ceph-csi (csi-rbdplugin DaemonSet)
↓
Rook-Ceph external mode (ConfigMap & Secret)
↓
Ceph MON endpoints (external Ceph cluster)
Rook-Ceph External Mode ConfigMap / Secret
Rook external mode 使用以下兩個 Kubernetes resources 傳遞 Ceph cluster 連線資訊:
rook-ceph-mon-endpointsConfigMap- 包含 MON endpoint 地址清單
- 格式範例:
mon1=10.1.1.1:6789,mon2=10.1.1.2:6789,mon3=10.1.1.3:6789 - 更新策略:先擴充為 dc1 + dc2,驗證 client 正常後,再收斂為 dc2-only
rook-ceph-configConfigMap- 包含
ceph.conf的 client-side 配置 - 其中
mon_host欄位必須反映新 MON endpoint 集合 - 更新策略:先擴充為 dc1 + dc2,驗證 client 正常後,再收斂為 dc2-only
- 驗證重點:確認
mon_host先包含新 MON endpoint 集合,之後再收斂為僅剩 dc2
- 包含
ceph-csi Behavior
- 動態學習路徑:
csi-rbdplugin內的 librbd client 通常會透過 Ceph 的 monmap gossip 學到新 MON endpoints - ConfigMap 角色:
rook-ceph-mon-endpoints/rook-ceph-config主要影響 pod 啟動或 reconnect 時讀到的ceph.conf - 驗證方式:檢查
csi-rbdpluginpod logs 與 pod 內連線行為,確認目前連線已穩定落在預期的 MON endpoint 集合 - 失效處置:若自動更新失效,則採用分批重啟 CSI pods(避免同時重啟所有 pods 造成短暫服務中斷)
KubeVirt VM 影響評估
MON endpoint 切換期間 VM 行為:
- Short MON Failover Disturbance
- librbd(Ceph RBD client library)內建 MON failover 機制
- 當 current MON 失效或地址變更時,librbd 會自動嘗試連線至其他 MON
- 典型 failover 時間:數秒內完成
- I/O Continuity
- 只要至少一個 MON 可達,RBD I/O 能繼續正常運作
- MON 主要負責 cluster map 發布與 auth,不參與 data path
- 驗證重點:VM 在 MON endpoint 切換期間是否持續正常 I/O
- Timeout Tuning (Optional)
- 若環境對 MON failover 延遲敏感(如關鍵交易系統),可考慮調整
rbd_default_timeout - 此為環境特定驗證項目,非預設強制要求
- 建議先執行 pilot test,觀察實際 failover behavior 再決定是否調整
- 若環境對 MON failover 延遲敏感(如關鍵交易系統),可考慮調整
監控重點
- Ceph 層面:
ceph mon stat:確認 MON quorum 狀態ceph -s:確認 cluster health 與 MON election 狀態
- Rook / ceph-csi 層面:
- 檢查
rook-ceph-mon-endpointsConfigMap 是否已更新 - 檢查
rook-ceph-config的mon_host欄位 - 檢視
csi-rbdpluginpod logs,確認 MON connection 正常
- 檢查
- KubeVirt / VM 層面:
- VM guest OS 的 disk I/O latency(如透過
iostat或應用監控) - KubeVirt virt-launcher pod 的 resource usage
- 若有應用層 SLA,確認 latency 與 throughput 仍在可接受範圍
- VM guest OS 的 disk I/O latency(如透過
3. Detailed MON Migration Runbook
本節詳述 MON migration 的完整執行步驟,包含 Ceph 端 add-before-remove 與 client endpoint 提前切到 dc2-only 的 coordination checkpoints。
🔄 Change Flow
本 runbook 推薦使用以下流程進行 MON migration。此流程依賴 Rook operator v1.14+ 的自動同步功能,無需手動編輯 ConfigMaps。
執行步驟
- Step 0:執行前置檢查
- Step 1:Ceph 端 host add 和 placement 配置(
ceph orch host add+ceph orch apply mon/mgr) - Step 2:等待 Rook operator 自動同步 + 驗證 csi-rbdplugin & VM I/O(新 6 MON endpoints)
- Step 3:Disable dc1 MON daemons(逐步縮減 placement 至 dc2-only)
- Step 4:等待 Rook operator 自動同步 + 驗證 csi-rbdplugin(dc2-only endpoints)
- Step 5:Remove dc1 MONs from Cluster(
ceph orch host rm)
預期總耗時:8-10 分鐘
環境需求:
- Rook operator 版本 ≥ v1.14
- auto-sync 功能已啟用(預設為啟用)
若需完整手動控制:
- 若 Rook operator 未自動更新 ConfigMaps(logs 無相關記錄)或版本 < v1.14
- 需要精細控制 client endpoint 切換時序
- 環境複雜或有多個 Kubernetes cluster 連線至同一 Ceph cluster
- 此時可執行手動 ConfigMap 更新進行介入
Step 0: Pre-Migration Backup and Validation
目標:確保 MON quorum 健康、備份關鍵配置、記錄 baseline
| Precheck (檢查項目 / 使用指令 / 原因) |
Action (節點 / 指令) |
Postcheck (預期結果 / Rollback) |
|---|---|---|
| MON Quorum 健康 遷移前 cluster 必須 HEALTH_OK,確認 quorum 完整 |
Ceph admin 節點ceph mon statceph quorum_status -f json-pretty |
預期結果:ceph mon stat + ceph quorum_status -f json-pretty - quorum = 3/3 且 HEALTH_OK |
| 備份 Rook ConfigMap / Secret 保留還原點,遷移失敗時可快速恢復 |
K8s admin 節點export BACKUP_DATE=$(date +%Y%m%d)kubectl -n rook-ceph get configmap rook-ceph-mon-endpoints -o yaml > /backup/rook-ceph-mon-endpoints.${BACKUP_DATE}.yamlkubectl -n rook-ceph get configmap rook-ceph-config -o yaml > /backup/rook-ceph-config.${BACKUP_DATE}.yamlkubectl -n rook-ceph get secret rook-ceph-mon -o yaml > /backup/rook-ceph-mon-secret.${BACKUP_DATE}.yaml |
預期結果:ls -l /backup/rook-ceph-*.yaml - 3 份備份檔案存在且可讀 |
| 記錄當前 MON endpoints 作為後續對比與 rollback 基準 |
K8s admin 節點kubectl -n rook-ceph get configmap rook-ceph-mon-endpoints -o jsonpath='{.data.data}'kubectl -n rook-ceph get configmap rook-ceph-config -o jsonpath='{.data.ceph\.conf}' \| grep mon_host |
預期結果:kubectl -n rook-ceph get configmap rook-ceph-mon-endpoints -o jsonpath='{.data.data}' - 已記錄 dc1 endpoint 清單 |
| 確認 dc2 MON 候選主機已就緒 確保 cephadm 已可管理 dc2 節點,且 location metadata 正確 |
Ceph admin 節點ceph orch host lsceph orch ls mon -f yaml |
預期結果:ceph orch host ls - mon-dc2-01/02/03 出現在 host 清單且 metadata 正確 |
| 記錄 Client Workload 清單 確認受影響的 csi-rbdplugin pods 與 KubeVirt VM |
K8s admin 節點kubectl -n rook-ceph get pods -l app=csi-rbdpluginkubectl get vmi -A |
預期結果:kubectl -n rook-ceph get pods -l app=csi-rbdplugin + kubectl get vmi -A - Pod/VM 清單已完整記錄 |
Step 1: Add dc2 MONs to Cluster
目標:將 dc2 MON 候選主機加入 orchestrator,並指定 MON/MGR 角色到所有 6 個節點
cephadm note: 本 Step 分兩階段執行:
- 使用
ceph orch host add逐一將 dc2 節點(mon-dc2-01 / 02 / 03)加入 orchestrator host 清單- 使用
ceph orch apply mon與ceph orch apply mgr指定完整 6 台節點的 placement
| Precheck (檢查項目 / 使用指令 / 原因) |
Action (節點 / 指令) |
Postcheck (預期結果 / Rollback) |
|---|---|---|
dc2 節點尚未在 orchestrator 清單中ceph orch host ls 確認,避免重複添加,IP / hostname 正確 |
Ceph admin 節點ceph orch host add mon-dc2-01 192.168.1.14ceph orch host add mon-dc2-02 192.168.1.15ceph orch host add mon-dc2-03 192.168.1.16 |
預期結果:ceph orch host ls - 6 台節點全出現在 orchestrator 清單 |
6 台節點全在 host 清單中ceph orch host ls 確認,apply placement 前所有節點必須就緒 |
Ceph admin 節點ceph orch apply mon --placement="mon-dc1-01 mon-dc1-02 mon-dc1-03 mon-dc2-01 mon-dc2-02 mon-dc2-03"sleep 120ceph orch apply mgr --placement="mon-dc1-01 mon-dc1-02 mon-dc1-03 mon-dc2-01 mon-dc2-02 mon-dc2-03"sleep 60 |
預期結果:ceph mon stat - quorum = 6,且 dc2 三台 MON 皆在 quorumRollback: ceph orch apply mon --placement="mon-dc1-01 mon-dc1-02 mon-dc1-03"Rollback: ceph orch apply mgr --placement="mon-dc1-01 mon-dc1-02 mon-dc1-03" |
Step 2: Wait for Rook Operator Auto-Sync and Verify I/O
目標:等待 Rook operator 自動同步 ConfigMaps(反映 6 MON 拓撲),並確認 csi-rbdplugin 與 VM I/O 正常
⚠️ Rook Operator Auto-Sync Note (v1.14+): 當 Ceph cluster MON 拓撲變更後,
rook-ceph-mon-endpoints與rook-ceph-config的mon_host會自動同步更新。 先確認 operator logs 是否已自動更新;若已更新,跳過手動介入部分。
| Precheck (檢查項目 / 使用指令 / 原因) |
Action (節點 / 指令) |
Postcheck (預期結果 / Rollback) |
|---|---|---|
| Step 1 quorum = 6 已確認 Rook operator 在 MON 拓撲變更後 1-2 分鐘自動同步 ConfigMap |
K8s admin 節點 等待 1-2 分鐘後 kubectl logs -n rook-ceph deployment/rook-ceph-operator --tail=50 \| grep -i monkubectl -n rook-ceph get configmap rook-ceph-mon-endpoints -o jsonpath='{.data.data}' |
預期結果:kubectl -n rook-ceph get configmap rook-ceph-mon-endpoints -o jsonpath='{.data.data}' - 包含 6 個 MON endpoints(dc1 + dc2)Rollback: kubectl -n rook-ceph edit configmap rook-ceph-mon-endpoints |
| 確認 rook-ceph-config mon_host 已更新 csi-rbdplugin reconnect 時讀取 ceph.conf,mon_host 必須含 dc1 + dc2 |
K8s admin 節點kubectl -n rook-ceph get configmap rook-ceph-config -o jsonpath='{.data.ceph\.conf}' \| grep mon_host |
預期結果:kubectl -n rook-ceph get configmap rook-ceph-config -o jsonpath='{.data.ceph\.conf}' \| grep mon_host - mon_host 含 dc1 + dc2 地址Rollback: kubectl -n rook-ceph edit configmap rook-ceph-config |
| 確認 csi-rbdplugin 已吸收新 MON endpoints | K8s admin 節點kubectl -n rook-ceph logs -l app=csi-rbdplugin --tail=50 \| grep -i mon |
預期結果:kubectl -n rook-ceph logs -l app=csi-rbdplugin --tail=50 \| grep -i mon - logs 顯示已連線新 MON endpointsRollback: kubectl -n rook-ceph delete pod <pod>(分批,每批間隔 30s) |
| csi-rbdplugin 可連線至 Ceph cluster 確認 client 端已可 reach dc2 MON |
K8s admin 節點 → exec 進 csi-rbdplugin podkubectl -n rook-ceph exec -it <csi-rbdplugin-pod> -- bashceph -s --conf=/etc/ceph/ceph.conf --keyring=/etc/ceph/keyring |
預期結果:ceph -s --conf=/etc/ceph/ceph.conf --keyring=/etc/ceph/keyring - 正常回傳且無連線錯誤 |
| VM I/O 正常(關鍵驗證) MON endpoint 切換期間 VM 不應有 I/O 中斷 |
VM guest OSvirtctl console <vm-name> -n <namespace>dd if=/dev/zero of=/tmp/test.dat bs=1M count=100iostat -x 1 5 |
預期結果:dd + iostat -x 1 5 - VM I/O 正常,無錯誤與明顯延遲Rollback: ceph orch apply mon --placement="mon-dc1-01 mon-dc1-02 mon-dc1-03"Rollback: ceph orch apply mgr --placement="mon-dc1-01 mon-dc1-02 mon-dc1-03" |
Step 3: Disable dc1 MON Daemons
目標:逐步縮減 MON placement 至 dc2-only,移除 dc1 MON daemons
策略:分三 Phase 逐個移除 dc1 MON(6→5→4→3),每 Phase 驗證 quorum 穩定後再進行下一步
| Precheck (檢查項目 / 使用指令 / 原因) |
Action (節點 / 指令) |
Postcheck (預期結果 / Rollback) |
|---|---|---|
| csi-rbdplugin 已切到新 endpoints(Step 2 gate 通過) 確認 client-side 已穩定,quorum 目前 = 6 |
Ceph admin 節點 Phase 1 — 移除 mon-dc1-01 ceph orch apply mon --placement="mon-dc1-02 mon-dc1-03 mon-dc2-01 mon-dc2-02 mon-dc2-03"ceph orch apply mgr --placement="mon-dc1-02 mon-dc1-03 mon-dc2-01 mon-dc2-02 mon-dc2-03"sleep 120 |
預期結果:ceph mon stat + ceph health detail - quorum = 5 且 HEALTH_OKRollback: ceph orch apply mon --placement="mon-dc1-01 mon-dc1-02 mon-dc1-03 mon-dc2-01 mon-dc2-02 mon-dc2-03"Rollback: ceph orch apply mgr --placement="mon-dc1-01 mon-dc1-02 mon-dc1-03 mon-dc2-01 mon-dc2-02 mon-dc2-03" |
Phase 1 quorum = 5 已確認ceph mon stat 驗證,確保穩定後再繼續 |
Ceph admin 節點 Phase 2 — 移除 mon-dc1-02 ceph orch apply mon --placement="mon-dc1-03 mon-dc2-01 mon-dc2-02 mon-dc2-03"ceph orch apply mgr --placement="mon-dc1-03 mon-dc2-01 mon-dc2-02 mon-dc2-03"sleep 120 |
預期結果:ceph mon stat + ceph health detail - quorum = 4 且 HEALTH_OKRollback: ceph orch apply mon --placement="mon-dc1-02 mon-dc1-03 mon-dc2-01 mon-dc2-02 mon-dc2-03"Rollback: ceph orch apply mgr --placement="mon-dc1-02 mon-dc1-03 mon-dc2-01 mon-dc2-02 mon-dc2-03" |
Phase 2 quorum = 4 已確認ceph mon stat 驗證,確保穩定後再繼續 |
Ceph admin 節點 Phase 3 — 移除 mon-dc1-03(完全切至 dc2) ceph orch apply mon --placement="mon-dc2-01 mon-dc2-02 mon-dc2-03"ceph orch apply mgr --placement="mon-dc2-01 mon-dc2-02 mon-dc2-03"sleep 120 |
預期結果:ceph mon stat + ceph health detail - quorum = 3(全為 dc2)且 HEALTH_OKRollback: ceph orch apply mon --placement="mon-dc1-03 mon-dc2-01 mon-dc2-02 mon-dc2-03"Rollback: ceph orch apply mgr --placement="mon-dc1-03 mon-dc2-01 mon-dc2-02 mon-dc2-03" |
Step 4: Verify Rook Operator Auto-Sync (dc2-only)
目標:等待 Rook operator 自動同步 ConfigMaps 以反映 dc2-only MON 拓撲,並確認 csi-rbdplugin 正常
| Precheck (檢查項目 / 使用指令 / 原因) |
Action (節點 / 指令) |
Postcheck (預期結果 / Rollback) |
|---|---|---|
| Step 3 quorum = 3(dc2-only)已確認 Rook operator 在 MON 拓撲變更後 1-2 分鐘自動同步 ConfigMap |
K8s admin 節點 等待 1-2 分鐘後 kubectl logs -n rook-ceph deployment/rook-ceph-operator --tail=50 \| grep -i monkubectl -n rook-ceph get configmap rook-ceph-mon-endpoints -o jsonpath='{.data.data}' |
預期結果:kubectl -n rook-ceph get configmap rook-ceph-mon-endpoints -o jsonpath='{.data.data}' - 僅包含 dc2 MON endpoints(3 個)Rollback: kubectl -n rook-ceph edit configmap rook-ceph-mon-endpoints |
| 確認 rook-ceph-config mon_host 已更新為 dc2-only ceph.conf mon_host 必須只含 dc2 地址 |
K8s admin 節點kubectl -n rook-ceph get configmap rook-ceph-config -o jsonpath='{.data.ceph\.conf}' \| grep mon_host |
預期結果:kubectl -n rook-ceph get configmap rook-ceph-config -o jsonpath='{.data.ceph\.conf}' \| grep mon_host - mon_host 僅含 dc2 地址Rollback: kubectl -n rook-ceph edit configmap rook-ceph-config |
| VM I/O 正常(關鍵驗證) MON endpoint 切換期間 VM 不應有 I/O 中斷 |
VM guest OSvirtctl console <vm-name> -n <namespace>dd if=/dev/zero of=/tmp/test.dat bs=1M count=100iostat -x 1 5 |
預期結果:dd + iostat -x 1 5 - VM I/O 正常,無錯誤與明顯延遲Rollback: ceph orch apply mon --placement="mon-dc2-01 mon-dc2-02 mon-dc2-03 mon-dc1-03"Rollback: ceph orch apply mgr --placement="mon-dc2-01 mon-dc2-02 mon-dc2-03 mon-dc1-03" |
Step 5: Remove dc1 MONs from Cluster
目標:確認 dc1 無其他 daemon 後,從 orchestrator 中移除 dc1 主機
| Precheck (檢查項目 / 使用指令 / 原因) |
Action (節點 / 指令) |
Postcheck (預期結果 / Rollback) |
|---|---|---|
| Step 4 gate 通過,csi-rbdplugin 連線至 dc2-only 確認 dc1 節點無其他非 MON daemon(如 OSD / MGR) |
Ceph admin 節點ceph orch ps \| grep mon-dc1確認無殘留 daemon 後: ceph orch host rm mon-dc1-01ceph orch host rm mon-dc1-02ceph orch host rm mon-dc1-03 |
預期結果:ceph orch host ls + kubectl -n rook-ceph get configmap rook-ceph-mon-endpoints -o jsonpath='{.data.data}' - dc1 主機已移除且 endpoint 為 dc2-only |
相關連結
-
← 回到主文件
返回 Ceph Cross-DC Migration 主題入口,查看場景說明與架構圖 -
→ OSD Migration Runbook
前往 OSD runbook,執行 rack-by-rack 的資料搬遷、recovery 與移除流程 -
→ Migration Strategy Comparison
回到策略比較頁,查看為何此場景建議先做 OSD migration,再處理 MON migration