這一篇整理值班工程師在沒有告警響起的時候,定時要讀哪些訊號、讀它們的理由,以及這些定時檢查和告警規則的分工。範圍是值班的日常:接班、交班與每週一次的營運會議。告警響起之後是否啟動事故流程與如何分級,見 8.1 事故分級與啟動條件;長事故中事故指揮的跨班次交接另有專篇,見 8.12 IC Handoff 與長事故跨班次協調。

例子沿用 4.0 服務端監控的分層 的短網址服務:一台主機上的入口 Nginx、後端程式、PostgreSQL 與 Valkey(相容 Redis 的記憶體資料庫),以 Prometheus(抓取指標並評估告警規則)與 Alertmanager(把告警分送成通知)監控,失效域(會因同一個原因一起停掉的那組元件)以外有心跳監看與外部探測。

例行檢查與告警規則的分工

告警送到人手上的方式有兩種,下文只用這兩個名字。呼叫值班(page)是由值班通知系統打電話或推播,要值班立即處理,半夜也會把人叫醒。只送通知是送到聊天頻道、信箱或開成工單,在上班時間處理。依 4.4 dashboard 與 alert 設計 的嚴重度分級,critical 呼叫值班,warning 只送通知。

例行檢查讀的是告警規則刻意不呼叫值班、或根本沒有寫成規則的訊號。AWS 的 John O’Shea 在 Amazon Builders’ Library 的〈Building dashboards for operational visibility〉寫道,任何需要人工檢視儀表板的營運流程,不論檢視得多頻繁,都會因人為疏失而失敗,所以 Amazon 以自動告警持續評估最重要的監控資料。O’Shea 這段話定下例行檢查的範圍:一個訊號能寫成「越過某個門檻就送出」的規則,就寫成告警,不靠值班定時去看。例行檢查本身也是人工流程,同樣會漏做,所以留在例行檢查裡的,只能是晚一兩天才被讀到也不會造成損害的訊號:接班檢查每天做一次時,一個訊號最晚隔天被讀到,漏做一次就再晚一天。這個範圍的前提是接班檢查至少每天做一次,排班以週輪替時,值班每天開工時照接班清單讀一次,不只在換班那天讀。

這些訊號有四種:

  • 離越線還很遠的趨勢:磁碟每週多用幾個百分點、離越線還有幾週的走向,告警現在送出也沒有要做的事,留給人定期看走勢,決定什麼時候擴充。幾小時內就會越線的走向不在這一類,它寫得成預測式告警,例如以 PromQL 的 predict_linear(依過去一段時間的走勢推算未來某個時間點的值)寫的「四小時內磁碟會滿」。
  • 需要人判斷才知道是不是故障的狀態:點擊量比上週少了兩成,可能是轉址出錯,也可能是一個大客戶的活動結束了。規則寫不出這個判斷。
  • 只送通知的告警與工單:《The Site Reliability Workbook》值班章的例子是一個還沒上線的服務,它的資料庫備份失敗:這類問題在上班時間處理就夠,告警應該開單而不是呼叫值班。開了的單與送出的通知要有人讀,例行檢查就是讀它們的時間點。
  • 監控與告警本身的狀態:還在生效的告警靜音、被暫停的心跳檢查項目、通知太多而被忽略的規則。這一類的故障讓原本的告警規則不送出,要由告警以外的機制發現。整套告警停擺時,由心跳監看送出通知(見 Dead Man’s Switch)。被遺忘的靜音可以另外寫提醒,見〈例行檢查項目改寫成告警規則的條件〉;提醒只告訴值班有靜音生效超過一天,逐一確認每個靜音的工作仍由接班檢查負責。被暫停的心跳檢查項目與被忽略的規則沒有現成的規則可寫,留給例行檢查。告警系統本身停擺或送不出通知時由誰發現,見 4.0 服務端監控的分層 的〈告警鏈的監看:心跳與通知失敗〉。

靜音不完全符合「晚一兩天讀到也不會造成損害」這個範圍:一個被遺忘、壓住 critical 告警的靜音,晚一天讀到就可能錯過一次故障。靜音仍要由接班檢查逐一確認,因為一個靜音該不該還在,要對照它對應的維護是否已經結束,而提醒只看得到靜音生效了多久;生效不到一天、維護早已結束的靜音,提醒也不會送出。所以風險要在設定時壓低:結束時間只設到維護預計的長度,維護沒結束時再延長。

接班時讀的訊號

接班檢查的目的是讓接班的人在第一則告警響起之前,就知道系統現在的狀態與還沒結束的事。《The Site Reliability Workbook》的〈On-Call〉章記錄的一個 Google 新團隊,值班者每一班開始時讀上一班的交班紀錄,結束時寄一份給下一班。要讀哪些項目依服務而定,判斷依據是這一項讀到異常時,值班是否會因此採取動作;下面每一項寫它防的是哪一種告警送不出、或規則寫不出的情形,以及讀到異常時通常怎麼處理,讀者據此組自己服務的接班清單。

  • 上一班的交班紀錄與還沒結的事件:上一班留下的事件與觀察,系統上查不到。紀錄裡有還沒結的事件,接班的人回覆確認接手,從那一刻起由他負責。紀錄的內容見〈交班紀錄的內容〉。
  • 生效中的告警靜音(silence):Alert Silence(告警靜音) 是人在 Alertmanager 手動設定、在一段時間內不送出符合條件的告警通知,與通訊軟體把對話設成靜音不同,它以標籤條件與結束時間界定(Grafana 的繁體中文介面也把 silence 譯成「靜音」)。維護時設下的靜音若結束時間設得比維護長,維護結束之後同一條規則再成立,也不會有任何通知。讀的方式是列出每一個靜音的條件、設定者、結束時間與註解,判斷它對應的工作是否已經結束;判斷不了時對照上一班交班紀錄裡記下的靜音與對應工作,或問設定者,問不到人就保留到結束時間,寫進自己的交班紀錄。
  • 上一次接班檢查之後只送通知的 warning 告警:沒有人判定的 warning,送出與沒送出的結果一樣。逐則判定:它指的狀況還在、不處理會在下一次接班檢查之前變成要呼叫值班的狀況,就開成工單、指定負責人;已經自行恢復或屬於已知的雜訊,記為沒有引發動作,供每週營運會議統計。
  • error budget 的走向:error budget 是 SLO(服務水準目標,例如每月 99.9% 的請求成功)在一個週期內容許的失敗額度。快速消耗由 Burn Rate(消耗速率)告警呼叫值班;4.6 SLI 量測與 SLO 訊號設計 的多視窗告警裡,長視窗以天計的那一組偵測的是緩慢消耗,適合只送通知。剩餘額度的百分比與它在 30 天 SLO 週期裡的走向在這裡看:照目前的速度在週期結束前會用完,就在每週營運會議上提出放慢發布(見 Error Budget)。
  • 排程工作與心跳檢查項目:昨晚的備份與匯出是否完成。沒有按時送心跳的工作已經由心跳監看通知;這裡要看的是心跳監看服務上被暫停的檢查項目,被暫停的項目在恢復之前不會因心跳中斷而通知。有一種檢查項目刻意維持暫停:用來回報「通知送不出去」的那個檢查項目只接收 /fail(心跳監看服務的失敗回報網址,呼叫它就把那個檢查項目標成失敗),平時就是暫停狀態,而心跳監看服務在這個項目暫停時照樣處理送到它的 /fail(見 第三方心跳監看與外部探測服務)。讀的方式是把暫停中的項目和預期維持暫停的清單比對,清單以外的才追查。
  • 到期事件:TLS 憑證、網域與第三方 API 金鑰在多久之後到期。有告警規則的項目在這裡只確認規則還在:在 Prometheus 的規則頁(或 /api/v1/rules,Prometheus 列出全部規則與狀態的 API)查得到那條規則,而且狀態不是錯誤。沒有規則的項目(例如手動續約的網域),剩不到一個月就排續約,並照〈例行檢查項目改寫成告警規則的條件〉把它改寫成規則(例如探測工具 Gatus 的 [DOMAIN_EXPIRATION] 條件)。
  • 容量的走向:主機磁碟、資料庫大小、佇列積壓的一週走勢,看它照目前的速度多久之後越過告警門檻,短於擴充需要的準備時間就排擴充。
  • 最近的部署與功能開關(feature flag)變更:Google 的《Site Reliability Engineering》在〈Introduction〉寫道,約七成的停機來自對線上系統的變更。接班時知道改了什麼,故障發生時第一個檢查的方向就有了。
  • 客服單量與排名前幾名的錯誤碼:使用者比監控先發現的故障,會先出現在客服單上。件數越過門檻時由客服系統直接建立事件(見 8.24 客服回報的處理 的〈轉給值班的條件與轉交方式〉);這一項是那條規則之外的後備檢查,看同一個錯誤碼的單量是否突然增加、或出現沒有對應事故的集中回報。

團隊選定自己的項目之後,把它們放在同一個儀表板或同一份清單,接班檢查才會在幾分鐘內做完。以 Alertmanager 為例,還沒過期的靜音以它隨附的命令列工具 amtool 列出:

1# 列出還沒過期的靜音(生效中的與排定之後才開始的都會列出):
2# 條件(Matchers)、結束時間、設定者與註解
3# --alertmanager.url 換成自己 Alertmanager 的網址
4amtool --alertmanager.url=http://localhost:9093 silence query
5
6# 輸出的範例(ID 與時間是佔位的值):
7# ID          Matchers                                          Ends At                  Created By  Comment
8# 772ca670-…  alertname="DiskWillFillIn4Hours" instance="db-1"  2026-10-14 12:05:57 UTC  oncall-a    磁碟擴充維護,預計 2 小時

讀輸出時對照每一列的 Ends At 與 Comment:註解寫的維護已經結束而 Ends At 還在後面,這個靜音要以 amtool silence expire <ID> 提前結束(<ID> 填輸出第一欄的值);註解是空的,就找 Created By 那個人確認它對應什麼工作。輸出沒有開始時間欄,排定在之後才開始的靜音也會列出,要分辨時加上 -o extended,輸出會多出 Starts At 欄。條件裡沒有 alertname、只寫了 severity 這類寬鬆標籤的靜音優先確認,因為它壓下的告警最多。設定靜音的人寫註解,是讓下一班讀得出它為什麼存在。

交班紀錄的內容

交班紀錄(handoff notes)是值班結束時寫給下一班的一份文字,讓下一班知道上一班留下了哪些還沒結束的事。值班換班與事故中換人時的責任交接,業界的通則叫 Handover Protocol:交接完成之前,責任仍屬於交出的那一方。交班紀錄要寫下來而不只是口頭交代,理由有兩個:下一班可能隔天才開始讀,口頭的內容到時候已經沒有人記得;每週營運會議要統計值班負擔,資料就來自這些紀錄。

交班紀錄寫的是下一班接手時要知道、而系統上查不到的事:

  • 還沒結的事件:每一件的現況、已經試過的處置、下一步、等的是誰,以及已經對客戶與客服說了什麼(內部狀態頁上的說法)與下一次更新的時間。
  • 這一班設下的靜音、它對應的工作與結束時間:下一班不必從靜音清單反推它為什麼存在。
  • 這一班做過的變更:重啟、手動擴充、改了設定,連同還沒寫回設定檔或版本控制的部分。
  • 觀察中、還沒到告警門檻的走向:例如「資料庫連線數這兩天的尖峰在升高,還沒越過門檻」。
  • 客服轉來、還在查的單:單號與目前查到的地方。
  • 這一班被呼叫的次數與時段:夜間被叫醒幾次、每一則告警最後是否引發動作;值班在告警工具上確認(ack)告警時已經標記過是否引發動作的(見 4.4 dashboard 與 alert 設計 的〈Noise rate 量測〉),交班紀錄只寫沒標記到的,供每週營運會議統計。

下一班讀完之後回覆確認接手;確認之前,還沒結的事件仍由上一班負責。

每週營運會議讀的訊號

每週營運會議(weekly operations review)是值班、工程、客服與相關角色一起看一週累積下來的訊號,處理單一班次看不出來的走向。《The Site Reliability Workbook》值班章收錄的 Evernote 案例,每天早上的站會回顧事故,每月開一次服務檢討會議,並在會上檢視值班負擔;同一章另外建議依蒐集到的結構化資料,定期討論呼叫值班次數的走向。Amazon 的團隊每週開營運會議,以輪盤(wheel of fortune)挑選要看的高層級稽核儀表板,看客戶體驗與關鍵的服務水準目標。原文沒有說明為什麼用輪盤;它帶來的效果是每個儀表板都可能被抽到,平常沒人看的儀表板也要維持在讀得懂、數字對得上現況的狀態。

每週營運會議讀的是單一班次累積不出來的訊號:

  • 這一週沒有引發動作的告警:每一則呼叫值班或送出的通知,最後是否引發動作。沒有動作的告警依原因處理:狀況確實存在、只是門檻太敏感,就調整門檻;要處理但不急,就改成只送通知;它是同一個原因觸發的多則告警之一(資料庫停了,查詢逾時與延遲告警一起響),就保留這則症狀告警,以分組或抑制把它們合成一則通知(見 4.4 dashboard 與 alert 設計 的〈降噪手段〉);值班收到而不知道該做什麼、所以沒有動作的,補上 runbook 連結;不需要任何人處理,才刪除。長期被忽略的告警會讓值班連實際發生的故障也跟著忽略(Alert Fatigue)。
  • 值班負擔:一週呼叫值班的次數、夜間被叫醒的次數,從交班紀錄統計。
  • 重複出現的客服回報:客服單以錯誤碼與功能分類之後排名前幾名的類別,各自寫回錯誤碼對照表、告警或查詢工具,見 8.24 客服回報的處理 的〈重複出現的回報:查證結果寫回知識文章、告警規則與查詢工具〉。
  • 錯誤碼對照表沒有涵蓋的錯誤碼:比對這一週客服單出現過的錯誤碼與錯誤碼對照表的列,查不到的錯誤碼補成一列並指定負責人,見 11.16 面向終端使用者的錯誤碼與請求編號 的〈錯誤碼對照表〉。
  • SLO 與 error budget 的月走勢:決定下一段時間發布節奏要不要放慢。
  • 交班紀錄裡反覆出現的觀察項:連續幾週都寫進交班紀錄的同一個走向,候選改寫成告警規則,判斷條件見〈例行檢查項目改寫成告警規則的條件〉。

每週處理的是這一週裡的個別告警與回報;整體的雜訊比例報告、沒人看的儀表板與沒有擁有者的規則以季為單位整理,見 4.8 訊號治理閉環 的〈治理節奏〉。

單人或兩三人的小團隊不必開會,做法可以縮成每天開工時對著自己的接班清單看幾分鐘、每週花一段固定時間看一週的告警與客服單;要保留的是交班紀錄與靜音的註解,因為少了它們,下一個接手的人(或休假回來的自己)無從知道上一段時間發生了什麼。

例行檢查項目改寫成告警規則的條件

例行檢查的每一個項目都要定期確認它還該不該由人看,判斷條件是三項:

  • 能不能寫出一個不需要判斷的門檻:三十天內到期的憑證、昨晚沒有完成的備份,都寫得出門檻,改寫成告警之後值班就不必每天看。
  • 讀了多少次都沒有讀到異常:一個項目連續幾週(週數由團隊定)每天都看、每天讀到的都在正常範圍,寫得出門檻的就改寫成規則,寫不出門檻、又一直讀不到異常的就從清單移除。
  • 異常時要多快處理:要在上班時間處理的,改寫成只送通知的 warning;要立即處理的,改寫成呼叫值班的告警,這時它本來就不該是例行檢查的項目。

靜音是寫得出規則、而以 Prometheus 指標寫的規則只量得到靜音數量、量不到單一靜音時長的例子。Alertmanager 自己在 /metrics 輸出 alertmanager_silences{state="active"},是生效中靜音的數量。Prometheus 要先有一個抓取 Alertmanager /metrics 的 job(Prometheus 設定裡的一組抓取目標);寫規則之前在 Prometheus 查一次 alertmanager_silences,active、pending、expired 三個狀態的序列都查得到,才代表抓得到,查不到時下面這條規則永遠不會成立,也不會報錯。抓得到之後,可以寫一條只送通知的規則:

 1groups:
 2  - name: alertmanager-self
 3    rules:
 4      - alert: SilenceActiveForADay
 5        # 生效中的靜音數量連續一天大於零時送出;
 6        # 它分不出是同一個靜音一直生效,還是幾個靜音輪流設下
 7        expr: alertmanager_silences{state="active"} > 0
 8        for: 1d
 9        labels:
10          severity: warning

群組名與規則名是自取的。寫好之後以 Prometheus 隨附的 promtool check rules <規則檔> 檢查語法;語法通過不代表 Prometheus 抓得到這個指標,那一項要靠前面的查詢確認。這條規則量的是數量而不是單一靜音的時長,團隊只要長期維持一個刻意的靜音,這條規則就一直成立,而一直成立的規則容易被人用另一個靜音壓掉。

SilenceActiveForADay 的通知也經過 Alertmanager,條件寬鬆的靜音(只寫 severity="warning" 或範圍更大)會把 SilenceActiveForADay 自己的通知一起壓下,而被遺忘時最危險的正是這種靜音。所以設定靜音時條件至少寫到 alertname,接班檢查時優先確認條件寬鬆的靜音。

要量單一靜音的時長、又不讓提醒被靜音壓下,改由排程腳本讀 Alertmanager 的 /api/v2/silences:它回傳每一個靜音(含已過期的)的條件、狀態(status.state)、開始時間(startsAt)、結束時間(endsAt)與設定者,腳本只取狀態是 active、生效超過一天的靜音,直接送到聊天頻道,不經過 Alertmanager,分得出是哪一個靜音,也不會被寬鬆的靜音壓下。SilenceActiveForADay 規則與這支腳本補的都是「有靜音被遺忘」的提醒,逐一確認每個靜音對應的工作仍由接班檢查負責。

寫不成規則、而且仍會讀到需要動手的情形的項目留在例行檢查裡:需要人判斷的業務數字、還在觀察的走向,以及每週營運會議裡那些要多人一起看的訊號。

延伸閱讀:告警分級、心跳監看、客服回報與值班制度