簡介:生產環境的突襲演練是我們邁出的艱難但有力的一步,鍛鍊了研發運維人員的應急響應能力,在真實使用者場景下錘鍊系統,推進了產品的輪班制度,提升了雲原生底座的穩定性和競爭力。
作者:智妍(鄭妍)、浣碧(何穎)
什麼是混沌工程,雲原生大潮下的混沌工程特點
透過使用雲計算廠商如阿里雲、AWS 等提供的服務,現代服務提供者得以用更低廉的成本,更穩定地進行豐富的軟體服務提供。但是真的一切如此輕而易舉嗎?主流雲計算廠商在 SLA 承諾的範圍內,都各自出現過一些歷史故障,可參見這份血淋淋的 github 上的報告列表[1]。另一方面,各個雲產品提供給了使用者使用的一些高可用能力,經常依然是需要用正確的姿勢來配置和使用的。
混沌工程可以幫助業務系統服務提供者透過建立破壞性事件、觀察系統和人員響應方式、針對最佳化改進這 3 個步驟來發現生產服務中脆弱的環節,並根據預期的 SLA 目標進行實施改進。除了指出需要改進的系統元件設計問題之外,混沌工程還可幫助發現需要監控和告警上的盲點、發現人員對系統理解、應急響應 SOP、排查能力上的不足,進而使得業務系統及其研發、運維人員整體的高可用能力水位大大上浮。因此 Netflix 提出此概念後,各大軟體廠商紛紛進行了對內實踐和對外產品提供。
雲原生在傳統雲計算基礎上,提供了更快更低成本的彈性,更好的軟硬一體化靈活性,已經成為雲計算發展最快的技術方向。雲原生幫助開發者大幅度降低資源成本和交付成本,從而更快更好地贏得市場。同時,雲原生也給傳統運維、研發方式帶來了徹底的變革,這就使得傳統的混沌工程手段需要跟隨演進。
雲原生背景下,其上的應用服務的混沌工程實施和傳統有什麼不同呢?從我們在阿里電商、中介軟體雲原生化的大量實踐中,總結出以下主要差異:
在這樣差異的背景下,用雲原生的手段,實施更加針對植根於雲原生應用的場景的混沌工程,是更加恰如其分,能夠提供更多能力提升的。
混沌工程實施模式的階段和發展
既然混沌工程能帶來如此多的好處,一個基於雲原生的應用服務或體系想要實踐,要如何落地呢?
從演練工具和落地實施來看,一個組織的故障演練經常分為幾個發展階段:手工演練,流程工具自動化演練,常態化無人值守演練,生產突襲演練。
這幾個階段的實施難度是從低到高,當然相應的收益也是從低到高。一個組織(雲使用者)可以隨著自己業務應用服務體量的增大、複雜化和高可用能力的增高的歷程,根據實際情況需要選擇自己合適的階段,然後隨之進行升級和發展。即使從最簡便的手工演練開始做起實施,經常也能帶來相當明顯且長遠的高可用能力系統性提升。
那麼每個階段分別有什麼特點,又該如何選擇呢
- 手工演練:一般在高可用能力建設初期階段,或者一次性驗收的情況下手工注入故障完成。透過人為檢視告警是否生效,系統恢復情況來進行演練。在這個階段只需要一些故障注入的小工具或者指令碼,方便後續使用即可。
- 自動化演練:高可用能力建設到一定階段後,往往會有定期檢查高可用能力是否退化的需求,自動化演練開始排上日程。自動化演練步驟一般包括:環境準備 -> 故障注入 -> 檢查 -> 環境恢復。在每個步驟中配置相應的指令碼來形成演練流程,下一次就可以一鍵點選自動化執行了。
- 常態化執行:演練進行到下一階段,我們會有更高的要求,希望演練可以自主混沌化執行,以無人值守的方式進行,這又對系統的高可用能力有了新的挑戰。這要求系統有不僅有監控告警可以發現故障,也有對應的預案模組來負責恢復,而要做到無人值守,需要系統進行更智慧精確的判斷故障情況,自動執行相應預案。
- 生產突襲:以上演練大多在灰度環境進行,不會影響到業務,生產突襲則要求系統有能力在生產環境控制爆炸半徑的前提下進行故障演練,以期發現一些業務相關、規模相關、配置相關、應急響應相關的,在灰度環境遺漏的部分,生產環境的演練對系統的要求較高,需要有一套執行規範,對系統的隔離能力也有較高要求。大多數的工作,能力建設都在灰度環境完成驗證,但生產突襲仍作為一個有效且必要的演練手段,用更真實的場景給研發體感,讓其真實執行預案,也鍛鍊了應急能力,對系統有更多信心和認知。
如何進行一次完整的故障演練實施
當應用首次使用 Kubernetes 進行應用部署和擴容時,最先關注的更多是功能是否可用,故障演練則是更高級別的要求,我們假設當前的系統已經初步通過了功能驗收,但對於一些故障情況下系統的表現還未知的前提下,來開始我們的故障演練之旅。
故障演練本身作為一種破壞性的操作,需要循序漸進,遵循一定的規範和流程來落地。下面我們從環境建設、系統能力分析、高可用能力建設、演練實施建議幾個方面來介紹一下,一個首次在 Kubernetes 中部署起來的應用應該如何循序漸進的實施故障演練。
Step 1:隔離環境建設
故障演練,特別是首次執行之前,我們需要明確好當前注入故障的環境情況,是否可能影響到業務流量,是否會造成無法彌補的損失,在阿里內部,我們有複雜的環境隔離和變更管控,以防故障注入影響到業務流量。
在環境類別上,我們會區分為以下幾類:
- 業務測試環境:用來進行 e2e 測試,全面的功能驗收,這個環境和有業務流量的生產網路是隔離的,從網路上避免了流量錯誤進入到其他環境,因此可以在這個環境上盡情的進行各種容錯性測試。
- 金絲雀環境:可以理解為是一種全面的鏈路灰度環境,這個環境有當前系統的所有元件,一般用來做上下游聯調,系統內部的鏈路灰度使用,這個環境是沒有實際業務流量的;
- 安全生產灰度環境:這個環境我們會引入 1% 的生產流量,並提前建設了切流能力,一旦這個環境出現問題,可以把流量迅速切換到生產環境中,該環境一般用來結合使用者流量做一段時間的灰度,以免全量釋出導致的不可控;
- 生產環境:真實使用者流量的環境,這個環境的任何運維動作都需要進行嚴格的變更稽核和前幾個環境的灰度透過才能變更;
故障演練一般會開始在金絲雀環境引入,可以在全鏈路、無真實流量的環境中做一些高可用能力的建設和驗收,常態執行的演練,在這個環境演練多次的場景,可定期在灰度環境和生產環境中、控制爆炸半徑的前提下進行真實突襲,作為能力的驗收。
一般情況下,考慮到成本投入和系統複雜度,業務應用可能不會建設 4 個隔離環境來循序漸進的推進,但我們推薦應用應該至少有兩個環境來區分使用者流量,環境上至少有一個和生產隔離的灰度環境,至少初期必須如此。環境建設中需要關注的問題如下:
- 隔離性:灰度環境和生產環境儘量做到隔離,包括但不限於網路隔離,許可權隔離,資料隔離等,考慮到一些容災的能力,還可以將兩個叢集建設在不同地域的 Kubernetes 叢集中。
- 真實性:灰度環境和生產環境儘量保持一致,比如外部依賴,元件版本。
環境建設達標後,才具備了演練的准入條件。
Step 2:故障場景分析
在分析系統的高可用能力時,往往沒有一個統一的答案,每個系統的薄弱點,瓶頸都不盡相同,但整理系統高可用能力時,我們可以提供一些通用的思路。
- 歷史故障:
歷史故障通常是快速瞭解一個系統薄弱能力的教科書,透過分析歷史故障,進行分類,可以快速得出當前系統那些元件更容易出現問題。
比如系統能力需要進行快速的彈性伸縮,伸縮失敗可能影響業務流量,可以推斷出它強依賴 Kubernetes 的擴縮容能力,需要監控關注此能力的可用性;比如系統資料讀寫頻繁,歷史出現過資料不一致問題,則可以考慮在資料層面進行穩定性建設,增加備份能力,回滾能力等。
- 架構分析
系統的架構在一定程度上決定了這個系統的瓶頸,透過分析系統的依賴也可以更瞭解系統的邊界,也更便於進行運維上的最佳化。
比如一個應用的部署方式是主備模式的,那必須要檢查的能力就是主備切換是否順暢,切換過程是否影響到業務流量;比如一個應用強依賴底層儲存,一旦儲存掛掉,業務會大面積故障,則在整理高可用能力的時候就需要想到儲存掛掉後是否有降級方案,儲存問題是否可以提前預警。
- 社群經驗:
很多系統的架構都是大同小異的,參考社群或友商的經驗就像提前看了模擬考題,總會有意想不到的收穫。我們總會在業界爆出一些故障時進行自我反思和重新整理,多次發現了自身的一些問題。網線被挖斷、刪庫跑路等寶貴的經驗庫,都在我們定期演練的列表中。
在阿里雲原生的架構上,我們整理瞭如下所示的演練模型供參考,在這個高可用能力模型中,我們根據系統架構按照管控層元件、元叢集元件、擴充套件元件,資料儲存,節點層,整體叢集進行區分,在每個模組中有一些通用的故障可以互相借鑑。
Step 3:系統高可用能力建設
在實際進行故障注入前,我們還需要問自己幾個問題。根據上述已經分析到的我們想讓系統擁有的高可用能力列表,系統是否具備當這些故障來臨時有敏捷的發現能力,人員有迅速的響應能力,系統本身是否具備自愈的能力或一些可用來在故障過程中使用快速恢復系統的工具呢?下面我們從發現能力和恢復能力兩個方面來給一些通用的建議。
- 發現能力
監控和告警是能夠發現系統是否處於穩態並讓應用負責人一目瞭然的方式。阿里內部團隊建設了兩種監控告警方式,一種是白盒告警,藉助系統內部暴露出來的各種維度的可觀測性資料的異常波動來發現潛在問題;一種是黑盒告警,從客戶視角把系統當做黑盒,探測正向功能。
- 恢復能力
故障來臨後,最優的結果是系統穩定絲滑,毫無影響,這對系統的能力建設要求極高,而實際的情況往往更為複雜。在阿里內部的實踐中,除了對系統本身專門建設了基本的程序自愈、切流能力、遷移能力、限流能力等,也建設了預案中心,中心化的沉澱我們所有的止損能力到系統中,白屏管理,接入,執行,根據專家經驗建立止損能力集,作為故障時的重要工具。
Step 4:演練實施
以上步驟完成之後,我們認為系統已具備了初步的高可用能力,可以開始實施故障演練。
一般情況下首次演練我們會挑選一些核心場景進行,在預發或測試環境,工具上使用半自動化的指令碼或僅包含故障注入模組的流水線來觸發,在研發和運維人員在場的情況下進行首次試驗。試驗前確認場景的預期,比如故障注入後需要 1min 進行告警,10min 內系統自愈恢復,以便在演練過程中隨時確認。演練執行後需要各部分人員進行人工確認系統表現是否符合預期,演練結束後及時恢復故障和環境。場景在演練過程中不符預期的部分,需要多次在此階段不斷驗證和演練;符合預期的場景進行標記,可以開始進入到常態化演練階段。
常態化演練階段的關鍵詞是混沌化、無人值守,Kubernetes 叢集由於架構的優勢,本身具備一定的自愈能力,因此更適合無人值守的演練。我們會篩選已經透過半自動演練的場景集合,組織為一些故障演練流水線,每個流水線中一般包含故障注入、監控檢查、恢復檢查、故障恢復等步驟,來閉環完成單個演練流程。同時阿里內部使用雲原生技術進行混沌化觸發,實現在演練物件、環境、時間、場景上的隨機,使得這些演練場景可以混沌化、常態化、無人值守的執行。透過常態化故障演練,助於發現一些偶發性系統問題,並可以在系統升級過程中協助檢查已有的高可用能力。
生產突襲的實施需要根據系統的架構情況進行,在阿里內部的實施中,一種控制風險的方式是選擇流量低峰去進行,並提前預備一鍵切流預案,一旦出現故障無法恢復的情況,立即切流止損。其他突襲相關的風險控制設計我們會在後續的系列文章中詳細分析。
結語
在內部雲原生領域實施故障演練的過程中,我們分析了 200 多個演練場景,透過 1000+/月的頻次進行常態化故障演練,有效的發現了 90 多個問題,避免了問題半徑進一步擴大;透過演練流程的搭建、校驗和混沌化執行,定期監測系統的告警和預案恢復能力,有效的攔截 50 多個新增高可用問題上線。生產環境的突襲演練是我們邁出的艱難但有力的一步,鍛鍊了研發運維人員的應急響應能力,在真實使用者場景下錘鍊系統,推進了產品的輪班制度,提升了雲原生底座的穩定性和競爭力。
本文為阿里雲原創內容,未經允許不得轉載。