
事故管理:Runbook 與 Post-mortem 模板
流程概覽
flowchart LR A[偵測<br/>Detection] --> B[分級<br/>Triage] B --> C[應變<br/>Response] C --> D[解決<br/>Resolution] D --> E[覆盤<br/>Postmortem] E --> F[預防<br/>Prevention] F -->|持續改善| A style A fill:#F44336,color:#fff style B fill:#FF9800,color:#fff style C fill:#FFC107,color:#000 style D fill:#4CAF50,color:#fff style E fill:#2196F3,color:#fff style F fill:#9C27B0,color:#fff
文章概覽
在本篇文章中,您將學習到:
- 為什麼每一個生產系統都終將面臨故障,差別只在於你準備得多充分
- 事故的完整生命週期:從偵測到預防的閉環流程
- 事故嚴重等級(P1-P4)的分類標準與應對時效
- On-call 輪值制度的設計原則與公平性考量
- Runbook 的撰寫規範與常見範例
- Blameless Post-mortem 的文化建設與實務範本
- 5 Whys 根因分析法的應用
- 災難復原演練(DR Drill)的執行方式
引言:每個生產系統都會故障,差別在於你準備得多好
在軟體工程的世界裡,有一個不變的真理:生產環境一定會出問題。 無論你的程式碼多麼嚴謹、測試覆蓋率多麼高、基礎設施多麼冗餘,故障終將發生。硬碟會壞、網路會斷、第三方服務會停擺、人為操作會出錯。
差別不在於故障會不會發生,而在於:
- 你能多快發現問題? 是使用者打電話來抱怨,還是你的監控系統在使用者受到影響之前就發出告警?
- 你能多快解決問題? 是手忙腳亂地 Google 搜尋解法,還是打開預先準備好的 Runbook 按步驟執行?
- 你能從故障中學到什麼? 是責怪犯錯的人然後不了了之,還是透過結構化的 Post-mortem 找出系統性問題並徹底改善?
成熟的工程團隊不會試圖消除所有故障(這是不可能的),而是建立一套完善的事故管理流程,讓團隊在面對故障時能夠冷靜、有序、高效地應對,並從每一次故障中持續學習與改進。
事故生命週期
一個完整的事故管理流程包含六個階段,形成一個持續改善的閉環:
flowchart LR A[偵測<br/>Detection] --> B[分級<br/>Triage] B --> C[應變<br/>Response] C --> D[解決<br/>Resolution] D --> E[覆盤<br/>Post-mortem] E --> F[預防<br/>Prevention] F -->|回饋改善| A style A fill:#F44336,color:#fff style B fill:#FF9800,color:#fff style C fill:#FFC107,color:#000 style D fill:#4CAF50,color:#fff style E fill:#2196F3,color:#fff style F fill:#9C27B0,color:#fff
- 偵測(Detection):透過監控告警、用戶回報或自動化檢測發現異常
- 分級(Triage):評估影響範圍與嚴重程度,決定應對層級
- 應變(Response):啟動應對流程,指派事故指揮官,開始排查與修復
- 解決(Resolution):實施修復措施,確認服務恢復正常
- 覆盤(Post-mortem):進行根因分析,撰寫事故報告,產出改善行動項目
- 預防(Prevention):執行行動項目,更新 Runbook,改善監控與告警
每一次故障都是改善系統的機會。這個閉環的關鍵在於最後一步(預防)的輸出會反饋到第一步(偵測),讓系統的可靠性隨著時間不斷提升。
核心概念
事故嚴重等級(Severity Levels)
並非所有事故都同等重要。明確的嚴重等級定義,讓團隊能夠根據影響程度分配適當的資源與關注度。
| 等級 | 名稱 | 定義 | 範例 | 回應時間 | 更新頻率 |
|---|---|---|---|---|---|
| P1 | Critical | 核心服務完全中斷,大量用戶受影響 | 主資料庫掛掉、全站無法存取、支付系統全面失敗 | 15 分鐘內 | 每 15 分鐘 |
| P2 | Major | 核心功能嚴重降級,部分用戶受影響 | API 回應時間超過 10 秒、部分區域無法登入、搜尋功能異常 | 30 分鐘內 | 每 30 分鐘 |
| P3 | Minor | 非核心功能異常,少數用戶受影響 | 推播通知延遲、報表匯出失敗、後台管理某功能錯誤 | 4 小時內 | 每日 |
| P4 | Low | 不影響服務的小問題 | UI 顯示瑕疵、日誌格式錯誤、非關鍵告警誤報 | 下個工作日 | 視需要 |
嚴重等級的判定應基於以下維度:
- 影響範圍:受影響的用戶數量或比例
- 業務影響:是否影響核心營收或關鍵業務流程
- 資料風險:是否有資料遺失或損毀的風險
- 時間敏感度:問題是否會隨時間持續惡化
On-call 輪值制度
On-call 是事故管理的第一道防線。設計良好的 On-call 制度,能確保任何時候都有人能夠回應告警並處理事故。
公平輪值的設計原則:
- 輪值週期:建議以一週為單位輪值,避免單次 on-call 時間過長造成疲勞
- 至少兩層:Primary(主要)和 Secondary(備援),Primary 無法回應時自動升級到 Secondary
- 補休機制:週末或假日的 on-call 值班應給予對等的補休時間
- 跨時區團隊:如果團隊分布在不同時區,利用 follow-the-sun 模式,讓每個時區只需負責其工作時段
- 新人保護期:新加入的工程師應有至少 2-4 週的 shadow 期,跟隨資深工程師學習後才正式加入輪值
升級路徑(Escalation Path):
告警觸發
└─→ On-call Primary(5 分鐘無回應)
└─→ On-call Secondary(10 分鐘無回應)
└─→ Team Lead / Engineering Manager(15 分鐘無回應)
└─→ VP of Engineering / CTO
以下是一份 On-call 輪值表範本:
# On-call 輪值表 — 2024 Q4
## 輪值規則
- 輪值週期:每週一 09:00 至下週一 09:00(UTC+8)
- 回應時間:P1 事故 15 分鐘內、P2 事故 30 分鐘內
- 升級時限:Primary 5 分鐘未回應自動升級到 Secondary
- 補休規則:週末/假日值班可補休等時數
## 輪值表
| 週次 | 日期範圍 | Primary | Secondary | 備註 |
|------|----------|---------|-----------|------|
| W40 | 09/30 - 10/06 | Alice | Bob | |
| W41 | 10/07 - 10/13 | Bob | Charlie | 國慶連假,加強關注 |
| W42 | 10/14 - 10/20 | Charlie | David | |
| W43 | 10/21 - 10/27 | David | Alice | |
| W44 | 10/28 - 11/03 | Alice | Bob | |
| W45 | 11/04 - 11/10 | Bob | Charlie | |
| W46 | 11/11 - 11/17 | Charlie | David | 雙十一大促,全員待命 |
| W47 | 11/18 - 11/24 | David | Alice | |
## 升級路徑
1. Primary On-call
2. Secondary On-call
3. Team Lead:Emily(電話:0912-xxx-xxx)
4. Engineering Manager:Frank(電話:0923-xxx-xxx)
## 聯繫方式
- 告警通知管道:PagerDuty → Slack #incidents → 電話
- 事故溝通頻道:Slack #incident-war-room
- 狀態頁面:https://status.example.com事故指揮官(Incident Commander)
在 P1 或 P2 事故中,必須有一位明確的事故指揮官(Incident Commander, IC)來協調所有應對行動。IC 的角色不是親自動手修復問題,而是統籌全局,確保正確的人在做正確的事。
IC 的核心職責:
- 宣告事故:確認事故等級,啟動對應的應對流程
- 組建應對團隊:根據問題類型召集相關領域的工程師
- 任務分派:將排查與修復工作分配給團隊成員,避免重複勞動
- 狀態同步:定期(每 15 分鐘)向利害關係人更新進展
- 決策裁定:當團隊對修復方案有分歧時,做出最終決定
- 記錄時間軸:確保所有關鍵事件和決策都被記錄下來(供 Post-mortem 使用)
- 宣告恢復:確認問題已解決,服務恢復正常後,結束事故狀態
IC 輪值建議: IC 通常由資深工程師或 Tech Lead 輪流擔任,與 On-call 輪值獨立排班。在規模較小的團隊中,On-call Primary 可以同時兼任 IC。
事故期間的溝通
事故發生時,清晰的溝通與資訊透明是降低混亂的關鍵。
內部溝通:
- 開設專屬的事故頻道(例如
#incident-2024-1015-db-outage),所有討論集中在此 - 避免在多個管道同時討論,造成資訊碎片化
- IC 定期發送結構化的狀態更新:目前狀況 → 正在做什麼 → 下一步 → 預計恢復時間
外部溝通:
- 狀態頁面(Status Page):如 Statuspage.io 或自建狀態頁面,讓使用者自行查看服務狀態
- 社群媒體:在官方 Twitter/X 帳號發布簡短狀態更新
- 客戶通知:對於企業客戶,透過專屬管道(Slack Connect、Email)進行主動通知
- 內部利害關係人:透過 Email 或 Slack 通知業務、客服、管理層,提供影響範圍與預計恢復時間
溝通範本 — 狀態更新:
[事故更新 — YYYY-MM-DD HH:MM]
等級:P1
狀態:調查中 / 已識別 / 修復中 / 已解決
摘要:
[簡述目前狀況]
影響範圍:
[受影響的服務/功能/用戶群]
目前行動:
[團隊正在進行的排查或修復工作]
預計恢復時間:
[如可預估則提供,否則說明下次更新時間]
下次更新時間:HH:MM
Runbook:事故處理的操作手冊
什麼是 Runbook?
Runbook 是一份逐步操作指引,記錄了處理特定已知問題的標準流程。它的核心價值在於:
- 降低 MTTR(Mean Time To Recovery):不需要從頭排查,按照已知步驟快速修復
- 消除人員依賴:即使最熟悉系統的工程師不在,其他人也能按照 Runbook 處理問題
- 減少人為錯誤:在壓力下,人容易做出錯誤判斷;有了 Runbook,按步驟執行即可
- 知識傳承:將團隊累積的實戰經驗系統化地記錄下來
Runbook 的結構
一份好的 Runbook 應該具備以下結構:
# Runbook:[問題標題]
## 基本資訊
- **嚴重等級**:P1 / P2 / P3 / P4
- **影響服務**:[受影響的服務名稱]
- **最後更新**:YYYY-MM-DD
- **維護者**:[姓名 / 團隊]
- **相關告警**:[對應的告警規則名稱或 ID]
## 症狀(Symptoms)
描述觸發此 Runbook 的症狀,讓 on-call 工程師能快速判斷是否適用。
- 告警訊息:`[具體的告警內容]`
- 用戶反映:[用戶可能回報的現象]
- 監控表現:[Grafana dashboard 上的異常指標]
## 影響評估(Impact Assessment)
- 受影響的用戶群體
- 受影響的功能
- 是否有資料遺失風險
- 問題是否會持續惡化
## 診斷步驟(Diagnosis)
按順序執行以下步驟,找出問題的根因:
### 步驟 1:確認服務狀態
```bash
# 檢查服務是否正在執行
kubectl get pods -n production -l app=<service-name>
# 查看最近的日誌
kubectl logs -n production <pod-name> --tail=100步驟 2:檢查依賴服務
# 檢查資料庫連線
psql -h <db-host> -U <user> -d <database> -c "SELECT 1;"
# 檢查 Redis 連線
redis-cli -h <redis-host> ping步驟 3:檢查資源使用狀況
# 檢查 CPU 和 Memory
kubectl top pods -n production -l app=<service-name>
# 檢查磁碟空間
df -h解決步驟(Resolution)
根據診斷結果,選擇對應的修復方案:
情境 A:服務程序崩潰
# 重啟服務
kubectl rollout restart deployment/<service-name> -n production
# 確認重啟成功
kubectl rollout status deployment/<service-name> -n production情境 B:資源不足
# 擴展 Pod 數量
kubectl scale deployment/<service-name> -n production --replicas=<N>情境 C:需要回滾
# 查看部署歷史
kubectl rollout history deployment/<service-name> -n production
# 回滾到上一版本
kubectl rollout undo deployment/<service-name> -n production驗證(Verification)
修復後,執行以下步驟確認服務已恢復:
- 服務健康檢查通過:
curl -s https://api.example.com/health - 錯誤率恢復正常(< 0.1%)
- 回應時間恢復正常(P99 < 200ms)
- 告警已自動解除
- 抽查用戶功能正常
升級條件(Escalation)
如果以上步驟無法解決問題,請升級處理:
- 30 分鐘內無法恢復 → 通知 Team Lead
- 1 小時內無法恢復 → 通知 Engineering Manager
- 涉及資料遺失 → 立即通知 CTO + 法務
參考資料
- [系統架構圖連結]
- [相關的 Post-mortem 報告]
- [相關的設計文件]
#### 常見 Runbook 範例
以下是幾個生產環境中最常見的問題情境,每個團隊都應該預先準備對應的 Runbook:
**1. 服務無法存取(Service Down)**
主要症狀:健康檢查失敗、HTTP 5xx 錯誤率飆升、使用者回報無法連線。
診斷方向:
- 檢查 Pod / Container 狀態,是否有 OOMKilled 或 CrashLoopBackOff
- 檢查最近是否有部署變更(git log、deployment history)
- 確認上游依賴(資料庫、快取、第三方 API)是否正常
- 查看應用程式日誌中的 error / fatal 訊息
常見修復:重啟服務、回滾到上一版本、擴展 Pod 數量。
**2. 磁碟空間滿(Disk Full)**
主要症狀:磁碟使用率告警(> 90%)、服務開始回傳 I/O 錯誤、資料庫無法寫入。
診斷方向:
- `df -h` 確認哪個磁碟分區已滿
- `du -sh /var/log/*` 找出佔用空間最大的目錄
- 檢查日誌輪替(logrotate)是否正常運作
- 確認是否有異常的大檔案或未清理的暫存檔
常見修復:清理過期日誌、刪除暫存檔、擴展磁碟容量、修復 logrotate 設定。
**3. 資料庫連線耗盡(Database Connection Exhausted)**
主要症狀:應用程式回傳 "too many connections" 錯誤、新請求被拒絕、連線池等待超時。
診斷方向:
- `SELECT count(*) FROM pg_stat_activity;` 查看當前連線數
- `SELECT * FROM pg_stat_activity WHERE state = 'idle in transaction';` 檢查是否有長時間未釋放的連線
- 檢查應用程式的連線池設定(pool size、idle timeout)
- 確認是否有慢查詢佔用連線過久
常見修復:終止 idle 連線、調整連線池設定、優化慢查詢、增加最大連線數。
**4. SSL/TLS 憑證過期(Certificate Expired)**
主要症狀:瀏覽器顯示安全警告、HTTPS 連線失敗、API 呼叫回傳 SSL 錯誤。
診斷方向:
- `openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates` 檢查憑證有效期
- 確認自動續約(如 Let's Encrypt / cert-manager)是否正常運作
- 檢查是否有中繼憑證遺失(chain certificate)
常見修復:手動更新憑證、修復自動續約機制、設定憑證到期前 30 天的提醒告警。
---
### Post-mortem:從故障中學習
#### Blameless Post-mortem 文化
Post-mortem 的目的是**從系統層面找出問題並改善**,而不是追究個人責任。如果團隊文化中,犯錯的人會被懲罰,那麼人們就會傾向隱藏錯誤、避免揭露真正的根因,最終導致問題反覆發生。
**Blameless 文化的核心原則:**
1. **人會犯錯,系統不應依賴人不犯錯**:如果一個人為操作失誤能導致嚴重事故,那問題在於系統缺乏足夠的防護機制,而不在於那個人
2. **專注於「如何」而非「誰」**:討論「這件事是如何發生的」和「我們的系統如何讓這件事有可能發生」,而非「是誰做錯的」
3. **鼓勵透明**:讓所有參與者感到安全,願意完整揭露事件經過,包括自己的失誤
4. **錯誤是學習機會**:每一次故障都讓我們更了解系統的弱點,這些知識極其寶貴
**實務做法:**
- Post-mortem 文件中不提及具體人名,使用角色描述(如「on-call 工程師」、「部署者」)
- Post-mortem 會議由非直接相關的人主持,確保客觀
- 將重點放在行動項目(Action Items)上——**我們要改變什麼,讓同樣的問題不再發生?**
#### Post-mortem 模板
以下是一份完整的 Post-mortem 報告範本:
```markdown
# Post-mortem 報告:[事故標題]
## 基本資訊
- **事故編號**:INC-YYYY-NNNN
- **事故等級**:P1 / P2 / P3
- **事故日期**:YYYY-MM-DD
- **事故時長**:X 小時 Y 分鐘
- **事故指揮官**:[角色]
- **報告撰寫人**:[角色]
- **報告日期**:YYYY-MM-DD
## 摘要(Summary)
以 2-3 句話簡述發生了什麼事、影響範圍、以及如何解決。
> 範例:2024 年 10 月 15 日 14:00-16:30,由於資料庫主節點的磁碟空間耗盡,
> 導致核心 API 服務無法處理寫入請求,約 60% 的用戶在此期間無法完成訂單。
> 問題在清理過期日誌並擴展磁碟容量後解決。
## 影響(Impact)
- **受影響時間**:HH:MM - HH:MM(共 X 分鐘)
- **受影響服務**:[列出受影響的服務]
- **受影響用戶數**:約 XX,XXX 人(佔總用戶 XX%)
- **業務影響**:
- 訂單流失:約 XXX 筆
- 營收損失:約 $XXX
- SLA 違約:是 / 否
- **資料影響**:是否有資料遺失或損毀
## 時間軸(Timeline)
所有時間以 UTC+8 表示。
| 時間 | 事件 |
|------|------|
| 13:45 | 磁碟使用率告警觸發(> 90%) |
| 13:50 | On-call 工程師收到告警,開始調查 |
| 14:00 | 資料庫主節點磁碟 100%,開始拒絕寫入 |
| 14:05 | API 錯誤率開始飆升,健康檢查失敗 |
| 14:10 | 升級為 P1 事故,指派事故指揮官 |
| 14:15 | 開設 #incident-2024-1015-db-disk 頻道 |
| 14:20 | 識別根因:未清理的慢查詢日誌佔用 50GB |
| 14:30 | 開始清理過期日誌 |
| 14:45 | 磁碟空間釋放至 60%,資料庫恢復寫入 |
| 15:00 | API 服務恢復正常,錯誤率降至基準線 |
| 15:30 | 提交磁碟擴展申請,容量從 100GB 增至 200GB |
| 16:00 | 磁碟擴展完成 |
| 16:30 | 確認所有指標穩定,宣告事故結束 |
## 根因分析(Root Cause Analysis)
### 直接原因
資料庫主節點的慢查詢日誌(slow query log)未設定 logrotate,
持續累積至佔滿磁碟空間。
### 根本原因
1. 資料庫伺服器的 logrotate 設定在上次遷移時遺漏
2. 磁碟使用率的告警門檻設為 90%,留給反應的時間不足
3. 沒有針對磁碟增長速率的趨勢告警
### 5 Whys 分析
1. **為什麼服務中斷?** → 資料庫無法寫入
2. **為什麼資料庫無法寫入?** → 磁碟空間已滿
3. **為什麼磁碟空間會滿?** → 慢查詢日誌持續增長未被清理
4. **為什麼日誌未被清理?** → logrotate 設定遺漏
5. **為什麼 logrotate 設定會遺漏?** → 伺服器遷移的 checklist 中未包含日誌管理的驗證項目
## 經驗教訓(Lessons Learned)
### 做得好的地方
- 告警在服務完全中斷前 15 分鐘就觸發了
- On-call 工程師在 5 分鐘內開始回應
- 根因識別迅速(20 分鐘內完成)
- 團隊溝通順暢,利害關係人及時收到通知
### 需要改善的地方
- 磁碟告警門檻 90% 太高,反應時間不足
- 沒有標準化的伺服器遷移 checklist
- 缺乏磁碟增長趨勢的預測性告警
### 意外收穫
- 發現另外兩台伺服器也有相同的 logrotate 遺漏問題,及時修復
## 行動項目(Action Items)
| # | 行動項目 | 優先級 | 負責人 | 到期日 | 狀態 |
|---|----------|--------|--------|--------|------|
| 1 | 所有 DB 伺服器加入 logrotate 設定 | P0 | DBA 團隊 | 10/18 | 完成 |
| 2 | 磁碟告警門檻調整為 75%,增加 60% 預警 | P0 | SRE 團隊 | 10/18 | 完成 |
| 3 | 新增磁碟增長速率的趨勢告警 | P1 | SRE 團隊 | 10/25 | 進行中 |
| 4 | 建立伺服器遷移標準 checklist | P1 | Infra 團隊 | 10/31 | 待開始 |
| 5 | 撰寫「磁碟空間滿」Runbook | P1 | On-call 團隊 | 10/25 | 進行中 |
| 6 | 排程季度性的磁碟容量審查 | P2 | SRE 團隊 | 11/15 | 待開始 |
## 附錄
- [相關的 Grafana Dashboard 截圖]
- [告警記錄連結]
- [Slack 事故頻道存檔]
5 Whys 根因分析法
5 Whys 是一種簡單但極其有效的根因分析技術。透過連續追問「為什麼」,從表面症狀逐步深入到根本原因。
使用原則:
- 從事實出發:第一個「為什麼」應該基於可觀察的事實,而非假設
- 不要太早停下:如果答案仍然是技術層面的,繼續往下追問;真正的根因通常是流程或文化層面的
- 不要分叉太多:每一層選擇最主要的原因繼續追問,避免發散成一棵樹
- 每一層都要有證據:「因為 X」這個回答需要有日誌、指標或其他證據支持
- 通常 3-5 層就夠了:不需要機械式地一定要問 5 次,重點是找到可以改善的根因
範例:API 回應時間異常
- 為什麼 API 回應時間超過 5 秒? → 資料庫查詢耗時過久
- 為什麼資料庫查詢耗時過久? → 某張表缺少必要的索引,進行了全表掃描
- 為什麼會缺少索引? → 新的查詢模式在 feature 開發時被加入,但沒有對應的索引
- 為什麼沒有建立對應的索引? → Code Review 流程中沒有包含資料庫查詢效能的檢查項目
- 為什麼 Code Review 沒有這個檢查項目? → 團隊缺乏資料庫效能相關的 Review checklist
行動項目:建立 Code Review checklist,加入「資料庫查詢效能」檢查項,要求所有新增的查詢都必須附上 EXPLAIN 分析結果。
行動項目的追蹤與跟進
Post-mortem 最常見的失敗模式是:報告寫完了,行動項目沒有人追蹤,然後同樣的問題再次發生。
確保行動項目落地的做法:
- 每個行動項目都有明確的負責人和到期日:不寫「團隊一起做」,而是指定一個具體的負責人
- 行動項目進入正式的工作追蹤系統:將行動項目建立為 Jira ticket 或 GitHub Issue,而非只存在於 Post-mortem 文件中
- 定期檢視進度:在每週的團隊會議中花 5 分鐘回顧未完成的行動項目
- 設定完成標準:每個行動項目應有明確的「完成」定義,而非模糊的「改善 XX」
- 季度回顧:每季度統計行動項目的完成率,識別系統性的執行瓶頸
事故嚴重等級分類表
以下整理一份更完整的分類參考表,可以直接作為團隊的分級標準使用:
| 維度 | P1 (Critical) | P2 (Major) | P3 (Minor) | P4 (Low) |
|---|---|---|---|---|
| 用戶影響 | > 50% 用戶受影響 | 10-50% 用戶受影響 | < 10% 用戶受影響 | 幾乎無感 |
| 功能影響 | 核心功能完全不可用 | 核心功能嚴重降級 | 非核心功能異常 | 細微問題 |
| 營收影響 | 直接營收損失 | 間接營收影響 | 潛在營收影響 | 無營收影響 |
| 資料風險 | 資料遺失或損毀 | 資料可能不一致 | 低風險 | 無風險 |
| 回應要求 | 立即、全員待命 | 30 分鐘內、相關團隊 | 工作時間處理 | 排入 backlog |
| 溝通頻率 | 每 15 分鐘更新 | 每 30 分鐘更新 | 每日更新 | 視需要 |
| 需要 IC | 是 | 是 | 否 | 否 |
| 需要 Post-mortem | 是(必須) | 是(必須) | 建議 | 否 |
災難復原演練(DR Drill)
紙上談兵的 Runbook 和事故應對流程,只有在實際演練過後才知道是否有效。災難復原演練(Disaster Recovery Drill)是定期驗證團隊事故應對能力的必要措施。
演練頻率與類型
| 類型 | 頻率 | 說明 | 範例 |
|---|---|---|---|
| 桌面演練(Tabletop) | 每月 | 團隊坐在一起,口頭走過事故情境 | 「假設主資料庫掛了,我們的流程是什麼?」 |
| 模擬演練(Simulation) | 每季 | 在 staging 環境中模擬真實故障 | 手動關閉一個服務,測試告警與應對流程 |
| 混沌工程(Chaos Engineering) | 持續性 | 在生產環境中注入可控的故障 | 使用 Chaos Monkey 隨機終止 Pod |
季度演練流程
-
規劃(演練前 2 週)
- 選定演練情境(例如:資料庫故障轉移、多區域切換、全站回滾)
- 定義成功標準(例如:RTO < 30 分鐘、RPO < 5 分鐘)
- 通知參與人員與利害關係人
- 準備觀察指標與記錄模板
-
執行(演練當天)
- 在預定時間注入故障
- On-call 團隊按照標準流程應對
- 記錄所有關鍵事件的時間點
- 觀察者記錄流程中的問題與改善點
-
覆盤(演練後 1 週內)
- 比對實際表現與成功標準
- 識別 Runbook 中的錯誤或不足
- 評估告警的及時性與準確性
- 更新 Runbook 與應對流程
- 將改善項目納入下一個 Sprint
演練的常見陷阱
- 事先通知太多人:如果所有人都知道「今天下午 3 點會演練」,就無法真實測試應對速度
- 只演練簡單場景:永遠只模擬「重啟服務」這種簡單操作,無法發現複雜情境下的問題
- 演練後沒有跟進:演練發現了問題,但沒有人去修復,下次演練又遇到同樣的問題
常見問題與風險
在建立事故管理流程的過程中,團隊常會遇到以下挑戰:
問題一:Runbook 過時
症狀:On-call 工程師打開 Runbook,發現裡面的指令已經不適用——服務已經遷移到新的叢集、指令中的 hostname 已經改了、依賴的工具已經被替換。
解法:
- 將 Runbook 的維護責任明確指派給服務擁有者
- 每次事故處理後,如果發現 Runbook 有誤或不足,作為 Post-mortem 的行動項目進行更新
- 設定季度性的 Runbook 審查週期,確認所有 Runbook 仍然有效
- 在 Runbook 中標記最後驗證日期,超過 3 個月未驗證的 Runbook 標記為「需要審查」
問題二:Post-mortem 行動項目未跟進
症狀:Post-mortem 會議開得很熱烈,行動項目列了一大堆,但三個月後回頭看,大部分都沒有完成。然後同樣的問題再次發生。
解法:
- 行動項目必須建立在工作追蹤系統中(Jira / Linear / GitHub Issues),而非僅存在於文件裡
- 指派具體的負責人和到期日,不接受「大家一起做」這種模糊分配
- 在每週的工程團隊週會中花 5 分鐘回顧未完成的 Post-mortem 行動項目
- 追蹤行動項目完成率作為團隊的 KPI 之一
問題三:告警疲勞(Alert Fatigue)
症狀:告警太多、太頻繁、太多誤報,導致 on-call 工程師開始忽略告警。當真正的問題發生時,反應速度嚴重下降,甚至完全沒有注意到。
解法:
- 定期審查告警規則,刪除已經不適用的告警
- 設定合理的告警門檻,避免過於敏感的告警
- 區分「需要立即處理」的告警和「僅供觀察」的通知,使用不同的通知管道
- 追蹤告警的信噪比(signal-to-noise ratio),目標是 actionable alert 比例 > 80%
- 如果一個告警連續一個月都沒有需要實際處理的情況,考慮降級或刪除
問題四:事故處理過度依賴特定人員
症狀:每次出事都是同一個人在處理,其他人只能在旁邊看。這個人一旦休假或離職,團隊就陷入恐慌。
解法:
- 強制輪值:每個人都必須排入 On-call 輪值,不允許永遠由同一人值班
- Pair On-call:新加入輪值的工程師先與資深工程師配對值班 2-4 週
- 記錄所有事故處理過程,轉化為 Runbook,將個人經驗系統化
- 定期進行 DR Drill,讓所有人都有實戰經驗
問題五:缺乏事故管理工具
症狀:事故發生時,在 Slack 群組中混亂地討論,沒有統一的事故追蹤、沒有自動化的升級流程、沒有結構化的狀態更新。
解法:
- 導入事故管理平台(PagerDuty、OpsGenie、incident.io)
- 設定自動化的升級流程(告警 → Slack 通知 → 電話 → 自動升級)
- 建立事故模板,讓事故的建立和追蹤有標準化的格式
- 與 ChatOps 整合,在 Slack 中直接管理事故生命週期
小結
事故管理不是一個一次性的專案,而是一個持續改善的過程。它的核心目標是:
| 指標 | 說明 | 改善方向 |
|---|---|---|
| MTTD(Mean Time To Detect) | 從故障發生到被偵測的時間 | 改善監控與告警的覆蓋率和靈敏度 |
| MTTR(Mean Time To Recovery) | 從故障偵測到服務恢復的時間 | 完善 Runbook、自動化修復 |
| MTBF(Mean Time Between Failures) | 兩次故障之間的間隔時間 | 落實 Post-mortem 行動項目、預防性維護 |
建立成熟的事故管理文化需要時間,但回報是巨大的。當你的團隊能夠在凌晨三點被告警叫醒後,冷靜地打開 Runbook、按步驟排查修復、在 30 分鐘內恢復服務,然後隔天用一場 Blameless Post-mortem 找出根因並改善系統——你就知道,這個團隊已經準備好面對任何挑戰了。
記住:目標不是消除所有故障,而是建立一個能夠優雅地處理故障、並從每次故障中變得更強的系統與團隊。
Proto 實踐對照
Proto 中的事故管理準備:Django Proto 內建結構化 JSON 日誌(方便 EFK 收集)和 PII Masking;Infra 層的 告警 ChatOps 整合了 Slack/Discord 通知。事故發生時,這些基礎建設讓團隊能快速定位問題。
延伸閱讀
- Alerts & ChatOps:如何設計有效的告警策略,以及透過 ChatOps 提升事故回應效率
- Backup & DR:備份策略與災難復原計畫的完整指南
- Metrics & Monitoring:監控系統的設計原則,為事故偵測提供堅實的基礎