作者:趙鈺瑩

本文轉載於 InfoQ。

原文鏈接:infoq.cn/article/EEKM94

作為混沌工程的重要推動者,Netflix 在混沌工程手冊(infoq.cn/article/AsN34J)中談到,在生產環境進行軟體驗證的想法通常會被嘲笑。過去,這句話基本都被翻譯為「我們在發布之前不打算完善地驗證這些代碼」。在經典的測試鏈路中,尋找軟體缺陷的普遍信條是離生產環境越遠越好。例如,在單元測試中發現缺陷要比在集成測試中發現更好,這裡的邏輯是:離生產環境越遠,或者是離發布越遠的時候,發現的缺陷就越容易被找到根本原因並徹底修復。

對於混沌工程而言,整個鏈路剛好反過來:在離生產環境越近的地方進行實驗越好,理想的實踐就是直接在生產環境中執行。對於軟體工程師來說,最難的莫過於,系統用戶永遠不會如預期那樣與系統進行交互,混沌工程是解決這一問題的理想方法,可以讓開發者瞭解除代碼之外,整個系統其他方面的情況,特別是狀態、輸入、以及第三方系統導致的難以預見的行為。

據瞭解,在 TiDB 的研發初期,PingCAP 就引入了混沌工程,以此保證 TiDB 在各種極端情況下的穩定性。在 ArchSummit 全球架構師峯會(深圳站)2019 大會期間,InfoQ 就混沌工程理念及實踐這一話題採訪了 PingCAP 首席架構師 @唐劉 ,以此瞭解 PingCAP 的實踐歷程。

唐劉,PingCAP 首席架構師,主要負責分散式 Key-Value 資料庫 TiKV 的研發工作,也會折騰下 TiDB 整個產品的測試,工具開發等工作。

混沌工程與分散式系統

理解是實踐的前提之一,唐劉在採訪中坦言,混沌工程這個名字比較容易讓人困惑,包括其英文「Chaos Engineering」,初次聽到這個單詞時確實不太好理解。唐劉表示:「最開始,我就是把它當成一種注入測試的方法,後來才發現這其實是一門工程學科,通過實驗的方式發現問題並解決問題。」

其實,混沌工程的理念很早之前就存在,唐劉表示,過去使用的錯誤注入就可以理解為混沌工程的一種表現方式,只不過 Netflix 將其提煉出來變成了通用準則,只要照著相關方法就能實施混沌工程,而這一技術誕生之際就與分散式系統密切相關,在《Chaos Engineering》一書中是這樣表述的:

混沌工程是在分散式系統上進行實驗的學科 , 目的是建立對系統抵禦生產環境中失控條件的能力以及信心 。

註:分散式系統就是,其中有臺你根本不知道的機器故障了,有可能會讓你自己的服務也故障。——Leslie Lamport

即使可預見所有在控制範圍內系統的狀態,也總是會出現意外情況,比如系統依靠的某些外部服務突發宕機,這在系統搬遷上雲後尤為明顯,雲服務也並不總是穩定可靠的。採訪中,唐劉解釋道,混沌工程主要是解決常規測試不能覆蓋的問題。對於分散式系統來說,因為其異常的複雜性,加上錯誤可能在任何時候、任何地點發生,眾多常規測試方法並不能保證系統正確。

當然,在某些場景下,直接在生產環境中進行實踐是非常困難且不可用的,比如將幹擾直接注入到行駛中的自動駕駛汽車的感測器上,這是比較危險的,但大部分用戶應該都不是在操作這類生死攸關的系統。

相比較而言,唐劉認為混沌工程比較適合對數據安全性要求較高的場景。此外,如果業務對故障容錯有所承諾,也需要通過混沌工程驗證系統是否可以支持容錯。量化到具體指標來看,如果開發人員確定系統會宕機並且清楚宕機之後會造成較大損失,可以通過「支持快速終止實驗」和「最小化實驗造成的『爆炸半徑』」等方式實施混沌工程。

當執行任何混沌工程實驗前,應該先有一個用來立即終止實驗的「紅色按鈕」,更好的方法則是自動化該功能,當其監測到對穩定狀態有潛在危害時立即自動終止實驗。第二個策略涉及在設計實驗時,考慮從實驗中獲得有意義結論的同時,兼顧最小化實驗可能造成的潛在危害。

無論是架構師、開發人員還是測試人員,唐劉都建議關注這一技術,這相當於從另一個視角審視系統,尤其是對開發者而言。唐劉補充道,開發一個優秀的系統並不只是寫代碼就足夠了,測試不應該僅僅依靠測試人員,他一直相信:

優秀的開發者一定是優秀的測試人員。

PingCAP 混沌工程實踐

如上文所言,在開始研發 TiDB 時,PingCAP 就決定引入混沌工程,應該算是國內喫螃蟹的團隊之一。談到當初的引入原因,唐劉表示,起初開發分散式資料庫時,整個團隊很自然就想到需要保證開發的資料庫能夠讓用戶放心使用,這就需要進行各種各樣的測試。當時,Netflix 開發的 Chaos Monkey 已經非常知名,得益於 Netflix 成功的部署經驗,PingCAP 團隊想到利用該工具解決穩定性問題。

回顧整個實踐歷程,唐劉表示大概可以分為三個階段,第一個階段是 2017 年之前,那時並沒有自動化的概念,所有實驗全部需要手動完成,包括申請機器、手動部署等。雖然比較繁瑣,但也在系統上線之前發現了不少問題。

第二個階段是從 2017 年到 2019 年初,PingCAP 基於 K8s 搭建了一套自動化 chaos 框架,叫做 Schrodinger,這套系統極大提升了整體生產力,只需自定義要做的實驗,Schrodinger 就能搞定。

第三個階段則是 2019 年初至今,PingCAP 一直在做 Schrodinger Cloud,Schrodinger 主要是為測試 TiDB,也可用來測試 TiDB 的周邊工具,甚至是合作夥伴的業務。面對這些需求,PingCAP 考慮基於 K8s 做一套更加通用的 Chaos 框架,採用 Operator 的方式,任何 Chaos 在 K8s 裡面都是 CRD,用戶只需要定義好自己的 CRD,Schrodinger 就可以自動完成後續事宜。

在開發混沌工程實驗時,唐劉建議可遵循以下原則,將有助於實驗設計:

  • 建立穩定狀態的假設;
  • 多樣化現實世界事件;
  • 在生產環境運行實驗;
  • 持續自動化運行實驗;
  • 最小化「爆炸半徑」。

具體來說,系統穩態可以通過一些指標,比如延遲和 QPS 數據等來定義,當系統指標在測試完成後,無法快速恢復穩態要求,可以認為這個系統是不穩定的;其次,引進多樣化的現實變數,比如網卡、磁碟故障等;然後,最為重要的是在生產環境中進行驗證,這樣做是存在風險的,因此最好提前與協作部門同步;最後,自動化可以讓整個過程的效率更高,最小化「爆炸半徑」可以避免不必要的損失。

舉例來說,對於一個三副本的系統而言,可以通過隨機殺死 Leader 節點的方式來驗證系統是否可以保持穩態。可預想的情況是系統在主節點被殺死後會出現一段抖動,隨後恢復正常則證明系統是具備容錯能力的,反之,則證明系統存在問題。

在這之中,主要有兩個大方向:一是發現錯誤;二是注入錯誤。TiDB 主要通過 Metrics(Prometheus 項目)、Log 和 Tracing 三種方式分析系統狀態。其中,TiDB 默認不開啟 Tracing 方式,因為這會對性能產生一定影響,僅在必要時啟動該方法。至於注入錯誤,應用、存儲、網路、CPU 等存在多種故障方式,唐劉在分享中提到了如下部分,供開發者參考:

根據過往實踐經驗,唐劉建議希望使用混沌工程的開發者可以參考混沌工程主頁(principlesofchaos.org/) 列出的步驟和原則。但是,要想真正實踐,還需要做很多工作,包括更好地對系統進行錯誤注入,更好地發現系統問題,這些其實業界沒有通用的解決方案,因此實踐起來還是比較麻煩的。採訪中,唐劉推薦可以閱讀 Netflix 的《Chaos Engineering》一書(中文翻譯版:infoq.cn/theme/13),GitHub 上有一個 awesome-chaos-engineering的 Repo(github.com/dastergon/aw)也可以參考。此外,如果整個開發團隊本來對測試就不太重視,認為這完全是測試團隊的事情,那可能也很難推動混沌工程落地。

結束語

三年前,我很少聽到有人談論混沌工程,現在已經蠻多了。

採訪最後, @唐劉 表示如今的混沌工程在國內已經比較出名,這個概念應該已經進入普及階段。但據唐劉的瞭解,國內真正對其應用很好的,並沒有特別多公司,大部分仍然處於理清概念,但不知道如何實施的階段。在這種背景下,企業可能最需要關注的是如何建立起自己的一整套自動化測試平臺,實現對系統的自動錯誤注入,並自動發現系統問題。在此基礎上,企業可以根據業務情況考慮深入實踐混沌工程。


推薦閱讀:
相關文章