GitHub 官方把 8 月 17 日那場停機的起點寫得很平淡——流量創了新高,中央美國一個關鍵基礎設施元件沒能隨之擴展——但同一篇貼文也承認,四月至今的月 commit 數從 14 億衝到 29 億。
四個月內 commit 數翻倍,GitHub 8/17 的容量問題不是巧合
這篇文章的材料一半來自 GitHub 官方在 8 月 20 日發出的貼文〈The August 17 outage, and the work ahead〉,作者是新任 CTO Vlad Fedorov;另一半來自 gslin 隔天寫的分析,把「流量創新高、元件沒跟上」這句平淡的官方定調,擺回「AI 浪潮讓用量翻倍」的脈絡裡重看。官方自己承認,8 月 17 日的停機總共拖了 7 小時 47 分,波及 github.com、身分驗證、GitHub Actions、API、pull request、issue 與 Copilot,幾乎是整個平台。
「流量創新高,元件沒跟上」——這句話蓋掉了什麼
Fedorov 在貼文裡對故障起點的描述是:「traffic reached a new peak, and a critical infrastructure component in our Central US data center failed to scale with it. The resulting capacity pressure spread through our systems, causing authentication failures」。翻成白話:流量衝上新高,中央美國一個關鍵元件沒能跟著擴展,壓力擴散開來,最後是認證系統先垮。這個說法本身沒有錯,但也沒有回答一個更根本的問題——為什麼是現在,為什麼是這個元件。故障報告習慣把鏡頭停在最後倒下的那一塊拼圖,很少往回拉,去看拼圖前面那一整段是怎麼被堆起來的。
答案藏在同一篇貼文的另一段數字裡:「Since April, monthly commits have grown from 1.4 billion to 2.9 billion.」自四月以來,GitHub 的月 commit 數從 14 億衝到 29 億,超過兩倍。貼文接著補了一句:「Today, Azure serves roughly 58% of GitHub's platform load and half of all Git operations, up from 12% of platform load in May.」五月時 Azure 只扛 12% 的平台負載,現在已經拉到大約 58%,順帶吃下一半的 Git 操作。
gslin 把這兩組數字放進更大的脈絡裡看:「一般來說已經是全球領先的產品了,不太會有短時間翻倍等級的成長,但在這一波 AI 浪潮的關係,讓 GitHub 的用量在半年翻倍,結果 capacity 不夠用直接炸掉了。」這是他自己的判斷,用詞也很隨性——但把「AI 帶動的開發工具讓寫 code、開 PR、跑 CI 的頻率一起往上衝」當成背景,回頭看 8/17 那句平淡的故障說明,確實不再只是一次意外。問題是,這個背景故事能不能撐起「量太大」這個結論,還是只是巧合疊在一起。
這個成長速度真正麻煩的地方,在於容量規劃通常是照著季度或年度的曲線去抓,不是照著月成長率破表的曲線去抓。四個月內增加一倍出頭的月 commit 數,代表任何一次容量評估如果還在用「去年同期的成長率」當基準,到了下一次評估周期就已經過時。這不是 GitHub 一家的麻煩——任何一個因為 AI 工具而用量暴增的平台,理論上都會遇到同樣的規劃時間差,只是規模夠大、夠顯眼,出事的時候才會被拿出來檢視。往下拆三個候選解釋。
假設一:純粹是被流量壓垮
gslin 的第一句判斷很直接:「GitHub 前幾天 outage 主要是因為量太大就炸掉了」。如果只看「commit 數翻倍」跟「停機」擺在一起,這個結論很好懂——量上去了,系統扛不住,垮了。
但官方貼文同一段話也交代了自己做了什麼:「We have since added more than 3 million CPU cores, 120 petabytes of high-speed storage, and significant network capacity.」四個月內加了 300 萬顆 CPU core、120 PB 高速儲存,外加相應的網路容量。這不是一家對成長毫無防備的公司——如果單純是「沒在管容量」,不會有這種規模的擴充動作。
真正對不上的地方是範圍:擴充是全平台性的動作,但故障點卡在「中央美國資料中心裡的一個元件」。全局在長大,某個局部沒跟上,這比「整體量太大」更精確,也更值得往下追——是哪個局部沒跟上,為什麼偏偏是它。
如果一個系統真的是被單純的流量壓垮,症狀通常是全平台性的資源耗盡:CPU 打滿、記憶體用盡、每個服務在同一時間一起變慢。但官方的敘述不是這樣——故障點被鎖定在中央美國資料中心裡的一個元件;至於已經遷到 Azure 的那部分路徑當時的狀況如何,官方貼文並沒有交代。這個差異本身,就是「純粹是量太大」這個假設站不住腳的地方:量確實是背景壓力,但故障的形狀是局部的,不是全域的,值得繼續往下找是哪個局部先扛不住。
切換看官方定調的故障擴散順序 · 5 個階段
假設二:Azure 遷移的比例衝很快,但真的抵銷了成長嗎
官方貼文裡有一句常被忽略的細節:「Azure's infrastructure and capacity have also accelerated our work to scale the largest monorepos.」Azure 的基礎設施同時也被拿去支撐最大型 monorepo 的擴展工作——換句話說,遷移到 Azure 不是單純地把舊機器換成新機器,還牽涉到把負載模式本身重新設計過。這代表「遷移比例」這個數字,背後混雜了不同性質的工作,不能單純當成「風險轉移了多少」的量尺。
第二個候選解釋看起來更精確:GitHub 這幾年一直在把負載遷到 Azure,遷移比例從 5 月的 12% 衝到現在的 58%,理論上舊系統(也就是故障發生的「中央美國資料中心」那一側)扛的負載應該愈來愈輕才對。如果遷移速度夠快,成長的壓力大部分該由 Azure 吸收掉。
46 個百分點的遷移進度,壓縮在 5 月到 8 月這幾個月裡完成,這本身就不是一個小工程動作。正常情況下,把負載搬到新平台通常是分服務、分階段慢慢挪,很少在這麼短的時間裡衝出這種幅度——換句話說,GitHub 不是沒有在跑遷移,而是跑得比平常快很多,只是流量漲得比遷移還快,兩條曲線賽跑,流量那條先衝線。
問題是,遷移比例上升的同時,整體流量也在漲,而且漲得更快。這兩個數字都是官方給的,放在一起算一次就看得出蹊蹺:
拖曳滑桿看 5 月到 8 月之間,Azure 分流比例與整體流量怎麼互相影響 · 兩條曲線
Azure 分流比例58%
Legacy 路徑負載指數(以 5 月整體流量 1.0× 為基準,5 月時為 0.88)0.87
Azure 路徑負載指數(以 5 月整體流量 1.0× 為基準,5 月時為 0.12)1.20
把 5 月當基準(Azure 12%、整體流量算作 1 倍),拖到現在(Azure 58%、整體流量約 2.07 倍,也就是 29 億除以 14 億),留在舊路徑上的絕對負載,從 0.88 變成大約 0.87,幾乎沒有下降。同一段時間裡,Azure 那一側扛的絕對負載,從 0.12 衝到大約 1.20,成長了將近十倍。這段推算不是官方公布的曲線,是用官方給的兩組比例回推的假設模型,需要說清楚:合理的推測是,Azure 遷移比例衝得快,看起來像是在替舊系統減壓,但因為總流量也在同一時間翻倍,舊路徑實際扛住的絕對流量幾乎沒變。「中央美國資料中心裡的關鍵元件」擴展跟不上,可能不是因為遷移進度慢,而是因為它從頭到尾都沒有真正被卸下多少重量。
這個候選解釋比「純粹量太大」更貼近官方的敘述,但同樣不是完整答案——它解釋了為什麼某個舊元件會撐不住,沒解釋為什麼是那一天,不是別天。
這裡有一個容易被忽略的算術陷阱:遷移進度這種指標,天生就是用比例呈現的,比例愈高,故事聽起來愈安心。但只要分母(整體流量)也在同時間成長,比例上升不保證分子(絕對負載)跟著下降。工程團隊在讀遷移儀表板的時候,如果只看「遷移完成度」這一欄,很容易漏掉「同期整體流量漲了多少」這一欄——兩欄擺在一起看,才知道剩下的那一小塊,實際扛的是變輕了,還是根本沒變。
假設三:retry storm 是壓垮的最後一步
官方貼文裡有一句話,把復原過程中的一個細節講得很清楚:「Errors in those services triggered a client-side retry loop that increased traffic during recovery.」認證失敗之後,Copilot 相關服務的用戶端重試機制,在系統嘗試復原的過程中,又把流量往上推了一截。這不是故障的起點,是故障擴散之後、系統想要自我修復時額外加上去的一層負擔——一個本來該幫忙復原的機制,反而拖慢了復原。
GitHub 在同一篇貼文裡公布的修復方向,直接對準這個問題:「We are applying consistent retry limits, retry budgets, and variable timeouts across service-to-service interactions to prevent retry storms and cascading load.」統一服務間呼叫的 retry 上限、retry 預算與逾時設定,目的就是不讓一次局部故障透過重試機制自己滾雪球。這也側面證實了 retry storm 在這次事故裡是真實存在的現象,只是官方自己把它定位成加重傷勢的因素,不是造成傷口的原因。
retry loop 會形成這種效果,並不是 GitHub 特有的毛病:一個服務失敗,呼叫端重試;重試又因為下游還沒恢復而失敗,於是再重試——如果沒有退避策略跟上限,重試的請求量會比原本的正常流量還高,等於在系統最虛弱的時候,反而加倍打它。這正是官方後續要修的方向:retry limit、retry budget、變動逾時,三個手段合起來,就是不讓「想幫忙復原」的機制自己變成新的流量來源。
這起事故並不是 8 月唯一一次:「This was our second significant incident in August, following an actions failure on August 6.」8/6 才發生過一次 Actions 故障,8/17 是同一個月裡的第二起重大事件。放在成長曲線的脈絡裡看,這比「單一元件運氣不好」更像是容量餘裕已經薄到,隨便一個局部問題都足以觸底。
容量餘裕被壓得多薄——8 月兩起事故的距離
「second significant incident in August」這句話,比任何一個技術細節都更說明容量餘裕的狀態。8/6 的 Actions 故障、8/17 的這場停機,中間只隔了十一天。如果一個平台的容量餘裕足夠厚,兩起獨立的重大故障不太可能在同一個月裡連續發生,除非兩者共享同一個脆弱點,或者整個系統的餘裕本身已經薄到,任何一個局部問題都足以把它推過門檻。
容量餘裕這個概念,工程上通常不會直接寫進故障報告,因為它不是一個可以單獨測量的數字,而是「尖峰負載」跟「系統上限」之間那段距離。當這段距離夠寬,個別元件的小失誤會被緩衝掉;當這段距離變窄,任何一次流量創新高都可能直接撞上上限。四個月內 commit 數翻倍、Azure 分流比例衝上 58%,兩者疊加的結果,很可能就是把這段緩衝距離壓縮到官方口中「一個關鍵元件沒能隨之擴展」的程度——這是本文從時間軸推出的合理解讀,官方沒有直接用「餘裕變薄」這個說法,但兩起事故只隔十一天,這件事本身是可以觀察到的事實。
對維運團隊來說,這種「餘裕被悄悄吃掉」的狀態最難處理的地方,在於它不會有單一的警訊。每一項擴充動作單獨看都是對的——加 CPU core、加儲存、加速遷移,樣樣都在做;但如果沒有人定期把「尖峰流量」跟「系統上限」這兩個數字放在同一張圖上比較,餘裕縮小的速度就只能等到真的撞牆那天才被發現。8/6 跟 8/17 這兩起事故的距離,某種程度上就是這張圖遲遲沒被畫出來的代價。
官方認的答案,以及沒被明說的部分
把三個候選解釋擺在一起看:
點名詞看每個假設的證據等級 · 3 個假設
三個候選解釋裡,純粹是量太大gslin 原話:「主要是因為量太大就炸掉了」——官方同時承認四個月內加了 300 萬顆 CPU core、120 PB 儲存,量的壓力是背景,但不是完整答案。、 Azure 遷移沒真正卸下負載本文用官方兩組比例(Azure 12% 到 58%、月 commit 數 14 億到 29 億)回推的假設模型:舊路徑的絕對負載幾乎沒下降。官方沒有這樣講過,屬於推論,不是官方結論。、 retry storm 加重傷勢官方原話:「a client-side retry loop that increased traffic during recovery」——官方定調為復原階段的加重因素,修復措施也直接針對它。, 只有中間一項是本文自己回推的模型,其餘兩項都能在官方貼文裡找到原話。
| 時間點 | 數字 | 來源 |
|---|---|---|
| 8 月 6 日 | 第 1 起 | Actions 故障(官方稱本次為「當月第二起重大事故」) |
| 8 月 17 日 | 7h47m | 本次停機時長 |
| 4 月 → 8 月 | 14 億 → 29 億 | 月 commit 數 |
| 5 月 → 現在 | 12% → 58% | Azure 承擔的平台負載比例 |
| 8 月 20 日 | — | CTO Vlad Fedorov 貼出官方檢討文 |
官方最終定調的直接故障點,是認證系統在壓力擴散之後失效——這一點有原話佐證,不是推測。retry storm 確實在復原階段加重了狀況,官方自己公布的修復措施也證實了這一點。至於「Azure 遷移比例上升卻沒有等比例卸下舊系統的負載」,是本文用官方公布的兩組比例回推出來的模型,官方沒有這樣講過,只能算是合理的推測,不是官方結論。
這對讀者自己維運的系統也有參考價值:容量規劃常常只看「整體用量成長了多少」,但真正決定會不會出事的,是「成長有沒有平均分攤到每一條路徑上」。一個服務即使整體遷移進度看起來很漂亮,只要還有一小塊共用元件沒被拆開,那一小塊就會是壓力最先集中的地方——而且它未必是遷移計畫裡優先順序最高的那一塊,因為單看比例,它看起來已經在變小。
官方貼文沒有正面回答的問題是:如果沒有這場停機,那個「沒能隨流量擴展」的元件,會不會排進下一輪擴充計畫的優先順序。八月兩起事故之間只隔十一天,這比任何官方說法都更直接地暗示,容量餘裕已經薄到經不起等待正常排程——但「為什麼直到出事才被排上優先順序」,官方貼文沒有交代,這也是這篇分析目前能推到的極限。
三個候選解釋疊在一起,比單獨拿出任何一個都更接近事故的全貌:流量翻倍是背景;Azure 遷移比例雖然衝得快,但沒有真正替最脆弱的那個元件減壓,是結構性原因;retry storm 是壓垮駱駝的最後一根稻草,是觸發時機。gslin 在文章最後留了一句反問,沒有給答案:「話說很少在領跑地位還看到這種等級的成長,算是受益者還是受害者…?」已經是全球領先的程式碼平台,還能在短時間內把用量翻倍,這件事本身很難得;但同一件事,也直接讓 8 月變成兩次重大故障的月份。
Take-away:官方的故障說明幾乎都會先講最後一根稻草——這次是認證系統、是中央美國那個元件。真正決定容量夠不夠用的,是它前面那條看不見的成長曲線。下次看到「流量創新高」這種故障公告,先去找成長率的數字,再回頭看架構有沒有跟上,順序不能反過來。