
Alerts & ChatOps:告警不是越多越好
有了 Metrics 和 Logs 之後,下一步是設定告警:什麼情況下要通知誰、用什麼管道通知、以及收到告警後要做什麼。告警設計得好,可以在問題影響使用者之前就介入;設計得差,團隊會被無止境的通知淹沒,最後開始忽略所有告警(alert fatigue),反而比沒有告警更危險。
架構概覽
flowchart TD Metric[指標超過閾值\nCPU / Disk / Error Rate] -->|觸發| AM[Alertmanager\n告警路由與聚合] AM -->|Critical| Urgent[即時通知\n電話 / PagerDuty] AM -->|Warning| Batch[批次彙整\nSlack / Discord] AM -->|Info| Digest[定期摘要\nEmail] Urgent --> Runbook[Runbook\n處理手冊] Batch --> Runbook Runbook --> Resolve[問題解決\n回報 & 覆盤]
架構概覽
flowchart TD Prometheus[Prometheus\nalert rules] -->|trigger| AM[Alertmanager\n:9093] AM -->|route by severity| Critical[Critical Route] AM -->|route by severity| Warning[Warning Route] AM -->|route by severity| Info[Info Route] Critical -->|immediately| Phone[Phone Call / PagerDuty] Critical -->|immediately| Slack[Slack #incidents] Warning -->|batch 5min| Slack2[Slack #alerts] Warning -->|batch 5min| Discord[Discord #alerts] Info -->|batch 1hr| Email[Email Digest] Slack --> Runbook[Runbook\n處理流程] Slack --> Acknowledge[Acknowledge\n確認接手]
Prometheus 觸發告警後送到 Alertmanager,Alertmanager 根據 severity 路由到不同的通知管道。Critical 立即通知(電話 + Slack),Warning 批次彙整後通知(5 分鐘一批),Info 每小時彙整一次用 email 送。每個告警都附帶 Runbook 連結。
核心概念
-
告警分級(Severity Levels):分三級。Critical(P1):服務完全不可用、資料遺失風險、安全事件。需要有人立即處理,不管是不是上班時間。例如:PostgreSQL 掛了、磁碟空間 < 5%、TLS 憑證過期。Warning(P2):服務降級、效能異常、資源即將耗盡。上班時間處理,不需要半夜叫人。例如:CPU > 85% 超過 5 分鐘、API error rate > 5%、磁碟空間 < 20%。Info(P3):需要關注但不緊急的事項。下次巡檢時處理。例如:憑證 30 天內到期、某個 exporter scrape 失敗。
-
告警抑制與聚合:如果 Host 掛了,上面跑的 10 個服務都會告警,一次收到 10 封通知反而造成混亂。Alertmanager 的
group_by功能可以把同一台 Host 的告警聚合成一條通知。inhibit_rules可以設定「如果已經有 HostDown 告警,就抑制該 Host 上所有服務的告警」,避免通知風暴。 -
Runbook:每個告警都應該附帶一個 Runbook(處理手冊),告訴收到告警的人該怎麼做。Runbook 不需要很長,但至少要包含:(1)這個告警代表什麼、(2)可能的原因、(3)處理步驟、(4)升級路徑(如果處理不了要找誰)。沒有 Runbook 的告警等於「我知道出事了,但不知道該怎麼辦」。
-
ChatOps 整合:把告警通知整合到團隊日常使用的通訊工具(Slack/Discord),而不是只發 email。好處是告警在團隊可見的 channel 裡,所有人都知道現在有什麼問題。可以在 channel 裡直接討論和協作,事後也有完整的對話紀錄。建議用專門的
#alertschannel,不要混在一般聊天 channel 裡。
使用情境
-
半夜服務異常:凌晨 2 點 PostgreSQL 掛了。Alertmanager 發送 Critical 告警到 on-call 工程師的手機(PagerDuty/phone call)和
#incidentschannel。工程師收到通知後,打開 Runbook 按步驟操作:檢查 PostgreSQL 日誌、重啟容器、驗證服務恢復。在#incidentschannel 回報處理過程和結果。 -
資源使用率升高:下午磁碟使用率超過 80%,觸發 Warning 告警。Alertmanager 等 5 分鐘彙整後,發到
#alertschannel。值班的維運人員在上班時間看到後,清理舊的 Docker images 和過期的備份檔案,回報處理完成。 -
告警回顧:每月回顧上個月的所有告警,統計各類型告警的數量和解決時間。發現某個 Warning 告警每天都觸發但每次都自動恢復(false alarm),調整閾值或移除該告警規則。發現某個 Critical 告警的解決時間太長,補充 Runbook 或改善自動化。
實作範例 / 設定範例
Alertmanager 設定
# alertmanager.yml
global:
resolve_timeout: 5m
route:
receiver: 'default'
group_by: ['alertname', 'instance']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
routes:
# Critical: 立即通知
- match:
severity: critical
receiver: 'critical-channel'
group_wait: 10s
repeat_interval: 1h
# Warning: 5 分鐘彙整
- match:
severity: warning
receiver: 'warning-channel'
group_wait: 5m
repeat_interval: 4h
# Info: 1 小時彙整
- match:
severity: info
receiver: 'info-email'
group_wait: 1h
repeat_interval: 24h
# 抑制規則:Host down 時,抑制該 Host 上的服務告警
inhibit_rules:
- source_match:
alertname: 'HostDown'
target_match_re:
alertname: '.+'
equal: ['instance']
receivers:
- name: 'default'
slack_configs:
- api_url: '${SLACK_WEBHOOK_URL}'
channel: '#alerts'
send_resolved: true
- name: 'critical-channel'
slack_configs:
- api_url: '${SLACK_WEBHOOK_URL}'
channel: '#incidents'
send_resolved: true
title: '🚨 CRITICAL: {{ .GroupLabels.alertname }}'
text: >-
{{ range .Alerts }}
*Alert:* {{ .Labels.alertname }}
*Instance:* {{ .Labels.instance }}
*Summary:* {{ .Annotations.summary }}
*Runbook:* {{ .Annotations.runbook_url }}
{{ end }}
# webhook_configs:
# - url: 'https://pagerduty-webhook-url'
- name: 'warning-channel'
slack_configs:
- api_url: '${SLACK_WEBHOOK_URL}'
channel: '#alerts'
send_resolved: true
- name: 'info-email'
email_configs:
- to: 'team@example.com'
send_resolved: falseDiscord Webhook 整合(替代 Slack)
# 如果團隊用 Discord,用 webhook_configs
receivers:
- name: 'discord-alerts'
webhook_configs:
- url: '${DISCORD_WEBHOOK_URL}'
send_resolved: true
http_config:
headers:
Content-Type: application/jsonRunbook 範本
## Runbook: DiskSpaceLow
### 告警條件
磁碟可用空間低於 20%
### 可能原因
1. Docker images 佔用過多空間
2. 日誌檔案未清理
3. 備份檔案未上傳到 MinIO 後刪除本地副本
4. 資料庫 WAL 檔案過大
### 處理步驟
1. 確認磁碟使用狀況
```bash
df -h
du -sh /var/lib/docker/*
du -sh /var/log/*- 清理 Docker 未使用資源
docker system prune -af --volumes - 清理過期備份
find /tmp/pg-backups -mtime +7 -delete - 檢查日誌 rotation 是否正常運作
升級路徑
如果清理後磁碟空間仍不足,聯繫 Infra Lead 評估擴容。
### 常見問題與風險
- **告警疲勞(Alert Fatigue)**:收到太多不重要的告警,團隊開始忽略所有通知,包括 Critical 的。避免方式:嚴格控制告警數量,每個告警都要有明確的 action(如果收到告警但不需要做任何事,就不應該是告警)。定期回顧和清理不實用的告警規則。
- **通知管道斷了**:Slack Webhook URL 過期或 Discord channel 被刪除,告警發不出去但沒有人知道。避免方式:設定 Alertmanager 自身的健康檢查、用多個通知管道(Slack + email)做備援。定期確認通知管道正常運作。
- **告警沒有 Runbook**:收到告警但不知道怎麼處理,只能等某個「知道的人」上線。避免方式:每建立一個告警規則就同時寫 Runbook,在告警的 annotations 裡加上 `runbook_url`。新告警沒有 Runbook 不允許上線。
- **on-call 機制不清楚**:半夜告警發到 channel 裡,但沒有指定誰要處理。每個人都覺得「應該別人會處理」。避免方式:建立明確的 on-call 排班,每週輪值,on-call 期間要確保手機通知開啟。搭配 PagerDuty 或 OpsGenie 做升級(如果 on-call 沒回應,自動通知下一位)。
### 優點
- 告警分級確保不同嚴重程度用不同管道和速度通知
- 聚合和抑制減少通知風暴
- ChatOps 整合讓告警處理過程對團隊透明
### 缺點 / 限制
- Alertmanager 設定語法不太直觀,容易設定錯誤
- 小團隊可能沒有足夠的人做 on-call 輪值
- Runbook 需要持續維護,否則很快過時
---
## 延伸閱讀
- [[11-metrics-monitoring|Metrics & Monitoring]]
- [[12-log-management|Log Management(EFK/ELK)]]
- [[14-data-movement-etl|Data Movement / ETL]]