GitHub服務中斷24小時11分鐘事故分析報告
來源 | The GitHub Blog
譯者 | 無明
UTC 時間 10 月 21 日 22:52,為了更換髮生故障的 100G 光纖裝置,美國東海岸網路中心與美國東海岸資料中心之間的連線被斷開。連線在 43 秒後恢復,但這次短暫的中斷引發了一系列事故,導致 24 小時 11 分鐘的服務降級。
前幾日,GitHub 經歷了一次事故,導致服務降級 24 小時 11 分鐘。雖然平臺的某些部分不受事故影響,但仍然有多個內部系統受到了影響,向用戶顯示了過時且不一致的內容。所幸沒有使用者資料丟失,但針對幾秒鐘資料庫寫入的手動調整工作仍在進行當中。在發生事故期間,Webhook 無法提供服務,也無法構建和釋出 GitHub Pages。
我們對每個受影響的使用者深表歉意。我們深切感受到使用者對 GitHub 的信任,併為構建能夠保持平臺高可用性的彈性系統而感到自豪。在這次事故中,我們讓使用者失望了,我們深感抱歉。雖然我們無法撤銷導致 GitHub 平臺長時間無法使用的問題,但我們可以解釋導致這次事故的原因、我們從中吸取的教訓以及我們將要採取的措施,以便確保類似情況不會再次發生。
背 景
大多數面向使用者的 GitHub 服務都執行在我們自己的資料中心。資料中心拓撲旨在提供強大且可擴充套件的邊緣網路,位於多個區域資料中心的前面,這些資料中心負責處理計算和儲存工作負載。儘管我們的物理和邏輯元件中內建了冗餘層,但我們的站點仍然有可能在一段時間內無法相互通訊。
UTC 時間 10 月 21 日 22:52,為了更換髮生故障的 100G 光纖裝置,美國東海岸網路中心與美國東海岸資料中心之間的連線被斷開。連線在 43 秒後恢復,但這次短暫的中斷引發了一系列事故,導致 24 小時 11 分鐘的服務降級。
之前,我們已經介紹過如何使用 MySQL 儲存 GitHub 元資料以及我們實現 MySQL 高可用性的方法。
GitHub 擁有多個 MySQL 叢集,大小從幾百 GB 到 5TB 不等,每個叢集最多有幾十個只讀副本來儲存非 Git 元資料,因此我們的應用程式可以提供拉取請求和問題管理、身份驗證管理、後臺處理協調等原始 Git 物件儲存之外的其他功能。應用程式不同部分的資料通過功能分片儲存在各種叢集中。
為了大規模提高效能,應用程式將資料直接寫入每個叢集的主資料庫,但在絕大多數情況下將讀取請求委派給副本伺服器。我們使用 Orchestrator 來管理 MySQL 叢集拓撲和處理自動故障轉移。Orchestrator 以 Raft 的共識演算法為基礎,可以實現應用程式無法支援的拓撲,因此必須十分小心讓 Orchestrator 配置與應用程式的期望保持一致。
事故時間表UTC 時間 2018 年 10 月 21 日 22:52
在發生網路分割槽時,主資料中心的 Orchestrator 根據 Raft 共識機制啟動了首領卸任(deselection)過程。美國西海岸資料中心和美國東海岸公有云的 Orchestrator 節點獲得了法定票數,並開始對叢集進行故障轉移,將寫入操作定向到美國西海岸資料中心。當連線恢復時,應用層立即開始將寫入流量引向西海岸站點的新主節點上。
美國東海岸資料中心的資料庫包含了一小段時間的寫入資料,這些資料尚未被複制到美國西海岸的資料中心。由於這兩個資料中心的資料庫叢集包含了其他資料中心不存在的資料,因此我們無法安全地將主資料庫轉移到美國東海岸資料中心。
UTC 時間 2018 年 10 月 21 日 22:54
我們的內部監控系統開始發出警報,告知我們的系統出現了大量故障。這個時候,已經有幾位工程師正在對收到通知進行分類。UTC 時間 23 點 02 分,第一響應團隊的工程師已經確定很多資料庫叢集的拓撲處於不正常狀態。Orchestrator API 顯示的資料庫複製拓撲只包含美國西海岸資料中心的伺服器。
UTC 時間 2018 年 10 月 21 日 23:07
到了這個時候,響應團隊決定手動鎖定我們的內部部署工具,以防止引入任何其他變更。在 UTC 時間 23:09,響應團隊將網站置為黃色狀態。這樣會自動將事故升級,並向事故協調員傳送警報。在 UTC 時間 23:11,事故協調員加入,兩分鐘後決定將網站置為紅色狀態。
UTC 時間 2018 年 10 月 21 日 23:13
這個問題影響了多個數據庫叢集。來自 GitHub 資料庫工程團隊的其他工程師也收到了通知。他們開始著手調查,看看需要採取哪些措施將美國東海岸資料庫配置為每個叢集的主資料庫並重新構建複製拓撲。這項工作具有很大的挑戰性,因為到目前為止,西海岸資料庫叢集已經從應用層接收了近 40 分鐘的寫入資料。另外,東海岸叢集中有幾秒鐘的寫入資料未被複制到西海岸,並阻止將新寫入的資料複製回東海岸。
保護使用者資料的機密和完整是 GitHub 的首要任務。30 多分鐘的美國西海岸資料中心資料寫入讓我們不得不考慮 failing-forward,這樣才能保證使用者資料的安全。然而,在東海岸執行的應用程式依賴於西海岸 MySQL 叢集的寫入資訊,目前無法應對由於跨國往返而帶來的額外延遲。這個決定將導致很多使用者無法使用我們的服務。最後我們認為,延長服務降級時間可以確保使用者資料的一致性。
UTC 時間 2018 年 10 月 21 日 23:19
通過查詢資料庫叢集的狀態,我們發現需要停掉元資料寫入作業。我們暫停了 Webhook 和 GitHub Pages,避免對已經從使用者收到的資料造成損壞。換句話說,我們的策略是優先考慮資料完整性,而不是站點可用性和恢復時間。
UTC 時間 2018 年 10 月 22 日 00:05
事故響應團隊的工程師開始制定解決資料不一致問題的方案,並實現 MySQL 故障轉移。我們的計劃是從還原進行備份,同步兩個站點的副本,回退到穩定的服務拓撲,然後繼續處理排隊的作業。我們更新了狀態,告訴使用者我們將要執行一次內部資料儲存系統的可控故障轉移。
MySQL 資料備份每四個小時進行一次並保留多年,但備份遠端儲存在一個公有云的 blob 儲存服務中。恢復數 TB 備份資料需要數小時時間,大部分時間用於從遠端備份服務傳輸資料。對大型備份檔案進行解壓縮、校驗、預處理並載入到新配置的 MySQL 伺服器上也花費了大量時間。在整個過程中,我們每天至少進行一次測試。在這個事故之前,我們從來沒有基於備份完整地重建整個叢集,而是依賴其他策略,例如延遲複製。
UTC 時間 2018 年 10 月 22 日 00:41
這個時候我們已經啟動了所有受影響的 MySQL 叢集的備份過程,工程師正在監控進度。同時,多個團隊的工程師正在研究如何加快傳輸和縮短恢復時間,並且不會進一步降低站點可用性或者損壞已有資料。
UTC 時間 2018 年 10 月 22 日 06:51
美國東海岸資料中心的幾個叢集已經從備份中恢復,並開始從西海岸複製新資料。這導致必須通過跨國連結執行寫入操作的頁面的載入時間變慢,但如果讀取請求落在新恢復的副本上,那麼從這些資料庫叢集讀取的頁面將返回最新結果。其他更大的資料庫叢集仍在恢復中。
我們的團隊已經知道如何直接從西海岸進行恢復,以突破從異地儲存下載導致的吞吐量限制,並對恢復過程越來越有信心,建立複製拓撲所需的時間取決於複製需要多長時間才能趕上來。這個估計是根據我們現有的複製遙測資料線性插值得出的,我們更新了狀態頁面,設定了兩個小時作為我們估計的恢復時間。
UTC 時間 2018 年 10 月 22 日 07:46
GitHub 釋出了一篇博文,提供了更多的背景資訊。我們在內部使用了 GitHub Pages,但因為幾個小時前所有的構建都已暫停,所以釋出這些內容需要額外的工作量。我們對造成的延遲深表歉意。我們希望能夠更快地釋出這些資訊,並確保在未來可以在這些限制條件下發布更新。
UTC 時間 2018 年 10 月 22 日 11:12
美國東海岸的所有主資料庫都已就緒。網站的響應能力也隨之提升,現在寫入操作被引向了與應用程式層同處同一物理資料中心的資料庫伺服器上。雖然這大大提高了效能,但仍有數十個資料庫讀取副本比主資料庫延遲了幾個小時。這些延遲的副本導致使用者在與我們的服務進行互動時看到不一致的資料。我們將讀取負載分散到大量的只讀副本中,每個請求都有可能到達已經有幾個小時延遲的只讀副本上。
實際上,要讓複製趕上主資料庫,所需的時間遵循的是功率衰減函式(power decay function)而不是線性軌跡。當歐洲和美國的使用者醒來並開始工作時,資料庫叢集的寫入負載增加,恢復過程所耗費的時間比原先估計的要長。
UTC 時間 2018 年 10 月 22 日 13:15
到目前為止,我們正在接近 GitHub.com 的高峰流量負載。事故響應團隊就如何開展後續的工作展開了討論。很明顯,複製延遲在增加。我們已經在美國東海岸公有云中配置額外的 MySQL 只讀副本。一旦這些例項就緒,就可以更容易在更多伺服器上分攤讀取請求。減少跨副本聚合可以讓複製更快趕上。
UTC 時間 2018 年 10 月 22 日 16:24
在副本進入同步狀態後,我們對原始拓撲進行了故障轉移,解決延遲和可用性問題。為了優先保證資料完整性,我們在開始處理積壓資料時保持服務狀態為紅色。
UTC 時間 2018 年 10 月 22 日 16:45
到了這個階段,我們必須平衡積壓資料所帶來的負載,因為過多的通知可能會導致生態系統的其他系統發生過載,我們還要儘可能快地將服務恢復到 100%。這個時候佇列中有超過 500 萬個 Webhook 事件和 8 萬個頁面構建請求。
當我們重新開始處理這些資料時,我們處理了大約 200,000 個 Webhook 負荷,這些負荷已經超過內部的 TTL 並被丟棄。在發現這個問題後,我們暫停了處理,並臨時延長了 TTL。
為避免進一步破壞狀態更新的可靠性,我們一直處於降級狀態,直到處理完所有積壓資料並確保我們的服務已明確恢復到正常的水平。
UTC 時間 2018 年 10 月 22 日 23:03
已處理完所有待處理的 Webhook 和 Pages 構建,並確認了所有系統的完整性和正常操作。網站狀態已更新為綠色。
下一步 解決資料不一致問題在恢復過程中,我們捕獲了 MySQL 二進位制日誌,其中包含我們在主站點中寫入但未被複制到西海岸站點的資料。未複製到西海岸的寫入數量相對較少。例如,我們最忙的一個叢集在受影響期間有 954 個寫入。我們目前正在分析這些日誌,並確定哪些寫入可以自行解決,哪些需要與使用者進行確認。我們有多個團隊參與了這項工作,並確定了有一類寫入已經被使用者重複操作併成功保留。我們的主要目標是保持使用者資料的完整性和準確性。
溝通
我們希望在事故期間向用戶傳達有意義的資訊,我們根據積壓資料的處理速度對恢復時間進行了多次公開估算。回想起來,我們的估算並沒有考慮到所有的變數。我們對此造成的混亂感到抱歉,並希望在將來能夠提供更準確的資訊。
技術舉措
在此次分析過程中,我們確定了很多技術舉措。隨著我們繼續在內部進行廣泛的事故後分析,我們發現我們有更多的工作要做。
調整 Orchestrator 配置,以防止跨區域選舉主資料庫。Orchestrator 只會按照配置的引數執行,不管應用程式層是否支援這種拓撲變更。單個區域內的首領選舉通常是安全的,但突然出現的跨國延遲是導致這次事故的主要因素。這是系統的緊急行為,因為我們之前沒有遇到過這麼大規模的內部網路分割槽。
我們已經建立了一個可以更快報告狀態的機制,可以更清晰地談論事故的進展。儘管 GitHub 的很多部分在事故期間仍然可用,但我們只能將狀態設定為綠色、黃色和紅色。我們意識到,這並不能讓我們準確瞭解哪些部分在正常執行,哪些部分出現了故障,在將來,我們還將顯示平臺的不同元件,這樣就可以瞭解每項服務的狀態。
在事故發生前的幾周,我們啟動了一項全公司範圍的工程計劃,通過多活設計讓多個數據中心為 GitHub 流量提供支援。這個專案的目標是在設施層面支援 N+1 冗餘,在不影響使用者的情況下容忍單個數據中心故障。這是一項很重要的工作,需要一些時間。我們相信這種跨地理位置相連線的網站可以提供了一系列良好的權衡。這次事故加劇了這個專案緊迫性。
我們將在驗證我們的假設方面採取更積極主動的立場。GitHub 是一家快速發展的公司,在過去十年中已經具備了一定程度的複雜性。隨著公司不斷的發展,捕捉和轉移權衡和決策的歷史負擔將變得越來越困難。
這次事故導致我們對站點可靠性的看法發生了轉變。我們已經意識到,更嚴格的運維控制或改進的響應時間對於像我們這樣複雜的服務系統的站點可靠性來說仍然是不夠的。我們還將啟動一種系統性實踐,在故障場景有可能對使用者產生影響之前對其進行驗證,我們將在故障注入和混沌工程方面進行投入。
結 論我們知道使用者有多依賴 GitHub 給專案和企業帶來成功。沒有人比我們更關心服務的可用性和資料的正確性。我們將繼續分析這次的事件,以便為使用者提供更好的服務並贏得使用者對我們的信任。
英文原文:
https://blog.github.com/2018-10-30-oct21-post-incident-analysis/
完
1.微信群:
新增小編微信:tangguoyemeng,備註“進群+姓名+公司職位”即可,加入【雲端計算學習交流群】,和志同道合的朋友們共同打卡學習!
2.徵稿:
投稿郵箱:[email protected];微訊號:tangguoyemeng。請備註投稿+姓名+公司職位。
推薦閱讀
掃描以下二維碼即可參與“2018 年 CSDN 軟體開發者大調查活動”!我們還為你準備了精美的禮品,華為 nova3 智慧手機、小愛智慧音箱、CSDN 揹包、CSDN 定製T恤、數百本技術圖書等你來拿!參與即有機會獲贈,還等什麼,快來試試吧!
↓↓↓ 點選【閱讀原文】檢視「CSDN雲端計算」往期精彩內容