事故檢討很容易召開,卻很難做得有用。會開了,文件寫了,四條改善事項記下來了,六個月後同一個故障又發生一次,而某個人正好在找別的東西時翻出那份舊文件。
談到這件事時,注意力幾乎都落在「不究責」這個詞上。這條原則確實重要,但失效的地方並不在那裡。有大量組織把不究責執行得一絲不苟,檢討卻什麼也沒有改變,原因很簡單:他們把檢討本身當成了交付物,而不是當成產出交付物的手段。
判斷你們的檢討是否有效,有一個簡單到令人難堪的測試:過去六個月記錄下來的改善事項,實際完成的比例是多少? 如果答案是「大部分」,那麼無論流程長什麼樣,它都在發揮作用。如果低於一半,你們是在開會而不是在運行一個流程,換更漂亮的範本也救不了。少數幾條帶負責人與期限的事項,勝過一份沒人有時間處理的詳盡清單。
事故檢討到底是為了什麼
不是為了解釋發生了什麼。到故障收尾的時候,在場的人通常已經知道了。
它存在的意義,是找出讓一個小問題長成大問題的那些條件,並且改掉其中幾條。這和「什麼壞了」是兩個不同的問題,而這個區別在動筆的那一刻就會顯現出來。「資料庫連線耗盡了」說的是什麼壞了。「連線池飽和沒有觸發任何告警,而本該顯示這一點的儀表板並不在值班手冊裡」說的是一個條件,條件是可以動手處理的。
前一種說法能推出的行動,最多就是「這次重啟後恢復了」。後一種說法能推出的是具體工作:加一條告警,在值班手冊裡補一行儀表板連結。這個差別決定了半年後同樣的事會不會再來一次。
第二個產物長期被低估,那就是一份關於這次事件的共同敘述。沒有它,每個人都會留著自己那個版本,而這些版本會朝著各自原本就相信的方向漂移。一年之後,兩個共同經歷過同一次故障的團隊,會講出互相矛盾的兩套說法。
不究責有非常具體的含義
它不是說沒有人犯錯。它是說,分析從這樣一個前提出發:一個人依據當時能拿到的資訊做出了合理判斷,採取的行動事後被證明是錯的,然後去問,這個行動在當時為什麼看起來是對的。Google 的 SRE 手冊系統講述了這套做法,以及隨之而來的失敗模式。
這不只是出於善意,真正的原因是究責會摧毀資訊。在一個故障會黏在個人身上的組織裡,人們描述事件時會格外小心,會略去看起來不利的細節,並且把回報推遲到自己足夠理解、能安全地講清楚為止。這時檢討拿到的,是一份為了自保而修改過的敘述,這是所有可能的輸入裡最差的一種。
而且丟掉的往往正是最有價值的那部分:判斷失誤的那一刻螢幕上顯示了什麼,為什麼當時覺得這些資訊已經夠了。恰恰是這一段最先被刪掉。
在實務上,不究責是一種語言屬性。「你為什麼重啟服務?」招來的是辯解。「你決定重啟的時候,儀表板上顯示的是什麼?」招來的是資訊。第二個問題也更有用,因為它的答案是關於你們監控體系的事實,而不是關於某位同事的事實。
如果確實存在個人層面的績效問題,請單獨、直接地處理。放進事故檢討裡處理會毀掉這次檢討,何況那也不是進行這種談話的好場合。
寫出能教會人的時間軸
時間軸是文件裡最有價值的部分,同時也是最經常被寫壞的部分:寫成了一串抽掉了人的技術事件。
請寫清楚人在什麼時候知道了什麼。不只是「14:32 重啟了服務」,還要寫這個人在 14:32 能看到什麼、他相信正在發生的是什麼。可以動手改的材料就在這裡。因為一個由含糊的儀表板造成的十五分鐘延遲是可以修復的問題,而一個只被記成空白的十五分鐘延遲不是。
標出真正要緊的時刻:什麼時候開始,什麼時候第一次有人注意到,什麼時候找對了人,什麼時候搞清了原因,什麼時候緩解,什麼時候徹底解決。改進就住在這些時刻之間的間隔裡,而偵測所花的時間往往是其中最長的一段。
在想著怎麼把復原做得更快之前,先看這段偵測間隔。在很多現場,沒人察覺的時間比真正動手修復的時間還要長。
趁記憶還新鮮時就寫,最好在一兩天之內。一個人在某個具體時刻相信過什麼,這種記憶消退的速度,遠快於對事情本身經過的記憶。
很少只有一個根本原因
這個說法鼓勵人們停在第一個說得通的解釋上,而任何規模的故障都是鏈條,需要好幾個條件同時成立才會發生。
有用的檢討會改為列出促成因素:觸發故障的那次變更、本該攔住它卻根本不存在的那個測試、發到了沒人看的頻道裡的那條告警、對上一代架構才準確的那份值班手冊。每一條都是獨立的機會,你可以挑最便宜的兩條來修,而不必去修鏈條上碰巧排在最前面的那一條。
「可以挑」這一點在實務上很關鍵。一旦寫死只有一個原因,對策也就被鎖定成一條,如果它恰好很貴,最後往往一條都不會落地。
這同時也減少了一種常見的扭曲。當一次檢討點名某個單一根本原因時,那個原因非常經常是「人為疏失」,而這是描述不是解釋,它恰好在調查本該開始的地方把調查關掉了。
讓後續追蹤真正發生
檢討的生死就在這裡決定,而藥方一點都不炫目。
減少條目。 兩條能做完的,勝過八條做不完的。按它們究竟降低了偵測時間、影響範圍還是複發機率來排序,其餘的砍掉。
寫上具名負責人與日期,放進你們日常使用的工作追蹤系統,而不是放在文件裡。只活在檢討文件裡的條目,在做規劃時是看不見的,而排程恰恰發生在那個時候。
在下一次檢討上檢查未完成的條目。 單是這一個習慣,作用就超過任何範本。它讓沒做完的事變得可見,也把一串互不相干的會議變成一個真正的流程。
誠實地接受其中一些條目。 一個長期只完成一半承諾的團隊,應該把承諾減半。記錄一個沒人會撥資源的意圖,比記錄一個決定不做更糟,因為後者至少是真的。
由此得到的改進,通常和我們的災難復原指南以及軟體測試策略所講的屬於同一類:更快的偵測、更小的影響範圍,以及一套換個人也能維運的系統。
Mecanik 在伺服器安全分析服務中,會對我們維護的系統做事故檢討。絕大多數案例的模式都一樣:技術原因很快就搞清楚了,真正昂貴的是那段沒被發現的空白。
常見問題
做事故檢討的意義是什麼? 是找出讓小問題長成大問題的那些條件並改掉其中幾條,這和「什麼壞了」是兩個問題。它還會產出一份關於事件的共同敘述,沒有這份敘述,每個人都會留著自己的私人版本,而那個版本會朝他原本就相信的方向漂移。
不究責到底是什麼意思? 是指分析假定一個人依據當時能拿到的資訊做出了合理判斷,行動事後被證明是錯的,並追問它在當時為什麼看起來是對的。它重要,是因為究責會摧毀資訊:人們為了自保而修改敘述,檢討於是拿著一份被汙染的輸入在工作。
檢討應該找出唯一的根本原因嗎? 不應該。任何規模的故障都是需要多個條件同時成立的鏈條,所以列出促成因素更有用。這樣你可以修最便宜的兩條,而不是鏈條上排第一的那條,也能避免以「人為疏失」收尾,因為那是描述而不是解釋。
事故時間軸應該包含什麼? 不只是系統做了什麼,還要包含人在什麼時候知道了什麼。記下什麼時候開始、什麼時候第一次有人注意到、什麼時候找對了人、什麼時候搞清原因、什麼時候緩解、什麼時候解決。改進住在這些間隔裡,而偵測時間通常是最長的一段。
為什麼檢討的改善事項從來做不完? 因為它們活在文件裡而不是工作追蹤系統裡,排程的時候看不見。解決辦法是減少條目、在日常系統裡寫上具名負責人與日期,並在下一次檢討開始時檢查未完成條目,讓沒做完的事變得可見。
評論