我的第一次 On Call 精神時光屋

莫力全 Kyle Mo
12 min readApr 29, 2024

--

什麼是 On Call ?

On-Call 是一個從歐美傳來的技術詞彙,在中文中沒有特別精確對應的詞語,較為接近的意義是「值班」。

On-Call 通常指的是企業為了快速響應生產故障或重大事件,在某段時間內指定某個人或某組人隨時待命(類似於值班),一旦企業發生生產故障或重大事件,將會透過郵件、短信、電話等手段第一時間通知這組人。而這些人無論是否處於工作時間,都必須立即放下手中的一切事務,迅速處理故障或響應重大事件。

在我過去的認知中,通常硬體或韌體相關的企業比較會有 On Call 制度,至於軟體業,過去的工作經驗都是會有運維團隊處理相關的事情,軟體工程師通常不太需要輪 On Call 這項任務。不過早有耳聞在外商中大多數的軟體工程是有 On Call 制度的,我目前所就職的外商也不例外,前陣子剛結束自己人生中的第一次 On Call Rotation,對我來說是個很特別的經歷,因此決定寫一篇久違的技術文章記錄一下。

心態調整

一開始我其實對於 On Call 是有點排斥的,因為有點類似變相的加班,尤其我們是美國時區跟亞洲時區兩個人輪流顧一天,一個人一天就需要負責 12 個小時的輪班,一次輪班是 7 天(包含假日),其實是非常勞累的。隨著每間公司的機制不同,On Call 的範圍也會不同,以我們來說,因為整體架構非常龐大,除了 Web 全端,還有 Operation Infra、更底層的 Backend、Security…等等團隊,所以會有很多 On Call Teams,我所在的 Web FullStack On Call Team 則需要負責監控大約 20 個 Web 小團隊的整體狀況,老實說心智負擔蠻大的,因為大多數的時間我們不會碰到其他團隊在開發的事項,尤其對於我這位 On Board 不到一年的新人來說,在很多業務或歷史沿革不清楚的狀況下,On Call 的壓力老實說蠻大的。

不過如我的文章標題所說,我認爲這次的經驗也很像是進入一個「精神時光屋」。

七龍珠的精神時光屋

在漫畫七龍珠中有一個神奇的場所叫做「精神時光屋」,在時光屋裡面的一年等於真實世界的一天,於是主角群們可以在裡面修煉好幾年,但在現實世界中僅僅過了幾天而已,他們透過這種方式在短時間內大幅提升自己的戰力。

這次 On Call 一週的時間,雖然因為運氣不好遇到 Critical Bugs 而痛苦萬分,但卻因為準備 On Call 與臨危授命想辦法解 Bugs,因此在短時間內學到了很多東西,就彷彿進入了精神時光屋一般,過程痛苦,但以結果來說卻是收穫滿滿。

(聽過一個職場前輩的分享,一份工作裡不可能所有的工作內容都是自己喜歡的,只要比例對自己來說還能接受,就該勇敢面對挑戰,我想 On Call 對我來說就是比較不喜歡但卻又被我當成想跨過的挑戰的部分吧!)

The On Call Handbook

通常一間公司如果有 On Call 制度的話,都會有所謂的 Handbook 或是Document,告訴 On Call Engineer 在準備好輪班前應該要具備哪些技術能力、申請哪些權限、遇到特殊問題要去哪裡查找資訊、On Call 時需要具備的心態…等等,我們公司在把我們排進 On Call Rotation 之前就會有相關的 Training,上完課後其實要花很多時間閱讀過 On Call Handbook,補足自己還缺少的相關知識與技能,透過這個過程其實也可以成長蠻多的。雖然每間公司在細節上一定會有所不同,但我也看了許多網路上的資源,發現對於 On Call 還是有一些心法可以適用大部分 On Call 的情境。例如這篇文章就是不錯的資源

其中有許多跟我們 On Call Handbook 類似的規範,例如:

Setting up Alerts & Escalation Policy

這是開始 On Call 流程最關鍵的一步。通常我們會使用警報管理工具,常見的有 OpsGenie 與 PagerDuty,來將不同平台的所有警報匯集在同一個地方發出。而設定警報很重要的一步是要避免警報疲勞,如果不論重要或是輕微的問題都會發出警報的話,久了的話會產生 On Call 疲勞,工程師也很難快速分別問題的嚴重性。

這時候就可以根據系統警報分級,例如只有 P0、P1 等級的問題會觸發 On Call App 的警報就是常見的方式,其他等級較低的問題則可以透過 Slack Channel 發出。

當 On Call App 響鈴時,On Call 工程師需要盡快得去按下確認的按鈕,代表已經知道這個問題,準備好進一步去處理。除此之外,通常會有一個 Escalation 的規則,如果幾分鐘之內沒有按下確認,會往更上層的主管去通報或是通知下一個 On Call 的人,所以可以想像如果漏掉訊息讓問題上報或是造成其他人的麻煩的話…你是會為自己惹出麻煩的😅

Escalation Policy 範例

(話說這類警報管理 App 真的蠻厲害的,不管你的手機設定飛航還是睡眠,警報來了聲音都是會響會震,也會打電話給你,真的令人覺得可靠又可恨🤣)

遇到 Outage 時的處理過程

在我們的 On Call Handbook 有提到一點遇到警報時最重要的事:

Do not Panic !

Do not Panic !

Do not Panic !

雖然像是廢話,不過自己經歷過一次之後才了解到維持冷靜的重要性😂

首先要做的除了按下 Acknowledgement 以外,也需要先定義出問題的系統警報分級以及影響範圍,更要找出對應負責的團隊,因為雖然你是 On Call Engineer,並不代表你要獨自解決這個問題,更多的時候「找到對的人去做對的處理」才是需要做的事。

掌握了問題以及範圍之後,就是時候通知相關的人員了。溝通是關鍵,有效的協調確保每個人都 “On the same page” 是相當重要的。除了透過訊息通知相關人員以外,我們也會開一張 Jira ticket,將所有重要訊息放上去,也方便後續處理的追蹤。

(不要小看開 ticket 或是紀錄的步驟,擔任 On Call Engineer 其實很多時候都是在做文字紀錄,例如開 ticket、回答其他人的疑問、撰寫 On Call 日誌…等等,你的文字要能讓其他人一看就能了解到底發生了什麼事,培養透過簡潔的文字說故事的能力是非常重要的)

對於那些嚴重又複雜,沒有辦法迅速找出 Root Cause 的問題,通常我們會進入所謂的 On Call War Room,一個不同團隊工程師聚集在一起共同應對問題的線上會議,On Call Engineer 有時需要負責分析問題,並把正確的人選也拉到會議中一起討論解決方案。這個過程一開始會有點不習慣,因為可能在 War Room 裡的人你平常根本都沒有機會合作到,一個都不認識,也怕自己問了蠢問題,但我認為尋求幫助不是軟弱的表現,而是解決問題的策略行動,因此不要怕自己問的問題很蠢,如果能夠抽絲撥繭找出問題所在,一定都會有所幫助。

針對嚴重的問題,我們的目標很明確「Mitigate, Don’t Muddle」盡量透過一些 workaround 暫時修復與緩解問題,而不是直接修改程式碼更改 Production 的狀態,最後也應該恢復到最後一個已知的穩定狀態。舉個例子,如果有個重大的問題可以透過清一些 DB 的資料、重啟 Pods、開關 feature flags 就可以緩解,就盡量避免直接更改 codebase。

一旦完成緩解措施,應該按照有結構的方法來找出根本原因 (Root Cause),從核心修復它,並確保未來有更穩定的基礎。當所有警報恢復正常且產品行為對所有客戶都符合預期時,可以認為問題已解決。重要的是要注意,問題被認為是在 permanent fix is in production 後才算解決,而不是在緩解之後。

最後一步是 Root Cause Analysis(RCA)。這個文件紀錄誰、什麼、哪裡、何時以及為什麼,以提取有意義的見解以及紀錄整個警報處理流程。在這一步中,我們可以記錄哪些做得好/不好,以及下一步可以如何進一步改進。我們的 RCA 報告並不是由 On Call Engineer 負責撰寫,但可想而知這步驟非常重要,每一次的經驗都可能是避免下一次遇到同樣問題的契機。

On Call 效率相關 Metrics

現在我們知道如何對警報做出反應,一些可以幫助我們了解團隊 On-Call 流程指標的數據包括:

MTTA( mean time to acknowledge 平均響應時間)是從觸發警報到開始處理問題的平均時間。這個指標有助於追踪團隊的響應速度和警報系統的有效性。

MTTR(mean time to resolve 平均解決時間)是完全解決故障所需的平均時間。這不僅包括發現故障、診斷問題和修復問題所花費的時間,還包括確保故障不再發生的時間。

案例分享:我 On Call 時遇到的 Critical Issues

首先沒有遇到警報不代表就沒事做,我們的 On Call Engineer 還要負責 ticket 的 re-assign、Patch Deployment、監控 k8s Pods…等等事項。

這次 On Call 我主要遇到兩個 Critical Issue。

  1. Memcached lose connection issue

這個問題聽起來嚴重,但其實比較 minor,因為我們的 login session 主要都存在 Memcached 裡,如果會影響到 login 就勢必非常嚴重,不過這個問題並不會影響登入,只會在偶爾操作時發生。但因為我對 Memcached 也不熟,因此只能透過 Dashboard、Logging 搜集一些有用的相關資訊,並上報到 Operation 團隊做進一步調查。

2. 某個 Data Center 的 MariaDB 直接掛掉

還記得 On Call 某天的晚上 9 點,突然被 Ping 說要加入 On Call War Room,因為某個 Data Center 的 MariaDB 掛了,原因是 CPU Usage 爆量了。

進入 On Call War Room 後就開始一連串的抽絲剝繭,從 Dashboard 與 Logging Platform 盡可能蒐集相關資訊。初步看下來是某支公開的 API 被某個客戶打了之後會產生大量的 DB query,而剛好這個 query 沒有下好 Index,每次都得 Full Table Scan,因而造成 CPU Usage 爆量的狀況。前面也有提過遇到 Critical 的 Issue 時會先思考有沒有 Mitigate (緩解)的方法,而我們的做法是重啟 API Server 的 Pods,讓 MariaDB 的 CPU Usage 先降下去,雖然可以暫時緩解,但因為問題還沒解決,不久後 CPU 又會被撐滿,我們只能再次重啟 Pods,這當然是治標不治本,看來還是要更根本的解決問題才行。

當天印象很深刻的是從晚上 9 點發現問題到了凌晨 12 點,我就交接給美國時區的 On Call Engineer,結果隔天睡一覺起來後問題還是沒有被解決,於是我在第二天的中午 12 點又再次進入了 On Call War Room,直到晚上 10 點半才解決問題離開 War Room,整整 10 個半小時,除了上廁所以外,其他的時間我都坐在電腦前參與線上會議,當天說真的有點快要崩潰了。

經過長時間的抽絲剝繭後,終於發現問題出在一段沒有寫好得 Code,會造成 query 不停 loop 的狀況,幸好當初這個 feature 在開發時有導入 feature flag,所以關掉 feature flag 之後 CPU 總算沒有再飆升了。

雖然只有一個 Data Center 遇到這個問題,但為了保險起見,也進到不同 Data Center 的 Cluster 中把這個 feature flag 都先關掉了。

這個解法看似簡單,但在一個龐大的 Codebase 中要找出奇怪問題的 Root Cause 其實非常困難,還要思考每一個解法的 Trade Off,整個解題的過程非常有趣,大家會輪流 Share 畫面,分享自己的發現,透過這次經驗我也驚覺自己的英文能力還是十分不足,每次心裡想的內容講出來好像都只剩下67成,這是我得再加強的地方。

心得感想

雖然我的職位是 Full Stack Engineer,不過日常開發上前後端的比率大約還是 7:3。但透過這次準備 On Call 的過程,學了很多 Infra 或是 Operation 的觀念,例如 Pods 的管理、DB 的操作、部署、Observability…等等。而且也發現 On Call 時遇到的 Critical Issues 比較少是前端方面的問題,畢竟就算畫面有問題至少服務大多數狀況還是可用的,這也是我需要持續加強的面向。

對我而言 On Call 帶來的好處還有學會 Take Ownership & Responsibility。我在過往的工作經驗中總會懷疑自己的價值,認為有沒有自己好像都沒差,但在 On Call 時出事情大家第一個找的是你,也指望你可以找出解決方案或帶領任務的進行,一開始會覺得自己很衰,但調整心態後會發現這些都是成長的機會,學會扛下倒在身上的重擔與責任,才有機會持續成長。

簡單紀錄了一下第一次 On Call 的經歷,希望能讓其他人更理解 On Call 都在做些什麼事,如果你跟我ㄧ樣要面對 On Call 且不太喜歡這個制度或是感受到些許壓力,把它看成提升自己的精神時光屋也許是不錯的方式喔!

(最後感謝強者同事 John & Timo & Catty 雖然沒有輪到 On Call 卻也還是幫了不少忙,救了我好幾次)

--

--

莫力全 Kyle Mo
莫力全 Kyle Mo

Written by 莫力全 Kyle Mo

什麼都想學的雜食性軟體工程師 🇹🇼 (https://github.com/kylemocode) 合作與聯繫 📪 oldmo860617@gmail.com IG 技術自媒體:@kylemo.webdev.life

No responses yet