混沌工程簡介

混沌工程簡介


最近看到 Netflix 的混沌工程的介紹,感觸頗深。在 TiDB 裏面,我們爲了保證系統的健壯性,也做了很多工作。在內部我們開始叫做 stability test,後來進化成 Schodinger 平臺。之前我一直苦於沒有沒法對我們做得工作進行歸類,畢竟它可能是一個 test,但又比 test 做得多一點,現在知道,原來我們一直做的其實算是一門工程實踐。


既然是工程,那麼就會有方法論,也就能詳細的歸納總結出來實施的步驟,這樣後面的同學就能非常快速的學習掌握,而不會像我們之前那麼漫無目的的探索了,但我們現在還做不到這一步,而且相比 Netflix,我們還有很多路要走。所以我打算深入研究下 Netflix 是如何做的,在想想如何提升我們自己的工作。

介紹

首先,我們需要知道,混沌工程到底是什麼。根據 Netflix 的解釋,混沌工程師通過應用一些經驗探索的原則,來學習觀察系統是如何反應的。這就跟科學家做實驗去學習物理定律一樣,混沌工程師通過做實驗去了解系統。


微信圖片_20200528102838.png


上圖就是混沌工程的典型代表 - 猴子。拜 Netflix 所賜,現在大部分的混沌工程項目都叫做 Monkey,也就是一隻討厭的猴子,在你的系統裏面上蹦下竄,不停搗亂,直到搞掛你的系統。

然後,我們需要知道,爲什麼需要混沌工程。應用混沌工程能提升整個系統的彈性。通過設計並且進行混沌實驗,我們可以瞭解到系統脆弱的一面,在還沒出現對用戶造成傷害之前,我們就能主動發現這些問題。

混沌工程其實是很重要的,但我之前一直以爲混沌工程就是測試,但它們還是有區別的。雖然混沌工程跟傳統測試通常都會共用很多測試工具的,譬如都會使用錯誤注入工具,但混沌工程是通過實踐對系統有更新的認知,而傳統測試則是使用特定方式對某一塊進行特定測試。譬如在傳統測試裏面,我們可以寫一個斷言,我們給定特定的條件,產生一個特定的輸出,如果不滿足斷言條件,測試就出錯了,這個其實是具有很明確的特性。但混沌工程是試驗,而試驗會有怎樣的新信息生成,我們是不確定的。譬如我們可以進行下面的這些試驗:

  • 模擬整個 IDC 當掉

  • 選擇一部分網絡連連接注入特定時間的延遲

  • 隨機讓一些函數拋出異常

  • 強制 NTP 時間不同步

  • 生成 IO 錯誤

  • 榨乾 CPU

這些試驗到底會有什麼樣的結果,有些我們可以預料,但有些可能我們就不會預先知道,只有發生了,纔會恍然大悟,有一種『喔,這也會出現!』的感嘆。

原則

在開始應用混沌工程之前,我們必須確保系統是彈性的,也就是當出現了系統錯誤我們的整個系統還能正常工作。如果不能確保,我們就需要先考慮提升整個系統的健壯性了,因爲混沌工程主要是用來發現系統未知的脆弱一面的,如果我們知道應用混沌工程能導致顯而易見的問題,那其實就沒必要應用了。

雖然 chaos 有混亂的意思,但混沌工程並不是製造混亂。相反,我們可以認爲混沌工程是用經驗的方法來定位問題的一門實驗學科。譬如,我們可以思考:『如果我們在系統裏面注入混亂了,這個系統會怎樣?』,或者『我們系統離混亂的邊界還有多遠?』。所以,爲了更好的進行混沌試驗,我們需要有一些原則來進行指導。

假定穩定狀態

在一個複雜系統裏面,我們有特別多的組件,有很多不同的輸入輸出,我們需要有一個通用的方式來區別系統哪些行爲是可以接受的,而哪一些則是不合適的。我們可以認爲當系統處於正常操作時候的狀態就是穩定狀態。

通常我們可以通過自己測試,來確定一個系統的穩定狀態,但這個方法當然是比較低效的,另一種更常用的做法就是收集 metric 信息,不光需要系統的 metric,也需要服務自身的 metric,但收集 metric 需要注意實時性的問題,你如果收集一個每月彙總的 metric 信息,其實沒啥用,畢竟系統是實時變化的。現在市面上面有很多不錯的開源 metric 系統,譬如我們就在用的 Prometheus。

當我們能收集到信息之後,就需要用這些信息去描述一個穩定狀態。這個難度比較大,因爲不同的業務是不一樣的,即使是同一個業務,不同時間也可能變化很大。但也有一些方法,譬如我們可以根據前面一段時間譬如上週的 metric 的曲線得到一個大概合理的穩定狀態,也可以自己做很多壓力測試,得到相關的數據。

當有了 metric 以及知道穩定狀態對應的 metric 是怎樣之後,我們就可以通過這些來考慮混沌實驗了。思考當我們注入不同的事件到系統中的時候,穩定狀態會如何變化,然後我們就會開始做實驗來驗證這個假設。

變更真實世界事件

在真實的世界中,我們可能遇到各種各樣的問題,譬如:

  • 硬件故障

  • 網絡延遲和隔離

  • 資源耗盡

  • 拜占庭錯誤

  • 下游依賴故障

做混沌試驗的時候需要模擬這些故障,來看系統的狀態。但從成本上面考慮,我們並不需要模擬所有的故障,僅僅需要考慮那些會比較頻繁發生,而且模擬之後會很有效果的。在 TiDB 裏面,我們主要就是模擬的網絡,文件系統的故障,但現在看起來還是不夠,後面會逐漸的添加更多。

在生產中進行試驗

要看混沌試驗有沒有效果,在真實生產環境中進行驗證是最好的方法。但我相信大部分的廠商還沒這麼大的魄力,這方面 Netflix 就做的很猛,他們竟然能夠直接停掉 Amazon 上面的一個 Zone。

如果不能再生產環境中試驗,一個可選的方法就是做 shadow,也就是通常的錄製生產環境的流量,然後在測試中重放。或者模擬生產環境,自己造數據測試。

自動化持續執行

最開始執行混沌試驗,我們可能就是人工進行,試驗進行的過程中,看 metric,試驗結束之後,通過收集的 metric 在對比,看系統的狀態。這個過程後面完全可以做成自動化的,也就是定期執行,或者系統發佈的時候執行等。

如果能做到自動化執行試驗,已經很不錯了,但我們可以做的更多,甚至有可能根據系統的狀態自動化的生成相關的試驗,這個 Netflix 已經做了很多研究,但我們這邊還處於初級階段,沒考慮過自動化生成的問題。

最小化影響範圍

在進行混沌試驗的時候,一定要注意影響的範圍,如果沒預估好,把整個服務搞掛了,導致所有的用戶都沒法使用,這個問題還是很嚴重的。

通常都會使用一種 Canary 的方法,也就是類似 A/B 測試,或者灰度發佈這種的,在 Canary 集羣這邊做很多試驗。也就是說,如果真的搞壞了,那也只是一小部分用戶被搞壞了,損失會小很多。

在 Canary 裏面還有一個好處,因爲我們知道整個系統的穩定狀態,即使不做混沌測試,也可以觀察 Canary 裏面的狀態是不是跟之前的穩定狀態一致的,如果不一致,那也可能有問題。

實踐

上面我們說了相關的原則,那麼如何開始進行一次混沌試驗呢?其實很簡單,只要做到如下步驟就可以:

  1. 選擇一個假設

  2. 選擇試驗的範圍

  3. 明確需要觀察的 metric 指標

  4. 通知相關的團隊

  5. 執行試驗

  6. 分析結果

  7. 增大試驗的範圍

  8. 自動化

譬如對於 TiDB 來說,譬如我們可以選擇驗證網絡隔離對系統的影響,我們會:

  1. 假設一臺機器的網絡隔離對整個系統不會造成影響

  2. 將一個用戶一臺 TiKV 進行網絡隔離

  3. 觀察 QPS,latency,等指標

  4. 通知負責這個用戶的 OPS 同學

  5. 斷網

  6. 一段時間之後分析 metric

  7. 在多個集羣測試

  8. 將這個流程自動化

上面只是一個簡單的例子,實際還會複雜很多,但通過這種方式做了操作了很多次之後,大家都會更加熟悉自己的系統。

混沌成熟度模型

這裏在簡單說說混沌成熟度模型,Netflix 總結了兩個維度,一個是複雜度,一個就是接受度。前者表示的是混沌工程能有多複雜,而後者則表示的是混沌工程被團隊的接受程度。

複雜度分爲幾個階段:

  • 初級

    • 試驗沒有在生產中進行

    • 進程被收工管理

    • 結果只反映系統 metric,沒有業務的

    • 只有簡單的事件進行試驗

  • 簡單

    • 試驗可以在類生產環境中進行

    • 能自動啓動執行,但需要人工監控和終止

    • 結果能反應一些聚合的業務 metric

    • 一些擴展的事件譬如網絡延遲可以進行試驗

    • 結果可以手工彙總和聚合

    • 試驗是預先定義好的

    • 有一些工具能進行歷史對照

  • 複雜

    • 試驗直接在生產環境中進行

    • 啓動,執行,結果分析,終止都是自動完成

    • 試驗框架集成在持續發佈

    • 業務 metrics 會在實驗組和控制組進行比較

    • 一些組合錯誤或者服務級別影響的事件可以進行試驗

    • 結果一直可以追蹤

    • 有工具可以更好的交互式的對比試驗和控制組

  • 高級

    • 試驗在每個開發步驟和任意環境都進行

    • 設計,執行和提前終止這些全部都是自動化的

    • 框架跟 A/B 或者其他試驗系統整合

    • 一個事件譬如更改使用模式和返回值或者狀態變更開始進行試驗

    • 試驗包括動態作用域和影響,可以找到突變點

    • 通過試驗結果能保護資產流失

    • 容量預測可以通過試驗分析提前得出

    • 試驗結果可以區分不同服務的臨界狀態

而接受度也有幾個階段:

  • 在暗處

    • 相關項目不被批准

    • 很少系統被覆蓋

    • 很少或者沒有團隊有意識

    • 早期接受者不定期的進行試驗

  • 有投入

    • 試驗被被官方批准

    • 部分資源被用於實踐

    • 多個團隊有興趣並投入

    • 少部分關鍵服務不定期進行試驗

  • 接受

    • 有專門的 team 進行混沌工程

    • 應急響應被集成到框架,從而可以創建迴歸試驗

    • 多數關鍵系統定期進行混沌試驗

    • 一些試驗驗證會在應急響應或者遊戲時間被臨時執行

  • 文化

    • 所有關鍵服務都有頻繁的混沌試驗

    • 大多數非關鍵服務定期進行

    • 混沌試驗已經是工程師的日常工作

    • 默認所有系統組件都必須參與,如果不想進行,需要有正當的理由

如果按照這上面兩個維度來看,我們其實做的並不好,所以還有很大的提升空間。

總結

上面就是對混沌工程的簡單介紹,後面我會考慮依照混沌工程的原則,開始工程化的實踐。雖然之前我們做過很多工作,如果能用理論開始指導,就能更進一步了。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章