天天看點

代碼拼寫錯誤導緻 17 個生産資料庫被删!微軟 Azure DevOps 當機始末

作者:InfoQ

作者 | 淩敏、核子可樂

由于低級錯誤,本該清理資料庫快照的修複代碼卻删掉了整個伺服器。

一個拼寫錯誤緻微軟 Azure DevOps 當機 10 小時

微軟Azure DevOps是一套應用程式生命周期服務。5 月 24 日,Azure DevOps 在巴西南部(SBR)區域内一處 scale-unit(微軟 Azure 部署架構中最小的容量單元)設施發生當機,當機持續了 10 個小時。

近日,微軟首席軟體工程經理 Eric Mattingly 對當機事件表達歉意并透露了當機原因:一個簡單的拼寫錯誤,緻使 17 個生産資料庫遭到删除。

Mattingly 解釋道,Azure DevOps 工程師偶爾會儲存生産資料庫的快照,據此調查上報的問題或測試性能改進方向。為了清理這些快照資料庫,會有專門的背景作業每天運作,并在快照超過一定期限後将其删除。

在最近的一波沖刺(靈活上下文中的小組項目,編号為 Sprint 222)中,Azure DevOps 工程師執行了代碼更新,想要用受支援的 Azure.ResourceManager.* NuGet 包替換掉已被棄用的 Microsoft.Azure.Managment.*包。

這對應着一條巨大的 pull request 變更請求,會将舊包中的 API 調用替換為新包中的 API 調用。引發此次事件的拼寫錯誤就出現在 pull request 内,導緻背景快照删除作業删掉了整個伺服器。

Mattingly 表示,“這條 pull request 中的快照删除作業裡隐藏着一條拼寫錯誤,它會删除 Azure SQL 資料庫調用,并替換成删除托管資料庫的 Azure SQL Server 調用。”

Azure DevOps 工程師使用安全部署實踐(SDP)将 Sprint 222 部署到了 Ring 0(微軟内部 Azure DevOps 組織),這裡不存在快照資料庫,是以删除作業不會執行。在 Ring 0 測試幾天之後,Azure DevOps 工程師又将其部署至 Ring 1,也就是在此期間巴西南部的 scale-unit 設施受到了影響。快照資料庫的存在時間觸發了這項 bug,該作業在删除 Azure SQL Server 的同時,還删掉了 scale-unit 設施中所有 17 個生産資料庫。從這時起,Azure DevOps 的 scale-unit 無法處理任何客戶流量。

據 Mattingly 介紹,此次當機事件并未引發資料丢失。為了防止問題再次發生,Mattingly 稱微軟已經采取了各種修複和重新配置措施,并向所有受此中斷影響的客戶道歉。

為什麼耗時 10 小時才完成恢複?

據了解,Azure DevOps 是有檢測此類問題的測試的。但根據 Mattingly 的介紹,“之是以以往沒有發現,是因為這部分代碼的運作條件非常罕見,我們的測試并沒有切實覆寫這些極端情況。”有推測認為,這種極端條件要求删除腳本捕捉到特别陳舊的資料庫快照。

雖然目前資料已經全部恢複,但整個當機前後耗時 10 多個小時,為什麼這麼久才完成修複?Mattingly 對此做出了解釋說明:“我們在資料庫被删除後的 20 分鐘内檢測到當機,值班工程師立即參與修複。在快速了解問題來源之後,我們開始恢複 SQL Server 及所有資料庫,并禁用了快照删除作業以防止該 bug 影響到其他客戶。但由于問題數量較多,是以恢複時間也相對較長。”

首先,客戶無法自行恢複 Azure SQL Server,是以必須由 Azure SQL 團隊參與恢複工作。确定需要 Azure SQL 值班工程師介入,接洽實際情況和問題,再加上伺服器的實際恢複大約耗費了 1 個小時。

其次,所有資料庫均配置有備份備援,但部分資料庫的建立時間早于區域備援備份的上線時間。在恢複資料庫時,Azure DevOps 為所有資料庫選擇了 Geo-zone-redundant,導緻一部分還原資料按照此前配置的 Zone-redundant 備份被複制到了配對區域。這種比對沖突又讓恢複過程延長了好幾個小時。對于這個問題,Azure DevOps 将確定所有資料庫備份均按 Azure 區域支援被配置為 Geo-zone-redundant,使其覆寫 Azure DevOps 中的所有 scale-unit。

最後,在資料庫開始恢複上線之後,由于 Azure DevOps 的 Web 伺服器出現了一系列複雜問題,盡管資料庫内容已經完成還原,客戶也仍然無法通路整個 scale-unit 設施。

這個問題源自伺服器的預熱任務,該任務會通過測試調用周遊可用的資料庫清單。但恢複過程中資料庫招聘了一項錯誤,導緻預熱測試“執行指數級退避重試,令預熱耗時由正常情況下的不到一秒延長到了平均 90 分鐘。”

更複雜的是,整個恢複過程是交錯進行的,一旦其中一、兩台伺服器重新開始接收客戶流量,就會因過載而再次當機。最終,工程師在隻能阻斷所有流向巴西南部 scale-unit 的流量,確定一切準備就緒再重新加入負載均衡器并處理流量。

如何避免此類問題再次發生?

目前,Azure DevOps 已經修複了快照删除作業中的 bug,并為快照删除作業建立了新的測試,面向真實 Azure 資源充分反映快照資料庫的删除場景。

Mattingly 表示,Azure DevOps 正着手為關鍵資源添加 Azure 資料總管鎖,借此防止意外删除。同時,確定所有 Azure SQL 資料庫備份均被配置為 Geo-zone-redundant 形式,并受到 Azure 區域的支援;確定未來的所有快照資料庫,隻會被建立在不同于生産資料庫的 Azure SQL Server 執行個體之上。

此外,還會修複 Web 伺服器預熱任務的邏輯,確定即使資料庫處于脫機狀态時也能成功啟動。并建立新的 cmdlet 來恢複已被删除的資料庫,確定恢複結果使用與被删除前相同的設定(包括備份備援)。

參考連結:

https://status.dev.azure.com/_event/392143683/post-mortem

https://www.theregister.com/2023/06/03/microsoft_azure_outage_brazil/

繼續閱讀