信心的毀滅與重建
在我最開始學習編程的時候,我一直覺得寫程序是很簡單的事情,程序總是按照我的想法串行的執行的,給一個輸入,總是有著符合預期的固定輸出。那時候寫代碼,可能大的挑戰在于理解分支,循環,但無論怎樣,只要控制得當,事情總是確定的。
那段時間可以算是非常快樂的日子,直到我遇到了多線程,人生中第一次有了『自信被打破』的恐慌,在多線程的世界里,事情不會在按照我想的方式來正常的運轉,我需要考慮 data racing,需要考慮 memory ordering。幸運的是,在經歷了短暫的不適應之后,很快我就能很好的擁抱并發了,畢竟我們這個世界本來就是在并行運轉的。雖然寫多線程程序相比之前更加的困難,但其實只要掌握了一些多線程的并發原語,知道如何使用 mutex,semaphore,channel 這些,其實會發現多線程的世界也是蠻有意思的。再加上,新一代的編程語言,無論是 Go,還是 Rust,都能讓大家更加游刃有余的處理并發問題,只要處理得當,給定一個輸入,仍然能得到我們想要的輸出。只不過,這時候要保證確定性要比之前困難了很多。
但好景不長,在駕馭了多線程之后,我的『自信再一次被打破』了,因為我進入了分布式系統的世界,在這個世界里面,一切都變得不在確定。給定一個輸入,我可能得到的結果是未知,因為我不知道這個執行在遠端是否被正常的執行了。而人類對于未知恰恰是最恐慌的。我不知道我的系統什么時候會出現網絡異常,或者磁盤什么時候突然壞掉,或者機房是不是突然斷掉了,一切的一切,對我來說都是未知的,譬如下面是我們在實際中遇到的一個問題:
我們的用戶將 TiDB 運行在國內某云廠商的機器上面,然后跟我們反映,讀延遲會不定期的增長,我們看了看監控,發現唯一的異常指標就是 Cached 的 memory 那段時間會突然下降。當時真的就懵逼了,完全不知道是為啥,最終發現,云廠商的運維監控腳本里面有個 bug,會不定期的將磁盤熱拔插,并且將現有的 page cache 刷到磁盤,所以那段時間 TiDB 的 read 操作很多是從磁盤重新讀取數據的。
可以看到,分布式系統真的是一個非常復雜的系統,故障無處不在,那么我們如何在這么復雜的分布式系統的世界里面生存下去呢?現在,一個很好的答案就是 - Chaos Engineering,中文里面叫做混沌工程。
混沌工程
相比于我們成天擔驚受怕系統會出現什么樣的問題,還不如提前就模擬線上環境可能出現的各種情況,來看我們的系統是否能做到容錯,仍然能繼續對外提供服務。當然,我們并不是簡單的就在線上環境上面,把機器給斷電,或者把網線給拔掉,在混沌工程領域,有一套指導原則,以及標準的實驗步驟,具體的可以參考 PRINCIPLES OF CHAOS ENGINEERING 。
簡單來說,要做一次混沌實驗,我們只需要做到如下的 4 個步驟:
- 定義系統的穩態,這個穩態就是系統在正常運行的時候一些指標,譬如當前請求的 QPS,latency 這些。
- 將系統分為實驗組以及對照組,做出一個假設,譬如我在實驗組引入一個故障,這個穩態仍然能在實驗組保持。
- 執行試驗,給實驗組引入現實世界中的故障,譬如拔掉網卡。
- 驗證第 2 步的假設是否成立,如果實驗組的穩態跟對照組不一樣了,證明我們的系統在第 3 步的故障中不能很好的容錯,所以我們需要改進。
可以看到,上面的步驟非常的簡單,但要在實際從很好的做混沌試驗,還是有一些困難的,主要在以下幾點:
- 自動化,我們需要有一套自動化的系統幫我們進行故障注入,進行假設對比等。
- 盡可能多的引入不同故障。現實環境中可能會出現非常多的故障,僅僅不是拔網線這么簡單,所以引入的故障越多越好。
- 業務方無感知。如果我們每次做混沌試驗,都要業務系統去配合,譬如在業務里面寫一些混沌相關的代碼,讓混沌試驗調用,或者更改系統的部署邏輯,跟混沌試驗配合,這種的就屬于緊耦合的。
你好,ChaosMesh!!!
所以,為了讓大家更好的做混沌試驗,我們開發了 ChaosMesh,ChaosMesh 是一套基于 Kubernetes 的云原生混沌工程平臺。ChaosMesh 的架構如下:
相比于其他混沌平臺,ChaosMesh 有如下優勢:
- 基于 K8s,只要你的系統能跑在 K8s 上面,那么就可以無縫的集成 ChaosMesh,而且不用修改任何業務代碼,真正是被測系統無感知。
- 多種多樣的故障注入。ChaosMesh 能全方位的幫你對網絡,磁盤,文件系統,操作系統等進行故障注入。我們后面也會提供對 K8s,或者云服務自身進行 chaos 的能力。
- 易于使用,你無需關注 ChaosMesh 的底層實現細節,只需用 YAML 配置好混沌試驗,就可以實施,后面所有的實驗是全自動化的。我們也提供了 Dashboard 能讓你在網頁上就輕松的進行試驗。
- 可觀測性,ChaosMesh 的 Dashboard 能很方便的讓你觀測系統,知道什么時候進行了什么試驗,知道你自己的系統當前的運行情況,當然,這里需要一點配置,你需要告訴 ChaosMesh 如何去獲取你系統的穩態指標,譬如你的系統使用 Prometheus,那么就可以告訴 ChaosMesh 如何去 Prometheus 查詢相關的監控指標。
- 強大的開源社區支持,ChaosMesh 的社區成長的非常迅速,我們非常高興的看到大部分的功能已經由社區支持,并且也有很多用戶。你無需擔心遇到問題不知道如何解決,當然,你可能要擔心下 ChaosMesh 做實驗的時候把你的數據給完全干掉,所以做實驗的時候一定要控制好實驗半徑,這個也是混沌工程的一條原則。
來一次 Chaos 實驗?
在我們開始一次 Chaos 實驗之前,你首先需要滿足兩個條件:
- 你自己的業務是跑在 K8s 上面的
- 在 K8s 上面安裝了 ChaosMesh
另外,在開始實驗之前,這里我還是要強調一下 Chaos 實驗的一些注意事項,可能你覺得我這個大叔很啰嗦,但小心駛得萬年船,因為稍微一不注意,你可能就丟了數據了。
- 如果你剛準備將你的系統應用 ChaosMesh,一定要保證首先在測試環境中使用。你的系統應該還非常的脆弱,如果在線上進行試驗,會非常的危險。
- 在生產系統中,一定要控制好試驗的爆炸半徑,控制好影響范圍,譬如我們可以先對某一個街道的用戶進行干擾,然后在擴大到某一個區域,或者某一個城市,如果我們一開始的影響半徑就很大,一個稍微不留意,你的 boss 就可能讓你第二天滾蛋了。
- 做混沌實驗一定不是隨機的瞎做實驗,我們是帶有目的的,是需要規劃好的,與其漫無目的的對系統隨機進行故障注入,我們還不如先問自己一個問題『為了對系統在混亂狀況下的表現更有信心,在哪里做混沌實驗最有價值?』也就是我們要熟悉了解我們的系統,做高杠桿價值的混沌實驗。
好了,現在你已經完全準備好了,現在就可以踏上混沌之旅了,因為 ChaosMesh 的使用是如此簡單,你只需要參考 用戶指南 就能上手使用,所以我就不過多介紹了,譬如下面的演示:
如果你仍然遇到了問題,歡迎給 ChaosMesh 提 issue,相信我,ChaosMesh 社區會很熱情的幫你解決問題的。
總結
隨著 ServiceMesh,Serverless 等理念的興起,我們的系統真的趨向于越來越分布式,這樣雖然簡化了我們單個模塊的實現,但整體來看,也可能會導致我們的系統因為過于分布式而變得復雜,那么如何在這種復雜的環境下仍然讓我們有信心能保證系統能正常穩定運行,混沌工程可以算是一個很不錯的選擇。
現在市面上面,支持混沌工程的平臺已經有很多了,但我這里仍然推薦 ChaosMesh,畢竟使用它能讓你極大提升你對系統的信心。
最后,歡迎來到復雜的分布式系統世界。