使用Grab的實驗平臺進行混沌實驗編排

Roman Atachiants · Tharaka Wijebandara · Abeesh Thomas

原文: https://engineering.grab.com/chaos-engineering

譯:時序

背景

對每個用戶來說,Grab是一個可以叫車,叫外賣或付款的一個APP。對工程師來說,Grab是一個有許多服務並通過RPC交互的分佈式系統,有時也可以叫做微服務架構。在數千臺服務器上運行的數百個服務每天都有工程師在上面進行變更。每次複雜的配置,事情可能都會變糟。 幸運的是,很多Grab App的內部服務不像用戶叫車那樣的動作這麼重要。例如,收藏夾可以幫用戶記住之前的位置,但如果它們不工作,用戶仍然可以得到較合理的用戶體驗。

服務部分可用並不是沒有風險。工程師需要對於RPC調用非核心服務時需要有有備用計劃。如果應急策略沒有很好地執行,非核心服務的問題也可能導致停機。

所以我們如何保證Grab的用戶可以使用核心功能,例如叫車,而此時非核心服務正在出問題?答案是混沌工程。

在Grab,我們通過在整體業務流的內部服務或組件上引入故障來實踐混沌工程。但失敗的服務不是實驗的關注點。我們感興趣的是測試依賴這個失敗服務的服務。

照理來說,上游服務應該有彈性並且整體業務流應該可以繼續工作。比如,叫車流程就算在司機地址服務上出現故障時仍應該可以工作。我們測試重試和降級是否配置正確,是否熔斷器被正確的設置。

為了將混沌引入我們的系統,我們使用了我們的實驗平臺(ExP)和Grab-Kit.

https://engineering.grab.com/introducing-grab-kit

混沌實驗平臺Exp將故障注入到處理流量服務的中間件(gRPC或HTTP服務器)。如果系統的行為與期望一致,你將對非核心服務故障時服務會平穩降級產生信心。

混沌實驗平臺ExP在Grab的基礎設施中模擬不同的混沌類型,如延遲和內存洩漏。這保證了每個組件在系統的依賴不響應或響應很高時仍能返回一些東西。它能保證我們對於實例級失敗有彈性,因為微服務級別的中斷對於可用性也是一個威脅。

配置混沌實驗

為了構建我們的混沌工程系統,我們認為需要在兩個主要領域引入混沌:

  • 基礎設置:隨機關閉基礎設施的實例和其他部分
  • 應用: 在較粗粒度引入運行時故障(如endpoint/request級別)

你可以稍後啟用有意的或隨機的混沌實驗:

  • 隨機的
  • 比較適合‘一次性’基礎設施(如EC2實例)
  • 測試冗餘的基礎設施對最終用戶的影響
  • 當影響面已經十分確定
  • 實驗
  • 精確度量影響
  • 使用實驗參數控制
  • 對最終用戶有限的影響
  • 適用於對於影響不十分確定的複雜故障(如延遲)

最後,你可以將故障模式按以下分類:

  • 資源:CPU,內存,IO,磁盤
  • 網絡:黑洞,延遲,丟包,DNS
  • 狀態:關機,時間,殺進程

這些模型都可以在基礎設施或應用級別使用或模擬:

使用Grab的實驗平臺進行混沌實驗編排

對於Grab,進行應用級別的混沌實驗並仔細度量影響面很重要。我們決定使用一個已有的實驗平臺來對圍繞系統的應用級別混沌實驗進行編排,即紫色部分,通過對下層像Grab-Kit這樣的中間件進行注入來實現。

為什麼使用實驗平臺?

現在有一些混沌工程工具。但是,使用它們經常需要較高級的基礎設施和運維技巧,有能力設計和執行實驗,以受控的方式有資源手工編排失敗場景。混沌工程不是簡單的在生產環境搞破壞。

將混沌工程理解成受控的實驗。我們的ExP SDK提供彈性和異步追蹤。這樣,我們可以將潛在的業務屬性度量對應到混沌失敗上。比如,在訂車服務上進行10秒延遲的混沌故障,我們可以知道多少輛車被影響了進而知道損失了多少錢。

使用ExP作為混沌工程的工具意味著我們可以基於應用或環境精確定製,讓它可以像監控和部署管道一樣與其他環境緊密集成。

在安全上也可以獲得收益。使用ExP,所有的連接都在我們的內部網絡中,給我們攻擊表面區域的能力。所有東西都可以掌控在手中,對外部世界沒有依賴。這也潛在的使監控和控制流量變容易了。

混沌故障可以點對點,編程式的,或定期執行。你可以讓它們在特定日期的特定時間窗口來執行。你可以設定故障的最大數量並定製它們(比如洩漏的內存MB數量,等待的秒)。

ExP的核心價值是讓工程師可以啟動,控制和觀察系統在各種失敗條件下的行為。ExP提供全面的故障原子集,用來設計實驗並觀察問題在複雜分佈式系統發生時的表現。而且,將混沌測試集成到ExP,我們對於部署流水線或網絡基礎設施不需要任何改動。因此這種組合可以很容易的在各種基礎設施和部署範式上使用。

我們如何打造Chaos SDK和UI

要開發混沌工程SDK,我們使用我們已有ExP SDK的屬性 - single-digit , 不需要網絡調用。你可以看這裡對於ExP SDK的實現。現在我們要做兩件事:

https://engineering.grab.com/feature-toggles-ab-testing

  1. 一個在ExP SDK之上的很小的混沌SDK。我們將這個直接集成在我們的已有中間件,如Grab-Kit和DB層。
  2. 一個專門的用來創建混沌實驗的基於web的UI

歸功於我們與Grab-Kit的集成,Grab工程師不需要直接使用混沌SDK。當Grab-Kit處理進入的請求時,它先使用ExP SDK進行檢查。如果請求“應該失敗”,它將產生適合的失敗類型。然後它被轉發到特定endpoint的處理器。

我們現在支持以下失敗類型:

  • Error - 讓請求產生error
  • CPU Load - 在CPU上加大load
  • 內存洩漏 - 產生一些永遠不能釋放的內存
  • 延遲 - 在一小段隨機時間內停止請求的處理
  • 磁盤空間 - 在機器上填入一些臨時文件
  • Goroutine洩漏 - 創建並洩漏goroutines
  • Panic -
  • 限流 - 在請求上設置一個頻率限制並在超過限制時拒絕請求

舉個例子,如果一個叫車請求到了我們的叫車服務,我們調用GetVariable(“chaosFailure”)來決定請求是否應該成功。請求裡包含所有需要用來做決定的信息(如請求ID,實例的IP地址等)。關於實驗SDK的實現細節,看這篇

博客。

https://engineering.grab.com/feature-toggles-ab-testing

為了在我們的工程師中推廣混沌工程我們圍繞它建立了很好的開發者體驗。在Grab不同的工程團隊會有很多不同的技術和領域。所以一些人可能沒有對應的知識和機能來進行合適的混沌實驗。但使用我們簡化過的用戶界面,他們不需要擔心底層實現。

並且,運行混沌實驗的工程師是與像產品分析師和產品經理不同的實驗平臺用戶。所以我們使用一種簡單和定製化UI配置新的混沌實驗來提供一種不同的創建實驗的體驗。

在混沌工程平臺,一個實驗有以下四步:

  1. 定義系統正常情況下的理想狀態。
  2. 創建一個控制組的配置和一個對比組的配置。控制組的變量使用已有值來賦值。對比組的變量使用新值來賦值。
  3. 引入真實世界的故障,例如增加CPU負載。
  4. 找到區分系統正確和失敗狀態標誌性不同。

要創建一個混沌實驗,標明你想要實驗破壞的服務。你可以在以後通過提供環境,可用區或實例列表來更細化這個選擇範圍。

下一步,指定一組會被破壞的服務影響的服務列表。你在試驗期間需要仔細監控這些服務。儘管我們持續跟蹤表示系統健康的整體度量指標,它仍能幫助你在稍後分析實驗的影響。

然後,我們提供UI來指定目標組和對比組的策略,失敗類型,每個對比組的配置。最後一步,提供時間週期並創建實驗。你已經在你的系統中加入了混沌故障並可以監控它對系統的影響了。

使用Grab的實驗平臺進行混沌實驗編排

結論

在運行混沌實驗後,一般會有兩種可能輸出。你已經確認了在引入的故障中系統保持了足夠的彈性,或你發現了需要修復的問題。如果混沌實驗最初被運行在預發環境那麼兩種都是不錯的結果。在第一種場景,你對系統的行為產生了信心。在另一個場景,你在導致停機故障前發現了一個問題。

混沌工程是讓你工作更簡單的工具。通過主動測試和驗證你係統的故障模式你減輕了你的運維負擔,增加了你的彈性,在晚上也能睡個好覺。


分享到:


相關文章: