Netflix混沌工程手册Part 2:混沌工程原则
本文翻譯自Netflix工程師合著的 *Chaos Engineering*一書。這本書介紹了混沌工程的主要概念,以及如何在組織中實(shí)踐這些概念和經(jīng)驗(yàn)。也許我們開發(fā)的相關(guān)工具只適用于Netflix自身的業(yè)務(wù)和系統(tǒng)環(huán)境,但我們相信工具背后的原則可以更廣泛地應(yīng)用于其他領(lǐng)域。
InfoQ 將就這一專題持續(xù)出稿,感興趣的同學(xué)可以持續(xù)關(guān)注。
本文略長(zhǎng),共計(jì)1.3萬字,預(yù)計(jì)閱讀時(shí)間35分鐘。
混沌工程原則
優(yōu)化復(fù)雜系統(tǒng)的性能通常需要在混亂的邊緣進(jìn)行,即系統(tǒng)行為將要變得混亂且無跡可尋之前。
Sydney Dekker,《陷入失敗》
“混亂”一詞讓我們想起隨機(jī)性和無序。然而,這不意味著混沌工程的實(shí)施也是隨機(jī)和隨意的,也不意味著混沌工程師的工作就是引發(fā)混亂。相反,我們把混沌工程視為一種學(xué)科,一種實(shí)驗(yàn)學(xué)科。
在上面的引用中,Dekker觀測(cè)了分布式系統(tǒng)的整體行為,他也主張從整體上了解復(fù)雜系統(tǒng)是如何失效的。我們不應(yīng)該僅僅著眼于發(fā)生故障的組件,而是應(yīng)該嘗試去理解,例如組件交互中的一些偶發(fā)意外行為,最終如何導(dǎo)致系統(tǒng)整體滑向不安全,不穩(wěn)定的狀態(tài)。
你可以將混沌工程視為一種解決“系統(tǒng)離混亂的邊界有多遠(yuǎn)” 的經(jīng)驗(yàn)方法。從另一個(gè)角度去思考,“如果我們把混亂注入到系統(tǒng)里,它會(huì)怎么樣?”
在這一部分,我們會(huì)介紹混沌工程實(shí)驗(yàn)的基本設(shè)計(jì),之后我們會(huì)討論一些更高級(jí)的原則。這些原則建立在真實(shí)實(shí)踐混沌工程的大規(guī)模系統(tǒng)之上。在實(shí)踐混沌工程的過程中,并不是必須遵照所有高級(jí)原則,但我們發(fā)現(xiàn),運(yùn)用的原則越多,你對(duì)系統(tǒng)彈性的信心就越充足。
實(shí)驗(yàn)
在大學(xué)里,電氣工程專業(yè)的學(xué)生必須學(xué)習(xí)一門“信號(hào)和系統(tǒng)”的課程,在這個(gè)課程中他們學(xué)習(xí)如何使用數(shù)學(xué)模型來推理電氣系統(tǒng)的行為。其中一門需要掌握的技術(shù)被稱為拉普拉斯變換。你可以用拉普拉斯變換,將整個(gè)電路的行為用一個(gè)數(shù)學(xué)函數(shù)表達(dá),我們稱之為傳遞函數(shù)。傳遞函數(shù)描述的是系統(tǒng)在受到脈沖時(shí)如何響應(yīng),輸入信號(hào)包含所有可能的輸入頻率的總和。一旦你有了一個(gè)電路的傳遞函數(shù),就可以預(yù)測(cè)它在受到所有可能的輸入信號(hào)時(shí)會(huì)如何響應(yīng)。
軟件系統(tǒng)里并沒有類似的傳遞函數(shù)。像很多復(fù)雜系統(tǒng)一樣,我們無法為軟件系統(tǒng)表現(xiàn)出的各種行為建立一個(gè)預(yù)測(cè)模型。如果我們有這樣一個(gè)模型,可以推導(dǎo)出一次網(wǎng)絡(luò)延遲驟升會(huì)給系統(tǒng)帶來什么影響,那樣就太完美了。但不幸的是,迄今為止我們并沒有發(fā)現(xiàn)這樣一個(gè)模型。
因?yàn)槲覀內(nèi)狈@樣的理論預(yù)測(cè)模型,所以就不得不通過經(jīng)驗(yàn)方法來理解,在各種不同情況下系統(tǒng)會(huì)如何表現(xiàn)。我們通過在系統(tǒng)上運(yùn)行各種各樣的實(shí)驗(yàn),嘗試給系統(tǒng)制造各種麻煩,看它會(huì)發(fā)生什么狀況。
但是,我們肯定不會(huì)給系統(tǒng)隨機(jī)的不同的輸入。我們?cè)谙到y(tǒng)性分析之后,期望可以最大化每個(gè)實(shí)驗(yàn)可以獲得的信息。正如科學(xué)家通過實(shí)驗(yàn)來研究自然現(xiàn)象一樣,我們通過實(shí)驗(yàn)來揭示系統(tǒng)的行為。
FIT 故障注入測(cè)試
分布式系統(tǒng)的經(jīng)驗(yàn)告訴我們,各種系統(tǒng)問題基本都是由預(yù)期外的事件或不良的延遲導(dǎo)致的。2014年初,Netflix開發(fā)了一個(gè)名為FIT的工具,意思是故障注入測(cè)試(Failure Injection Testing)。這個(gè)工具能讓工程師在訪問服務(wù)的一類請(qǐng)求的請(qǐng)求頭中注入一些失敗場(chǎng)景,當(dāng)這些注入了失敗場(chǎng)景的請(qǐng)求在系統(tǒng)中流轉(zhuǎn)時(shí),微服務(wù)中被注入的故障錨點(diǎn)會(huì)根據(jù)不同的失敗場(chǎng)景觸發(fā)相應(yīng)的邏輯。
例如,我們要測(cè)試系統(tǒng)在某個(gè)保存用戶數(shù)據(jù)的微服務(wù)中斷時(shí)的彈性能力。我們預(yù)計(jì)系統(tǒng)中某些服務(wù)不會(huì)如預(yù)期運(yùn)行,但諸如重放等基本功能仍適用于已登錄用戶。使用FIT,我們指定進(jìn)入服務(wù)的所有請(qǐng)求中,有5%會(huì)在請(qǐng)求頭中包含失敗場(chǎng)景。當(dāng)這些請(qǐng)求在系統(tǒng)中傳播時(shí),只要發(fā)到客戶數(shù)據(jù)微服務(wù)的請(qǐng)求都會(huì)自動(dòng)收到故障響應(yīng)。
高級(jí)原則
在開發(fā)混沌工程實(shí)驗(yàn)時(shí),牢記以下原則將有助于實(shí)驗(yàn)設(shè)計(jì)。在接下來的章節(jié)里將會(huì)深入探討以下每個(gè)原則:
- 建立穩(wěn)定狀態(tài)的假設(shè);
- 多樣化現(xiàn)實(shí)世界事件;
- 在生產(chǎn)環(huán)境運(yùn)行實(shí)驗(yàn);
- 持續(xù)自動(dòng)化運(yùn)行實(shí)驗(yàn);
- 最小化“爆炸半徑”。
預(yù)測(cè)和預(yù)防故障
在2017年美洲SRECon大會(huì)上,Preetha Appan介紹了她和她的團(tuán)隊(duì)在 indeed.com 開發(fā)的一個(gè)引入網(wǎng)絡(luò)故障的工具。在演講中,她闡述了預(yù)防故障的切實(shí)需求,而不是僅僅在故障發(fā)生時(shí)做出響應(yīng)。他們的工具Sloth,作為一個(gè)守護(hù)進(jìn)程,運(yùn)行在基礎(chǔ)設(shè)施的每一個(gè)節(jié)點(diǎn)上,包括數(shù)據(jù)庫和索引服務(wù)器。參見 https://www.usenix.org/conference/srecon17americas/program/presentation/appan
3. 建立穩(wěn)定狀態(tài)的假設(shè)
對(duì)于任何復(fù)雜系統(tǒng),都會(huì)有許多可變動(dòng)的部件,有許多形式的輸入輸出。我們需要有一個(gè)通用的方式來區(qū)分系統(tǒng)行為是預(yù)期中的,還是預(yù)期之外的。我們將系統(tǒng)正常運(yùn)行時(shí)的狀態(tài)定義為系統(tǒng)的“穩(wěn)定狀態(tài)”。
如果你在開發(fā)或運(yùn)行一個(gè)軟件服務(wù),你如何清楚地了解它是否在正常工作?你如何認(rèn)定它的穩(wěn)定狀態(tài)?你應(yīng)該從哪里著眼來回答上面的問題?
穩(wěn)定狀態(tài)
在系統(tǒng)思維社區(qū)中使用“穩(wěn)定狀態(tài)”這個(gè)術(shù)語,來指代系統(tǒng)維持在一定范圍內(nèi)或一定模式的屬性,諸如人體維持體溫在一定范圍內(nèi)一樣。我們期望通過一個(gè)模型,基于所期望的業(yè)務(wù)指標(biāo),來描述系統(tǒng)的穩(wěn)定狀態(tài)。這是我們?cè)谧R(shí)別穩(wěn)定狀態(tài)方面的一個(gè)目標(biāo)。要牢記穩(wěn)定狀態(tài)一定要和客戶接受程度一致。在定義穩(wěn)定狀態(tài)時(shí),要把客戶和服務(wù)之間的服務(wù)水平協(xié)議(SLA)納入考量。
如果你的服務(wù)是一個(gè)新服務(wù),想知道它是否正常工作的唯一途徑可能只有自己去運(yùn)行一下。例如服務(wù)可以通過網(wǎng)站訪問,那你可能需要打開網(wǎng)頁并嘗試觸發(fā)一個(gè)任務(wù)或事務(wù)來檢查這個(gè)服務(wù)。
這種快速檢查系統(tǒng)健康的方法顯然并不理想:他是勞動(dòng)密集型的,也就是說我們基本不會(huì)或不常會(huì)做這件事。我們可以自動(dòng)化運(yùn)行類似測(cè)試,但這還不夠。如果這些測(cè)試不能找到系統(tǒng)中的問題,該怎么辦?
更好的方法是先搜集和系統(tǒng)健康有關(guān)的數(shù)據(jù)。如果你在閱讀本書,我們相信你已經(jīng)在使用某種指標(biāo)收集系統(tǒng)來監(jiān)控你的系統(tǒng)。有大量的開源和商業(yè)工具可以采集系統(tǒng)方方面面的數(shù)據(jù):CPU負(fù)載,內(nèi)存使用情況,網(wǎng)絡(luò)I/O,以及各類時(shí)序信息,例如需要多長(zhǎng)時(shí)間響應(yīng)一個(gè)Web請(qǐng)求,或者查詢各種數(shù)據(jù)庫的耗時(shí)。
系統(tǒng)的指標(biāo)有助于幫助我們?cè)\斷性能問題,有時(shí)也能幫助我們發(fā)現(xiàn)功能缺陷。業(yè)務(wù)指標(biāo)與系統(tǒng)指標(biāo)形成對(duì)比,業(yè)務(wù)指標(biāo)通常回答這樣的問題:
- 我們正在流失用戶嗎?
- 用戶目前可以操作網(wǎng)站的關(guān)鍵功能嗎?例如在電子商務(wù)網(wǎng)站里為訂單付款,添加購物車等。
- 目前存在較高的延遲致使用戶不能正常使用我們的服務(wù)嗎?
某些組織有非常明確的,和收入直接相關(guān)的實(shí)時(shí)指標(biāo)。例如像Amazon和eBay會(huì)跟蹤銷售量,Google和Facebook會(huì)跟蹤廣告曝光次數(shù)。
由于Netflix使用的是按月訂閱模式,所以我們沒有這類指標(biāo)。我們也會(huì)測(cè)量注冊(cè)率,這是一個(gè)重要的指標(biāo),但是只看注冊(cè)率不能反映整體系統(tǒng)的健康狀況。
我們真正想要的是一個(gè)可以反映當(dāng)前活躍用戶的滿意狀況的指標(biāo),因?yàn)闈M意的用戶才有可能連續(xù)訂閱。可以這么說,如果當(dāng)前和系統(tǒng)做交互的用戶是滿意的,那么我們基本可以確定系統(tǒng)目前是健康的。
遺憾的是,我們目前還沒找到一個(gè)直接、實(shí)時(shí)的可以反映用戶滿意度的指標(biāo)。我們會(huì)監(jiān)控客服電話的呼叫量,這或許是一個(gè)可以間接反映客戶滿意度的指標(biāo),但是從運(yùn)營角度出發(fā),我們需要更快、更細(xì)粒度的反饋。Netflix有一個(gè)還不錯(cuò)的可以間接反映用戶滿意度的指標(biāo)——播放按鈕的點(diǎn)擊率。我們管這個(gè)指標(biāo)叫做視頻每秒開始播放數(shù),簡(jiǎn)稱為SPS(Starts per sencond)。
SPS很容易測(cè)量,而且因?yàn)橛脩舾顿M(fèi)訂閱服務(wù)的直接目的就是看視頻,所以SPS應(yīng)該和用戶滿意度密切相關(guān)。這個(gè)指標(biāo)在東海岸下午6點(diǎn)會(huì)明顯高于早上6點(diǎn)。我們就可以據(jù)此來定義我們系統(tǒng)的穩(wěn)定狀態(tài)了。
相比某個(gè)服務(wù)的CPU負(fù)載來說,Netflix的可靠性工程師(SREs)更關(guān)注SPS的下降:SPS下降會(huì)立刻向他們發(fā)送警報(bào)。CPU負(fù)載的尖刺有時(shí)重要有時(shí)不重要,而像SPS這樣的業(yè)務(wù)指標(biāo)才是系統(tǒng)邊界的表述。這才是我們要關(guān)注并驗(yàn)證的地方,而不是那些像CPU負(fù)載類的內(nèi)部指標(biāo)。
很多現(xiàn)有的數(shù)據(jù)采集框架默認(rèn)采集大量的系統(tǒng)級(jí)別指標(biāo),所以通常來說,讓系統(tǒng)有能力抓取到業(yè)務(wù)級(jí)別的指標(biāo)比系統(tǒng)級(jí)別更難。然而花精力采集業(yè)務(wù)級(jí)別指標(biāo)是值得的,因?yàn)樗鼈儾攀窍到y(tǒng)健康的真實(shí)反映。
這些指標(biāo)獲取的延遲越低越好:那些在月底算出來的業(yè)務(wù)指標(biāo)和系統(tǒng)今天的健康狀況毫無關(guān)系。
對(duì)于選擇的任何指標(biāo),需要平衡以下幾點(diǎn):
- 指標(biāo)和底層架構(gòu)的關(guān)系;
- 收集相關(guān)數(shù)據(jù)需要的工作量;
- 指標(biāo)和系統(tǒng)后續(xù)行為間的時(shí)間延遲。
如果你還不能直接獲取和業(yè)務(wù)直接相關(guān)的指標(biāo),可以暫時(shí)先利用一些系統(tǒng)指標(biāo),比如系統(tǒng)吞吐率,錯(cuò)誤率,99%以上的延遲等。你選擇的指標(biāo)和業(yè)務(wù)關(guān)系越強(qiáng),得到的可以采取可執(zhí)行策略就越強(qiáng)。你可以把這些指標(biāo)想象成系統(tǒng)的生命特征指標(biāo),像脈搏、呼吸、血壓、體溫等。同樣重要的是,在客戶端驗(yàn)證服務(wù)產(chǎn)生的警報(bào)可以提高整體效率,而且可以作為對(duì)服務(wù)端指標(biāo)的補(bǔ)充,以構(gòu)成某一時(shí)刻用戶體驗(yàn)的完整畫面。
3.1 如何描述穩(wěn)定狀態(tài)
與人體的生命體征一樣,你需要清楚“健康”的數(shù)值范圍。例如我們知道37攝氏度以下是人體的健康溫度。
請(qǐng)牢記目標(biāo):我們期望通過一個(gè)模型,基于所期望的業(yè)務(wù)指標(biāo),來描述系統(tǒng)的穩(wěn)定狀態(tài)。
很多業(yè)務(wù)指標(biāo)并不像我們的體溫那樣穩(wěn)定,他們也許會(huì)經(jīng)常劇烈波動(dòng)。我們?cè)倥e一個(gè)醫(yī)學(xué)中的例子,心電圖測(cè)量心臟附近人體表面的電壓差,這個(gè)信號(hào)是用來觀測(cè)心臟行為的。但心電圖采集的信號(hào)會(huì)隨著心臟跳動(dòng)而變化,因此醫(yī)生不能將這個(gè)信號(hào)與單個(gè)閾值進(jìn)行比較來判斷患者是否健康。醫(yī)生需要比較的是信號(hào)波動(dòng)的模式和患者健康時(shí)的模式是否一致。
在Netflix,SPS也不是一個(gè)和人體體溫一樣的穩(wěn)定指標(biāo),它也隨著時(shí)間波動(dòng)。下圖描繪的就是SPS隨時(shí)間變化的波動(dòng)情況,可以看出,它有一個(gè)穩(wěn)定的模式。這是因?yàn)槿藗兞?xí)慣于在晚餐時(shí)間看電視節(jié)目。因?yàn)镾PS隨時(shí)間的變化可以預(yù)期,所以我們就可以用一周前的SPS波動(dòng)圖作為穩(wěn)定狀態(tài)的模型。Netflix的可靠性工程師們總是將過去一周的波動(dòng)圖放在當(dāng)前的波動(dòng)圖之上,以發(fā)現(xiàn)差異。就像下圖中當(dāng)前的圖線是紅色,上一周的圖線是黑色。
圖1 SPS隨時(shí)間變化你所處的行業(yè)決定了你的指標(biāo)是否以一種可以預(yù)期的方式隨時(shí)間波動(dòng)。例如,如果你負(fù)責(zé)一個(gè)新聞網(wǎng)站,流量的尖刺可能來源于一個(gè)大眾關(guān)注度高的新聞事件。某些事件的尖刺可以預(yù)期,比如選舉、重大賽事,但是其他類型的事件不太可能被預(yù)測(cè)到。在這一類場(chǎng)景中,準(zhǔn)確描述系統(tǒng)的穩(wěn)定狀態(tài)將會(huì)非常復(fù)雜。無論哪種情況,描述穩(wěn)定狀態(tài)都是建立有意義假設(shè)的必要前提。
3.2 建立假設(shè)
每當(dāng)你進(jìn)行混沌工程實(shí)驗(yàn)的時(shí)候,你應(yīng)該首先在心里對(duì)實(shí)驗(yàn)結(jié)果有一個(gè)假設(shè)。將你的系統(tǒng)直接置于各種事件里看看系統(tǒng)會(huì)怎么樣的想法可能比較誘人,然而,沒有一個(gè)預(yù)先的假設(shè),你就不清楚應(yīng)該從數(shù)據(jù)里找什么,最終也難以得出有效結(jié)論。
定義好指標(biāo)并理解其穩(wěn)定狀態(tài)的行為之后,你就可以使用它們來建立實(shí)驗(yàn)的假設(shè)。思考一下當(dāng)你向系統(tǒng)注入不同類型的事件時(shí),穩(wěn)定狀態(tài)行為會(huì)發(fā)生什么變化。例如你向中間層的服務(wù)增加請(qǐng)求數(shù)量,穩(wěn)定狀態(tài)會(huì)被破壞還是保持不變?如果被破壞了,你期待系統(tǒng)如何表現(xiàn)?
在Netflix,我們使用混沌工程來提高系統(tǒng)彈性,因此我們實(shí)驗(yàn)的假設(shè)一般是這樣的形式:向系統(tǒng)注入的事件不會(huì)導(dǎo)致系統(tǒng)穩(wěn)定狀態(tài)發(fā)生明顯的變化。
例如,我們?cè)趶椥詫?shí)驗(yàn)里故意讓一個(gè)非關(guān)鍵服務(wù)中斷,以驗(yàn)證系統(tǒng)是否可以優(yōu)雅降級(jí)。我們可能會(huì)中斷基于用戶瀏覽歷史展示的個(gè)性化影片列表服務(wù),這時(shí)系統(tǒng)應(yīng)該返回默認(rèn)的影片列表。
每當(dāng)我們執(zhí)行非關(guān)鍵服務(wù)中斷實(shí)驗(yàn)時(shí),我們的假設(shè)都是注入的故障不會(huì)對(duì)SPS產(chǎn)生影響。換句話說,我們的假設(shè)是實(shí)驗(yàn)措施不會(huì)使系統(tǒng)行為偏離穩(wěn)定狀態(tài)。
我們還會(huì)定期執(zhí)行演習(xí),例如將一個(gè)AWS區(qū)域的流量全部轉(zhuǎn)移到另外兩個(gè)區(qū)域。目的是驗(yàn)證我們?cè)谶M(jìn)行這類故障恢復(fù)時(shí),SPS不會(huì)偏離穩(wěn)定狀態(tài)。這可以讓我們對(duì)出現(xiàn)一個(gè)區(qū)域中斷性故障時(shí)執(zhí)行故障恢復(fù)充滿信心。
最后,讓我們思考一下,如何衡量穩(wěn)定狀態(tài)行為的變化。即便你已經(jīng)建立了穩(wěn)定狀態(tài)行為模型,你也需要定義清楚,當(dāng)偏離穩(wěn)定狀態(tài)行為發(fā)生時(shí)你要如何測(cè)量這個(gè)偏差。如果你曾調(diào)節(jié)過報(bào)警系統(tǒng)的閾值,就應(yīng)該清楚,定義偏離穩(wěn)定狀態(tài)的偏差是否在合理的范圍是具有挑戰(zhàn)性的。只有定義清楚“正常”的偏差范圍,才可以獲得一套驗(yàn)證假設(shè)的完善的測(cè)試集。
金絲雀分析
在Netflix,我們使用金絲雀發(fā)布:我們首先把新代碼發(fā)布到一個(gè)只接受一小部分生產(chǎn)流量的小型集群,然后進(jìn)行驗(yàn)證以確保新發(fā)布的健康性,最后再進(jìn)行全面發(fā)布。
我們使用名叫自動(dòng)金絲雀分析ACA(Automated Canary Analysis)的內(nèi)部工具,通過穩(wěn)定狀態(tài)的指標(biāo),來驗(yàn)證金絲雀集群是否健康。ACA拿金絲雀集群與一個(gè)大小相同,并運(yùn)行舊代碼的基準(zhǔn)集群,比較一系列系統(tǒng)指標(biāo)。金絲雀集群的得分必須足夠高才能通過金絲雀發(fā)布階段。服務(wù)擁有者還可以向ACA中添加應(yīng)用的自定義指標(biāo)。
通過ACA,工程師可以清晰地觀察描述穩(wěn)定狀態(tài)的重要參數(shù),同時(shí)可以對(duì)基于穩(wěn)定狀態(tài)建立的假設(shè),在不同集群間的表現(xiàn)進(jìn)行比較驗(yàn)證。我們其他的一些混沌工程工具也會(huì)使用ACA提供的服務(wù)來測(cè)試穩(wěn)定狀態(tài)變化的各類假設(shè)。
4. 多樣化現(xiàn)實(shí)世界事件
每個(gè)系統(tǒng),從簡(jiǎn)單到復(fù)雜,只要運(yùn)行時(shí)間足夠長(zhǎng),都會(huì)受到不可預(yù)測(cè)的事件和條件的影響。例如負(fù)載的增加、硬件故障、軟件缺陷、還有非法數(shù)據(jù)(有時(shí)稱為臟數(shù)據(jù))的引入。我們無法窮舉所有可能的事件或條件,但常見的有以下幾類:
- 硬件故障;
- 功能缺陷;
- 狀態(tài)轉(zhuǎn)換異常(例如發(fā)送方和接收方的狀態(tài)不一致);
- 網(wǎng)絡(luò)延遲或隔離;
- 上行或下行輸入的大幅波動(dòng)以及重試風(fēng)暴;
- 資源耗盡;
- 服務(wù)之間的不正常的或者預(yù)料之外的組合調(diào)用;
- 拜占庭故障(例如性能差或有異常的節(jié)點(diǎn)發(fā)出有錯(cuò)誤的響應(yīng)、異常的行為、對(duì)調(diào)用者隨機(jī)返回不同的響應(yīng),等等);
- 資源競(jìng)爭(zhēng)條件;
- 下游依賴故障。
也許最復(fù)雜的情況是上述事件的各類組合導(dǎo)致系統(tǒng)發(fā)生異常行為。
要徹底阻止對(duì)可用性的各種威脅是不可能的,但是我們可以盡可能減輕這些威脅。在決定引入哪些事件時(shí),我們應(yīng)當(dāng)估算這些事件發(fā)生的頻率和影響范圍,然后權(quán)衡引入他們的成本和復(fù)雜度。在Netflix,我們選擇關(guān)閉節(jié)點(diǎn)的一方面原因就是,節(jié)點(diǎn)中斷在現(xiàn)實(shí)中發(fā)生頻率很高,同時(shí)引入關(guān)閉事件的成本和難度很低。對(duì)于區(qū)域故障來說,即使引入的成本高昂且復(fù)雜,我們還是必須要做,因?yàn)閰^(qū)域性故障對(duì)用戶的影響是巨大的,除非有足夠的彈性應(yīng)對(duì)它。
文化因素也是一種成本。例如對(duì)于傳統(tǒng)數(shù)據(jù)中心來說,健壯性、穩(wěn)定性、變更的嚴(yán)格控制,在文化上要優(yōu)先于敏捷性——隨機(jī)關(guān)閉節(jié)點(diǎn)類型的實(shí)驗(yàn)對(duì)傳統(tǒng)數(shù)據(jù)中心文化上是一種挑戰(zhàn)。隨著遷移到云上帶來的硬件職責(zé)外部化,工程部門對(duì)硬件故障越來越習(xí)以為常。這種認(rèn)知實(shí)際上在鼓勵(lì)一種對(duì)待故障可預(yù)期性的態(tài)度,這種態(tài)度可以進(jìn)一步推動(dòng)混沌工程的采用和被支持。雖然硬件故障并不是線上事故的最常見原因,但是它相對(duì)容易理解,同時(shí)也是在組織里引入混沌工程并獲益的一個(gè)較簡(jiǎn)單的途徑。
和硬件故障一樣,一些現(xiàn)實(shí)世界的事件也可以直接注入:例如每臺(tái)機(jī)器的負(fù)責(zé)增加、通信延遲、網(wǎng)絡(luò)分區(qū)、證書失效、時(shí)間偏差、數(shù)據(jù)膨脹等等。除此之外,其他的一些事件的注入可能會(huì)具有技術(shù)或文化的障礙,所以我們需要找尋其他方法來看看它們會(huì)如何影響生產(chǎn)環(huán)境。例如發(fā)布有缺陷的代碼。金絲雀發(fā)布可以阻止許多簡(jiǎn)單和明顯的軟件缺陷被大規(guī)模發(fā)布到生產(chǎn)環(huán)境,但并不能阻擋全部的缺陷被發(fā)布出去。故意發(fā)布有缺陷的代碼風(fēng)險(xiǎn)太大,可能會(huì)造成對(duì)用戶過度的影響(參見最小化“爆炸半徑”一節(jié))。要模擬這類發(fā)布帶來的缺陷問題,一種辦法是對(duì)相應(yīng)的服務(wù)調(diào)用注入異常。
Blockade
戴爾云管理團(tuán)隊(duì)開發(fā)了一個(gè)開源的,基于Docker的,用來測(cè)試分布式應(yīng)用的網(wǎng)絡(luò)故障或隔離的混沌工程工具,名叫Blockade。它通過在Docker的宿主機(jī)網(wǎng)絡(luò)管理中創(chuàng)建各種異常場(chǎng)景,來影響在Docker容器中運(yùn)行的應(yīng)用。這個(gè)工具的一些功能包括:在容器間創(chuàng)建任意分區(qū)、容器數(shù)據(jù)丟包,容器網(wǎng)絡(luò)延遲注入,以及在故障注入時(shí)便捷的系統(tǒng)監(jiān)控能力。
我們了解了通過對(duì)相應(yīng)服務(wù)調(diào)用注入異常,來模擬一次失敗的部署,這是因?yàn)殄e(cuò)誤代碼帶來的影響已經(jīng)被隔離在僅僅是運(yùn)行他們的幾臺(tái)服務(wù)器中。通常來說,故障隔離既可以是物理隔離也可以是邏輯隔離。隔離是容錯(cuò)的必要但不充分條件。要獲得一個(gè)可以接受的結(jié)果,還需要某種形式的冗余或者優(yōu)雅降級(jí)。只要子部件的故障能引發(fā)整個(gè)系統(tǒng)不可用,那么這個(gè)故障就沒有被隔離。故障的影響范圍和隔離范圍被稱為故障的故障域。
提供產(chǎn)品的組織設(shè)定產(chǎn)品可用性的預(yù)期,并負(fù)責(zé)制定SLA ——哪些東西一定不能失敗或者失敗是否具備預(yù)案。發(fā)現(xiàn)和驗(yàn)證故障域以確保滿足產(chǎn)品的可用性預(yù)期是工程師團(tuán)隊(duì)的責(zé)任。
故障域還為混沌工程提供了一個(gè)乘數(shù)效應(yīng)。回到剛才的例子,如果對(duì)服務(wù)調(diào)用失敗的模擬是成功的,那么這不僅可以驗(yàn)證該服務(wù)對(duì)部署缺陷代碼的彈性,同時(shí)也可以驗(yàn)證它在高負(fù)載、錯(cuò)誤配置、其他異常終止等場(chǎng)景引發(fā)失敗時(shí)的彈性。此外,在故障域中你可以向系統(tǒng)注入各類故障來觀察故障的癥狀。例如你在真實(shí)環(huán)境中看到了一些癥狀,你可以逆向找出癥狀的根源故障及其發(fā)生的幾率。在故障域的級(jí)別進(jìn)行實(shí)驗(yàn)還有個(gè)好處是,可以提前對(duì)不可預(yù)見的導(dǎo)致故障的原因做好準(zhǔn)備。
我們不應(yīng)該給系統(tǒng)注入引發(fā)故障的根因事件。每一個(gè)資源都會(huì)形成一個(gè)故障域,這個(gè)故障域包括所有對(duì)它有強(qiáng)依賴的部件(當(dāng)該資源不可用時(shí),所有依賴也都不再可用)。向系統(tǒng)注入故障根因的事件會(huì)暴露出這些因?yàn)橘Y源共享形成的故障域。團(tuán)隊(duì)也經(jīng)常會(huì)為這類資源共享的情況而感到驚訝。
我們不需要窮舉所有可能對(duì)系統(tǒng)造成改變的事件,只需要注入那些頻繁發(fā)生且影響重大的事件,同時(shí)要足夠理解會(huì)被影響的故障域。工程師在設(shè)計(jì)系統(tǒng)架構(gòu)的時(shí)候也許已經(jīng)考慮了故障域。例如在微服務(wù)架構(gòu)中,服務(wù)組是最重要的故障域之一。有時(shí)團(tuán)隊(duì)認(rèn)為他們的服務(wù)不是關(guān)鍵服務(wù),但最后卻在故障時(shí)因?yàn)闆]有做合理的隔離導(dǎo)致整個(gè)系統(tǒng)宕機(jī)。所以,在系統(tǒng)中用實(shí)驗(yàn)驗(yàn)證這些預(yù)先定好的邊界非常關(guān)鍵。
再強(qiáng)調(diào)一次,注入的事件一定是你認(rèn)為系統(tǒng)能處理的。同時(shí),注入的事件應(yīng)該是所有可能的真實(shí)世界的事件,而不僅僅是故障或延遲。我們上面舉的例子更多關(guān)注軟件部分,但真實(shí)世界里人的因素對(duì)系統(tǒng)彈性和可用性也起到了至關(guān)重要的作用。例如對(duì)故障處理中人工控制的流程和工具進(jìn)行實(shí)驗(yàn)或演習(xí)也會(huì)提高可用性。
Netflix的混沌工程的規(guī)范化
在Netflix,混亂猴子和混亂金剛是由一個(gè)集中的團(tuán)隊(duì)進(jìn)行開發(fā),發(fā)布,維護(hù)和制定規(guī)則和執(zhí)行的。而FIT是一個(gè)自助服務(wù)的工具。這也是第一次我們的工具需要微服務(wù)工程師們的時(shí)間和接受才能運(yùn)行。當(dāng)然,他們不得不對(duì)工具發(fā)現(xiàn)的對(duì)彈性的威脅做出回應(yīng)。即便許多團(tuán)隊(duì)在開發(fā)階段確實(shí)嘗試到了FIT的好處,但還是難以廣泛和高頻率的使用。我們?cè)贔IT有這么強(qiáng)大的工具來提高彈性,但是我們卻遇到了普及問題。
Netflix的混沌工程團(tuán)隊(duì)認(rèn)為現(xiàn)在我們分別有了小尺度和大尺度(如關(guān)閉節(jié)點(diǎn)和關(guān)閉整個(gè)區(qū)域)上的實(shí)踐,但我們還缺少中間環(huán)節(jié)的最佳實(shí)踐:持續(xù)提高我們對(duì)微服務(wù)各類故障的彈性。FIT對(duì)這方面的探索提供了一個(gè)基礎(chǔ),但是執(zhí)行這樣一個(gè)實(shí)驗(yàn)的負(fù)擔(dān),使得我們并沒能像混亂猴子和混亂金剛那樣,在工程師團(tuán)隊(duì)中形成一致。
我們重新回過頭從頭到尾仔細(xì)思考了如何將混沌工程作為一個(gè)落地的實(shí)踐。我們走訪了一些工程師,詢問他們混沌工程對(duì)他們意味著什么。多數(shù)的回復(fù)都是混沌工程就是在生產(chǎn)環(huán)境中搞破壞。聽起來很有意思,很多人都在生產(chǎn)環(huán)境中搞破壞,但這些破壞都毫無價(jià)值。我們要想辦法讓混沌工程規(guī)范化。
2015年中,我們發(fā)表了混沌工程原則(Principles of Chaos Engineering),定義了混沌工程作為計(jì)算機(jī)科學(xué)中的一門新的學(xué)科。
通過這個(gè)新的規(guī)范形式,我們?cè)贜etflix正式推動(dòng)了混沌工程。我們?yōu)榛煦绻こ痰慕M成繪制了藍(lán)圖:我們清楚目標(biāo)是什么,而且我們清楚如何評(píng)估做的夠不夠好。原則為我們奠定了基礎(chǔ),讓我們可以把混沌工程提升到新的高度。
5. 在生產(chǎn)環(huán)境運(yùn)行實(shí)驗(yàn)
在我們這個(gè)行業(yè)里,在生產(chǎn)環(huán)境中進(jìn)行軟件驗(yàn)證的想法通常都會(huì)被嘲笑。“我們要在生產(chǎn)環(huán)境中驗(yàn)證”這句話更像是黑色幽默,它被翻譯成“我們?cè)诎l(fā)布之前不打算完善地驗(yàn)證這些代碼”。
經(jīng)典測(cè)試的一個(gè)普遍信條是,尋找軟件缺陷要離生產(chǎn)環(huán)境越遠(yuǎn)越好。例如,在單元測(cè)試中發(fā)現(xiàn)缺陷比在集成測(cè)試中發(fā)現(xiàn)更好。這里的邏輯是,離生產(chǎn)環(huán)境越遠(yuǎn),或者是離發(fā)布越遠(yuǎn)的時(shí)候,發(fā)現(xiàn)的缺陷就越容易被找到根本原因并徹底修復(fù)。如果你曾經(jīng)分別在單元測(cè)試,集成測(cè)試,和生產(chǎn)環(huán)境中debug過問題,上述邏輯的智慧就不言而喻了。
但是在混沌工程領(lǐng)域里,整個(gè)策略卻要反過來了。在離生產(chǎn)環(huán)境的越近的地方進(jìn)行實(shí)驗(yàn)越好。理想的實(shí)踐就是直接在生產(chǎn)環(huán)境中執(zhí)行實(shí)驗(yàn)。
傳統(tǒng)軟件測(cè)試中,我們是在驗(yàn)證代碼的邏輯正確性。是我們對(duì)函數(shù)和方法的行為有很好理解的情況下,寫測(cè)試來驗(yàn)證它們對(duì)不對(duì),換句話說,是驗(yàn)證代碼寫得對(duì)不對(duì)。
而當(dāng)我們執(zhí)行混沌工程實(shí)驗(yàn)時(shí),我們所感興趣的是整個(gè)系統(tǒng)作為一個(gè)整體的行為。代碼只是整個(gè)系統(tǒng)的重要組成部分,而除了代碼之外,整個(gè)系統(tǒng)還有很多其他方面。特別是,狀態(tài)、輸入、以及第三方系統(tǒng)導(dǎo)致的難易預(yù)見的系統(tǒng)行為。
下面我們深入了解一下為什么在生產(chǎn)環(huán)境中執(zhí)行對(duì)混沌工程來說是至關(guān)重要的。我們要建立的是對(duì)系統(tǒng)在生產(chǎn)環(huán)境的信心,我們當(dāng)然就需要在生產(chǎn)環(huán)境中進(jìn)行實(shí)驗(yàn)。否則,我們就僅僅是在其他我們并不太關(guān)心的環(huán)境中建立信心,這會(huì)大大削弱這些實(shí)踐的價(jià)值。
5.1 狀態(tài)和服務(wù)
我們之前簡(jiǎn)要討論過系統(tǒng)的“狀態(tài)”。在這一節(jié)我們仔細(xì)討論一下有狀態(tài)服務(wù)。如果我們不需要在系統(tǒng)中維護(hù)任何狀態(tài),那么軟件工程將會(huì)簡(jiǎn)單很多。然而狀態(tài)卻在我們建造的這類系統(tǒng)中無處不在。
在微服務(wù)架構(gòu)中,當(dāng)我們提到狀態(tài)的時(shí)候,通常我們說的是有狀態(tài)服務(wù),例如數(shù)據(jù)庫服務(wù)。數(shù)據(jù)庫僅僅保存一些測(cè)試設(shè)置開關(guān)的系統(tǒng),與保存所有生產(chǎn)數(shù)據(jù)的系統(tǒng),在行為上是不同的。其他一些有狀態(tài)服務(wù)包括緩存服務(wù),對(duì)象存儲(chǔ)服務(wù),以及可持久化的消息服務(wù)。
配置數(shù)據(jù)是另一種影響系統(tǒng)行為的狀態(tài)。無論使用靜態(tài)配置文件,動(dòng)態(tài)配置服務(wù)(像etcd),還是兩者的組合(像我們?cè)贜etflix一樣),這些配置信息本身也是一種狀態(tài),而且它們可以嚴(yán)重影響系統(tǒng)行為。
即使在無狀態(tài)的服務(wù)中,狀態(tài)仍然以內(nèi)存中的數(shù)據(jù)結(jié)構(gòu)的形式存在于請(qǐng)求之間,并因此影響到后續(xù)請(qǐng)求。
還有無數(shù)的角落里隱藏著許許多多的狀態(tài)。在云服務(wù)中,自動(dòng)伸縮組中虛擬機(jī)或者容器的個(gè)數(shù)也是一個(gè)系統(tǒng)的狀態(tài),這個(gè)狀態(tài)會(huì)隨時(shí)間、隨外部需求或集群變化而不斷改變。網(wǎng)絡(luò)硬件如交換機(jī)和路由器也有狀態(tài)。
總有一些意想不到的狀態(tài)會(huì)傷害到你。如果你是我們的目標(biāo)讀者,你應(yīng)該已經(jīng)踩過一些坑了。要想解決混沌工程關(guān)注的對(duì)于系統(tǒng)彈性的威脅,你需要把生產(chǎn)環(huán)境中存在的各式各樣的狀態(tài)問題暴露給混沌工程實(shí)驗(yàn)。
5.2 生產(chǎn)環(huán)境中的輸入
對(duì)于軟件工程師來說,最難的一課莫過于,系統(tǒng)的用戶永遠(yuǎn)不會(huì)如你預(yù)期的那樣與你的系統(tǒng)進(jìn)行交互。這一課在設(shè)計(jì)系統(tǒng)的UI的時(shí)候尤為典型,在設(shè)計(jì)混沌工程實(shí)驗(yàn)的時(shí)候也需要牢記。
設(shè)想一下,你的系統(tǒng)提供了從用戶接收不同類型請(qǐng)求的服務(wù)。你可以為用戶輸入設(shè)計(jì)一個(gè)組合數(shù)據(jù)模型,但因?yàn)橛脩粲肋h(yuǎn)不會(huì)如你預(yù)期般行動(dòng),生產(chǎn)系統(tǒng)總是會(huì)收到測(cè)試覆蓋之外的輸入數(shù)據(jù)組合。
真正對(duì)系統(tǒng)的建立信心的唯一方法就是在生產(chǎn)環(huán)境中針對(duì)真實(shí)的輸入數(shù)據(jù)驗(yàn)證實(shí)驗(yàn)。
5.3 第三方系統(tǒng)
分布式系統(tǒng)就是,其中有臺(tái)你根本不知道的機(jī)器故障了,有可能會(huì)讓你自己的服務(wù)也故障。
Leslie Lamport
即使可以預(yù)見所有在控制范圍內(nèi)系統(tǒng)的狀態(tài),我們也總是會(huì)依賴于外部系統(tǒng),它們的行為我們不可能全都知道。2012年的平安夜,在Netflix全體員工的記憶上烙上了深深的印記。AWS 一個(gè)區(qū)域的 ELB(Elastic Load Balancing)服務(wù)故障,導(dǎo)致了Netflix全部服務(wù)嚴(yán)重中斷。
如果系統(tǒng)部署在像AWS或Azure這樣的云服務(wù)中,那么存在大量的你所依賴,而又不完全了解的外部服務(wù)是顯而易見的。但即使你的系統(tǒng)全都運(yùn)行在自己的數(shù)據(jù)中心,但在生產(chǎn)環(huán)境中,系統(tǒng)還是會(huì)依賴其他的外部服務(wù),例如DNS,SMTP,NTP,等等。就算這些服務(wù)你都自己部署,他們也經(jīng)常會(huì)需要和外部的不受你控制的服務(wù)進(jìn)行交互。
如果你的服務(wù)提供了一個(gè)Web UI,那么你的用戶所使用的瀏覽器就變成了你系統(tǒng)的一部分,但它不受你控制。即使你對(duì)客戶端擁有全面的控制,例如IoT設(shè)備,你仍然逃不開用戶所連接的網(wǎng)絡(luò)環(huán)境和設(shè)備的影響。
第三方系統(tǒng)的行為在他自己的生產(chǎn)環(huán)境,與他和其他環(huán)境的集成的大環(huán)境中的行為總是有所不同。這進(jìn)一步強(qiáng)調(diào)了你需要在生產(chǎn)環(huán)境運(yùn)行實(shí)驗(yàn)的事實(shí),生產(chǎn)環(huán)境才是你的系統(tǒng)和第三方系統(tǒng)進(jìn)行真實(shí)交互的唯一場(chǎng)所。
面向云服務(wù)的混沌工程工具
只要系統(tǒng)部署在云上,那么混亂就是不可避免的。所幸我們的社區(qū)已經(jīng)注意到并且開發(fā)了一些優(yōu)秀的基于云的混沌工程工具,并且可以和不同的云提供商整合使用。除了混亂猴子之外,值得一提的工具有Chaos Lambda,它可以讓我們?cè)谏a(chǎn)時(shí)間隨機(jī)關(guān)閉AWS的Auto Scaling Group(ASG)實(shí)例。還有Microsoft Azure的Fault Analysis Service,它是專為測(cè)試在Microsoft Azure Service Fabric所構(gòu)建服務(wù)的工具。
5.4 生產(chǎn)環(huán)境變更
在Netflix,我們的系統(tǒng)一直在不斷更新。每天工程師和自動(dòng)腳本都在通過不同的方式更新著系統(tǒng),例如發(fā)布新代碼,更改動(dòng)態(tài)配置,添加持久化的數(shù)據(jù),等等。
如果我們擴(kuò)展我們系統(tǒng)的概念來包括這些生產(chǎn)環(huán)境中的變更,那么很明顯在測(cè)試環(huán)境中想要模擬這些系統(tǒng)行為有多困難。
5.5 外部有效性
當(dāng)心理學(xué)家或教育研究人員等社會(huì)科學(xué)家進(jìn)行實(shí)驗(yàn)時(shí),他們的主要關(guān)注點(diǎn)之一就是“外部有效性”:這個(gè)實(shí)驗(yàn)的結(jié)果能否概括我們真正感興趣的現(xiàn)象?或者測(cè)量結(jié)果的產(chǎn)品運(yùn)行環(huán)境是否是專門為了測(cè)試而準(zhǔn)備的?
如果你不直接在生產(chǎn)環(huán)境中運(yùn)行混沌工程實(shí)驗(yàn),那么本章所討論的問題(狀態(tài)、輸入、第三方系統(tǒng),生產(chǎn)環(huán)境變更)就都是混沌工程實(shí)驗(yàn)的外部有效性的潛在威脅。
5.6 不愿意實(shí)踐混沌工程的借口
我們認(rèn)識(shí)到,在有些環(huán)境中,直接在生產(chǎn)環(huán)境中進(jìn)行實(shí)驗(yàn)可能非常困難甚至不可能。我們并不期待工程師將干擾注入到行駛中的自動(dòng)駕駛汽車的傳感器里。但是,多數(shù)用戶應(yīng)該都不是在操作這類安全悠關(guān)的系統(tǒng)。
5.6.1 我很確定它會(huì)宕機(jī)!
如果你不愿在生產(chǎn)環(huán)境執(zhí)行混沌工程實(shí)驗(yàn)的原因是,你對(duì)系統(tǒng)在你注入事件時(shí)會(huì)如何反應(yīng)缺乏信心,那么這可能是你的系統(tǒng)還不夠成熟來應(yīng)對(duì)混沌工程實(shí)驗(yàn)的信號(hào)。你應(yīng)該在對(duì)系統(tǒng)的彈性具備一定信心的時(shí)候再進(jìn)行混沌工程實(shí)驗(yàn)。混沌工程的一個(gè)主要目的是識(shí)別系統(tǒng)中的薄弱環(huán)節(jié)。如果已經(jīng)看到明顯的薄弱環(huán)節(jié),那你應(yīng)該首先專注于提高系統(tǒng)在這一點(diǎn)上的彈性。當(dāng)你確信系統(tǒng)有足夠的彈性時(shí),就可以開始進(jìn)行混沌工程實(shí)驗(yàn)了。
5.6.2 如果真的宕機(jī)了,麻煩就大了!
即使你對(duì)系統(tǒng)彈性有很大的信心,你也可能會(huì)猶豫不決要不要執(zhí)行混沌工程實(shí)驗(yàn),因?yàn)閾?dān)心如果實(shí)驗(yàn)揭示出系統(tǒng)薄弱環(huán)節(jié)的同時(shí)造成過多的破壞。
這是一個(gè)非常合理的顧慮,這也是我們正在致力解決的問題。我們采用的方法是通過下面兩個(gè)途徑來最小化潛在的影響范圍:
- 支持快速終止實(shí)驗(yàn);
- 最小化實(shí)驗(yàn)造成的“爆炸半徑”。
當(dāng)你執(zhí)行任何混沌工程實(shí)驗(yàn)之前,應(yīng)該先有一個(gè)用來立即終止實(shí)驗(yàn)的“大紅色按鈕”(我們真的有一個(gè)大紅色按鈕,雖然是虛擬的)。更好的方法是自動(dòng)化這個(gè)功能,當(dāng)它監(jiān)測(cè)到對(duì)穩(wěn)定狀態(tài)有潛在危害的時(shí)候立即自動(dòng)終止實(shí)驗(yàn)。
第二個(gè)策略涉及在設(shè)計(jì)實(shí)驗(yàn)時(shí),要考慮到如何既能從實(shí)驗(yàn)中獲得有意義的結(jié)論,同時(shí)兼顧最小化實(shí)驗(yàn)可能造成的潛在危害。這一點(diǎn)在后面的最小化“爆炸半徑”一節(jié)中討論。
5.7 離生產(chǎn)環(huán)境越近越好
即便你不能在生產(chǎn)環(huán)境中執(zhí)行實(shí)驗(yàn),你也要盡可能的在離生產(chǎn)環(huán)境最接近的環(huán)境中運(yùn)行。越接近生產(chǎn)環(huán)境,對(duì)實(shí)驗(yàn)外部有效性的威脅就越少,對(duì)實(shí)驗(yàn)結(jié)果的信心就越足。
不能在生產(chǎn)環(huán)境中做實(shí)驗(yàn)?
在2015年紐約Velocity Conference上,來自Fidelity Investment的Kyle Parrish和David Halsey做了題為“太大而無法測(cè)試:如何破壞一個(gè)在線交易平臺(tái)而不造成金融災(zāi)難”的演講。他們?cè)谝粋€(gè)包括大型機(jī)的金融交易系統(tǒng)上運(yùn)行了混沌工程實(shí)驗(yàn)。用他們的話來說,“我們意識(shí)到,用我們的災(zāi)備環(huán)境,配合生產(chǎn)環(huán)境的前端,就可以用現(xiàn)有的一些部件,再構(gòu)造出一套生產(chǎn)環(huán)境。我們?cè)缴钊?#xff0c;這個(gè)想法就越可行。我們發(fā)現(xiàn)大型機(jī)災(zāi)備系統(tǒng)非常理想,因?yàn)樗c生產(chǎn)環(huán)境保持實(shí)時(shí)同步,包含所有生產(chǎn)環(huán)境的代碼,數(shù)據(jù),處理能力和存儲(chǔ)能力,支持團(tuán)隊(duì)也完全了解它是如何運(yùn)行的。我們也清楚的了解到,可以在這個(gè)系統(tǒng)上執(zhí)行2倍或3倍于實(shí)際生產(chǎn)峰值時(shí)的流量。我們可以再造一套生產(chǎn)環(huán)境!”這是一個(gè)有創(chuàng)造力的繞過制度規(guī)范來模擬生產(chǎn)環(huán)境的實(shí)例。
記住:為了保障系統(tǒng)在未來不會(huì)遭受大規(guī)模中斷事故,冒一點(diǎn)可控的風(fēng)險(xiǎn)是值得的。
6. 持續(xù)自動(dòng)化運(yùn)行實(shí)驗(yàn)
自動(dòng)化是最長(zhǎng)的杠桿。在混沌工程的實(shí)踐中,我們自動(dòng)執(zhí)行實(shí)驗(yàn),自動(dòng)分析實(shí)驗(yàn)結(jié)果,并希望可以自動(dòng)創(chuàng)建新的實(shí)驗(yàn)。
6.1 自動(dòng)執(zhí)行實(shí)驗(yàn)
手動(dòng)執(zhí)行一次性的實(shí)驗(yàn)是非常好的第一步。當(dāng)我們想出尋找故障空間的新方法時(shí),我們經(jīng)常從手動(dòng)的方法開始,小心謹(jǐn)慎地處理每一件事以期建立對(duì)實(shí)驗(yàn)和對(duì)系統(tǒng)的信心。所有當(dāng)事人都聚集在一起,并向CORE(Critical Operations Response Engineering,Netflix的SRE團(tuán)隊(duì)的名稱)發(fā)出一個(gè)警示信息,說明一個(gè)新的實(shí)驗(yàn)即將開始。
用這種較恐懼和極端級(jí)別的態(tài)度有利于:1)正確運(yùn)行實(shí)驗(yàn) 2)確保實(shí)驗(yàn)有最小的“爆炸半徑”。當(dāng)我們成功執(zhí)行了實(shí)驗(yàn)之后,下一步就是自動(dòng)化這個(gè)實(shí)驗(yàn)以讓其持續(xù)運(yùn)行。
如果一個(gè)實(shí)驗(yàn)不是自動(dòng)化的,那他就是作廢了。
當(dāng)今系統(tǒng)的復(fù)雜性意味著我們無法先驗(yàn)的知道,生產(chǎn)環(huán)境的哪些變動(dòng)會(huì)改變混沌工程實(shí)驗(yàn)的結(jié)果。基于這個(gè)原因,我們必須假設(shè)所有變動(dòng)都會(huì)改變實(shí)驗(yàn)結(jié)果。在共享狀態(tài)、緩存、動(dòng)態(tài)配置管理、持續(xù)交付、自動(dòng)伸縮、時(shí)間敏感的代碼等等的作用之下,生產(chǎn)環(huán)境實(shí)際上處在一個(gè)無時(shí)不在變化的狀態(tài)。導(dǎo)致的結(jié)果就是,對(duì)實(shí)驗(yàn)結(jié)果的信心是隨著時(shí)間而衰減的。
理想情況下,實(shí)驗(yàn)應(yīng)該隨著每次變化而執(zhí)行,這有點(diǎn)兒像是混沌金絲雀。當(dāng)發(fā)現(xiàn)新的風(fēng)險(xiǎn)時(shí),操作人員如果相當(dāng)確定根源是即將發(fā)布的新代碼,那他就可以選擇是否應(yīng)該阻止發(fā)布新版本并優(yōu)先修復(fù)缺陷。這種方法可以更深入了解生產(chǎn)中的可用性風(fēng)險(xiǎn)發(fā)生和持續(xù)的時(shí)間。在另一個(gè)極端,每年一次的演習(xí)中的問題調(diào)查難度更高,需要完全從零開始檢查,而且很難確定這個(gè)潛在的問題存在于生產(chǎn)環(huán)境多久了。
如果實(shí)驗(yàn)不是自動(dòng)化的,那么它就不會(huì)被執(zhí)行。
在Netflix,服務(wù)的可用性由該服務(wù)的開發(fā)和維護(hù)團(tuán)隊(duì)全權(quán)負(fù)責(zé)。我們的混沌工程團(tuán)隊(duì)通過培訓(xùn),工具,鼓勵(lì)和壓力來幫助服務(wù)所有者提高服務(wù)的可用性。我們不能也不應(yīng)該讓工程師犧牲開發(fā)速度,專門花時(shí)間來手動(dòng)定期執(zhí)行混沌工程實(shí)驗(yàn)。相反的,我們自己投入精力來開發(fā)混沌工程的工具和平臺(tái),以期不斷降低創(chuàng)建新實(shí)驗(yàn)的門檻,并能夠完全自動(dòng)運(yùn)行這些實(shí)驗(yàn)。
混沌工程自動(dòng)化平臺(tái) Chaos Automation Platform(ChAP)
我們的混沌工程團(tuán)隊(duì)在2015年的大部分時(shí)間里都在以咨詢的形式,在關(guān)鍵微服務(wù)上運(yùn)行混沌工程實(shí)驗(yàn)。這對(duì)于真正掌握FIT的能力和局限非常必要,但是我們也知道這樣手把手的咨詢方式?jīng)]辦法規(guī)模化。我們需要一個(gè)可以在整個(gè)組織規(guī)模化這個(gè)實(shí)踐機(jī)制。
到2016年初,我們有了一個(gè)計(jì)劃將混沌工程的原則引入到微服務(wù)層。我們注意到FIT有一些問題妨礙了自動(dòng)化和廣泛應(yīng)用。其中一部分可以在FIT本身解決,另外一部分則需要較大的工程量,比請(qǐng)求頭修改和FIT提供的代碼故障模擬點(diǎn)注入要復(fù)雜得多。
2016年底我們發(fā)布了混沌工程自動(dòng)化平臺(tái),簡(jiǎn)稱ChAP,旨在解決這些不足之處。
FIT中大多數(shù)問題都是由于缺乏自動(dòng)化導(dǎo)致的。過多的對(duì)人工參與,例如設(shè)置故障場(chǎng)景,觀測(cè)運(yùn)行時(shí)關(guān)鍵指標(biāo)的變化等,這些被證明是大規(guī)模應(yīng)用的障礙。我們傾向于依靠現(xiàn)有的金絲雀分析(參見前面對(duì)金絲雀分析的介紹)來自動(dòng)判斷實(shí)驗(yàn)是否在可接受的范圍內(nèi)執(zhí)行。
隨后我們使用一個(gè)自動(dòng)化模板開始進(jìn)行真正的實(shí)驗(yàn)。在上面討論過的FIT例子里,我們影響了5%的流量,觀察它對(duì)SPS是否有影響。如果我們沒有觀察到任何影響,我們會(huì)將受影響的流量提高到25%。任何影響都有可能被其他和SPS相關(guān)的噪音所掩蓋。像這樣用大量流量做實(shí)驗(yàn)是有風(fēng)險(xiǎn)的,它只能給我們較低的信心我們可以隔離一些小的影響,它也可以防止多個(gè)故障同時(shí)出現(xiàn)。
為了最小化爆炸半徑,ChAP為每個(gè)被實(shí)驗(yàn)的微服務(wù)創(chuàng)建一個(gè)控制節(jié)點(diǎn)和一個(gè)實(shí)驗(yàn)集群。例如我們像上述的實(shí)例中說的,測(cè)試一個(gè)用戶信息的微服務(wù),ChAP會(huì)詢問我們的持續(xù)集成工具Spinnaker關(guān)于這個(gè)集群的信息。ChAP用這個(gè)信息創(chuàng)建這個(gè)服務(wù)的兩個(gè)節(jié)點(diǎn),一個(gè)作為控制節(jié)點(diǎn),另一個(gè)作為實(shí)驗(yàn)節(jié)點(diǎn)。然后它會(huì)分流一小部分流量,并平均分配在控制節(jié)點(diǎn)和實(shí)驗(yàn)節(jié)點(diǎn)上。只有實(shí)驗(yàn)節(jié)點(diǎn)里注入了故障場(chǎng)景。當(dāng)流量在系統(tǒng)中流轉(zhuǎn)時(shí),我們可以實(shí)時(shí)比對(duì)控制節(jié)點(diǎn)和實(shí)驗(yàn)節(jié)點(diǎn)上的成功率和操作問題。
有了自動(dòng)化的實(shí)驗(yàn),我們就有了較高的信心,我們可以通過一對(duì)一比對(duì)控制節(jié)點(diǎn)和實(shí)驗(yàn)節(jié)點(diǎn)來監(jiān)測(cè)到即使是很小的影響。我們只影響了流量中的很小部分,并且已經(jīng)隔離了實(shí)驗(yàn),因此我們就可以并行運(yùn)行大量的實(shí)驗(yàn)了。
在2016年底,我們將ChAP與持續(xù)交付工具Spinnaker集成在一起,這樣微服務(wù)就可以在每次新發(fā)布時(shí)運(yùn)行混沌工程實(shí)驗(yàn)了。這個(gè)新功能有些類似金絲雀,但是在這個(gè)場(chǎng)景下我們需要它不間斷運(yùn)行,不會(huì)立即自動(dòng)優(yōu)雅降級(jí),因?yàn)檫@里我們的目的是要盡可能發(fā)現(xiàn)所有未來潛在的系統(tǒng)問題。服務(wù)所有者基于在他們的微服務(wù)中發(fā)現(xiàn)的薄弱環(huán)節(jié),我們給予了他們防止降級(jí)發(fā)生的機(jī)會(huì)。
6.2 自動(dòng)創(chuàng)建實(shí)驗(yàn)
如果你已經(jīng)可以配置定期自動(dòng)運(yùn)行實(shí)驗(yàn),你就處在一個(gè)非常好的狀態(tài)了。然而,我們認(rèn)為還可以追求一個(gè)更好的自動(dòng)化水平:自動(dòng)設(shè)計(jì)實(shí)驗(yàn)。
設(shè)計(jì)混沌工程實(shí)驗(yàn)的挑戰(zhàn)并非來自于定位導(dǎo)致生產(chǎn)環(huán)境崩潰的原因,這些信息在我們的故障跟蹤中有。我們真正想要做的是找到那些本不應(yīng)該讓系統(tǒng)崩潰的事件的原因,包括那些還從未發(fā)生過的事件,然后持續(xù)不斷的設(shè)計(jì)實(shí)驗(yàn)來驗(yàn)證,保證這些事件永遠(yuǎn)不會(huì)導(dǎo)致系統(tǒng)崩潰。
然而這是非常困難的。導(dǎo)致系統(tǒng)波動(dòng)的原因空間是非常巨大的,我們不可能有足夠的時(shí)間和資源窮舉所有可能導(dǎo)致問題的事件及其組合。
Lineage-Driven Fault Injection (LDFI)
一個(gè)值得關(guān)注的關(guān)于自動(dòng)創(chuàng)建實(shí)驗(yàn)的研究是一項(xiàng)叫做Lineage-Driven Fault Injection (LDFI)的技術(shù),由加州大學(xué)圣克魯茲分校的Peter Alvaro教授開發(fā)。LDFI可以識(shí)別出可能導(dǎo)致分布式系統(tǒng)故障的錯(cuò)誤事件組合。LDFI的工作原理是通過推斷系統(tǒng)正常情況下的行為來判斷需要注入的候選錯(cuò)誤事件。
2015年,Peter Alvaro與Netflix的工程師合作來研究是否可以把LDFI應(yīng)用在我們的系統(tǒng)上。他們成功地在Netflix FIT框架的基礎(chǔ)上開發(fā)了一個(gè)版本的LDFI,并且識(shí)別出了可能導(dǎo)致嚴(yán)重故障的一些錯(cuò)誤事件組合。
有關(guān)如何在Netflix應(yīng)用這項(xiàng)工作的更多信息,請(qǐng)參閱“第七屆ACM云計(jì)算研討會(huì)論文集”(SoCC '16)上發(fā)表的論文“Internet規(guī)模的自動(dòng)化故障測(cè)試研究”http://dx.doi.org/10.1145/2987550.2987555 。
7. 最小化“爆炸半徑”
1986年4月26日,人類歷史上最嚴(yán)重的核事故之一發(fā)生在烏克蘭的切爾諾貝利核電站。具有諷刺意味的是,災(zāi)難是由于一次彈性演習(xí)導(dǎo)致的:一次驗(yàn)證冷卻劑泵冗余電源的演習(xí)。雖然我們大多數(shù)人并不從事像核電廠冷卻系統(tǒng)這樣高危的項(xiàng)目工作,但每一次混沌工程實(shí)驗(yàn)的確具備導(dǎo)致生產(chǎn)環(huán)境崩潰的風(fēng)險(xiǎn)。混沌工程師的一項(xiàng)專業(yè)職責(zé)就是要理解和降低生產(chǎn)風(fēng)險(xiǎn),可以為實(shí)驗(yàn)而具備良好設(shè)計(jì)的系統(tǒng)可以阻止大規(guī)模的生產(chǎn)事故,僅僅影響到少量的用戶。
不幸的是,我們經(jīng)常運(yùn)行本來只會(huì)影響一小部分用戶的測(cè)試,卻由于級(jí)聯(lián)故障無意中影響到了更多的用戶。在這些情況下,我們不得不立即中斷實(shí)驗(yàn)。雖然我們絕不想發(fā)生這種情況,但隨時(shí)遏制和停止實(shí)驗(yàn)的能力是必備的,可以避免造成更大的危機(jī)。我們的實(shí)驗(yàn)通過很多方法來探尋故障會(huì)造成的未知的和不可預(yù)見的影響,所以關(guān)鍵在于如何讓這些薄弱環(huán)節(jié)曝光出來而不會(huì)意外造成更大規(guī)模的故障。我們稱之為最小化“爆炸半徑”。
能帶來最大信心的實(shí)驗(yàn)也是風(fēng)險(xiǎn)最大的,是對(duì)所有生產(chǎn)流量都影響的實(shí)驗(yàn)。而混沌工程實(shí)驗(yàn)應(yīng)該只承受謹(jǐn)慎的,可以衡量的風(fēng)險(xiǎn),并采用漸進(jìn)的方式,每一步都基于前一步的基礎(chǔ)之上。這種遞進(jìn)的方式不斷增加對(duì)系統(tǒng)的信心,而不會(huì)對(duì)用戶造成過多不必要的影響。
最小風(fēng)險(xiǎn)的實(shí)驗(yàn)只作用于很少的用戶之上。為此我們驗(yàn)證客戶端功能時(shí)只向一小部分終端注入故障。這些實(shí)驗(yàn)僅限于影響一小部分用戶或一小部分流程。他們不能代表全部生產(chǎn)流量,但他們是很好的早期指標(biāo)。例如,如果一個(gè)網(wǎng)站無法通過早期實(shí)驗(yàn),就沒必要影響大量其余的真實(shí)用戶。
當(dāng)自動(dòng)化實(shí)驗(yàn)成功之后(或者小量設(shè)備驗(yàn)證沒有涵蓋要測(cè)試的功能時(shí)),下一步就是運(yùn)行小規(guī)模的擴(kuò)散實(shí)驗(yàn)。這種實(shí)驗(yàn)會(huì)影響一小部分百分比的用戶,因?yàn)槲覀冊(cè)试S這些流量都遵循正常的路由規(guī)則,所以最終它們會(huì)在生產(chǎn)服務(wù)器上均勻分布。對(duì)于此類實(shí)驗(yàn),你需要用你定義好的成功指標(biāo)來過濾所有被影響的用戶,以防實(shí)驗(yàn)的影響被生產(chǎn)環(huán)境的噪音掩蓋。小規(guī)模擴(kuò)散實(shí)驗(yàn)的優(yōu)勢(shì)在于它不會(huì)觸動(dòng)到生產(chǎn)環(huán)境的例如斷路器閾值,所以你可以驗(yàn)證每一個(gè)單一請(qǐng)求的超時(shí)和預(yù)案。這可以驗(yàn)證系統(tǒng)對(duì)瞬時(shí)異常的彈性。
下一步是進(jìn)行小規(guī)模的集中實(shí)驗(yàn),通過修改路由策略讓所有實(shí)驗(yàn)覆蓋的用戶流量導(dǎo)向到特定的節(jié)點(diǎn)。這些節(jié)點(diǎn)會(huì)經(jīng)歷高度集中的故障、延遲等測(cè)試。這里我們會(huì)允許斷路器打開,同時(shí)會(huì)暴露隱藏的資源限制。如果我們發(fā)現(xiàn)有無效的預(yù)案或者奇怪的鎖競(jìng)爭(zhēng)等情況導(dǎo)致服務(wù)中斷,那么只有實(shí)驗(yàn)覆蓋的用戶會(huì)受到影響。這個(gè)實(shí)驗(yàn)?zāi)M大規(guī)模生產(chǎn)環(huán)境故障,但同時(shí)可以把負(fù)面影響控制在最小,然而結(jié)果卻能帶來高度的信心。
風(fēng)險(xiǎn)最大但最準(zhǔn)確的實(shí)驗(yàn)是大規(guī)模無自定義路由的實(shí)驗(yàn)。在這個(gè)實(shí)驗(yàn)級(jí)別,實(shí)驗(yàn)結(jié)果應(yīng)該在你的主控控制臺(tái)顯示,同時(shí)因?yàn)閿嗦菲骱凸蚕碣Y源的限制,實(shí)驗(yàn)可能會(huì)影響到不在實(shí)驗(yàn)覆蓋范圍內(nèi)的用戶。當(dāng)然,沒有什么比讓所有生產(chǎn)用戶都參與實(shí)驗(yàn),能給你更多關(guān)于系統(tǒng)可以抵御特定故障場(chǎng)景的確定性了。
除了不斷擴(kuò)大實(shí)驗(yàn)范圍,在實(shí)驗(yàn)造成過多危害時(shí)及時(shí)終止實(shí)驗(yàn)也是必不可少的。有些系統(tǒng)設(shè)計(jì)會(huì)使用降級(jí)模式來給用戶帶來稍小的影響,這還好,但是當(dāng)系統(tǒng)完全中斷服務(wù)的時(shí)候,就應(yīng)該立即終止實(shí)驗(yàn)。這可以由之前討論過的“大紅色按鈕”來處理。
我們強(qiáng)烈建議實(shí)施自動(dòng)終止實(shí)驗(yàn),尤其是在定期自動(dòng)執(zhí)行實(shí)驗(yàn)的情況下。關(guān)于弄清楚如何構(gòu)建一個(gè)可以實(shí)時(shí)監(jiān)控到我們感興趣的指標(biāo)的系統(tǒng),并可以隨時(shí)實(shí)施混沌工程實(shí)驗(yàn),這完全依賴于你手上的獨(dú)特的系統(tǒng)構(gòu)造,我們留給讀者當(dāng)做一個(gè)課后練習(xí)。
為了讓盡可能高效地應(yīng)對(duì)實(shí)驗(yàn)發(fā)生不可預(yù)期的情況,我們要避免在高風(fēng)險(xiǎn)的時(shí)間段運(yùn)行實(shí)驗(yàn)。例如我們只在所有人都在辦公室工作的時(shí)間段運(yùn)行實(shí)驗(yàn)。
如果實(shí)驗(yàn)的工具和儀器本身就會(huì)對(duì)系統(tǒng)和指標(biāo)產(chǎn)生影響,那么整個(gè)混沌工程的目的就被破壞了。我們要的是建立對(duì)系統(tǒng)彈性的信心,記住每次只檢驗(yàn)一個(gè)可控的故障。
譯者簡(jiǎn)介
侯杰,TGO 鯤鵬會(huì)會(huì)員,美利金融技術(shù)副總裁,整體負(fù)責(zé)美利金融技術(shù)研發(fā)工作。曾在愛點(diǎn)擊,IBM 中國,IBM 澳大利亞擔(dān)任研發(fā)管理,咨詢管理等職位,帶領(lǐng)團(tuán)隊(duì)負(fù)責(zé)過多個(gè)大規(guī)模金融行業(yè)信息化項(xiàng)目,和互聯(lián)網(wǎng)轉(zhuǎn)型實(shí)踐。畢業(yè)于南京大學(xué)。
下期預(yù)告
接下來我們會(huì)討論實(shí)踐中的混沌工程以及混沌工程的成熟度模型。
相關(guān)閱讀
Netflix 混沌工程手冊(cè) Part 1:混沌工程簡(jiǎn)介
總結(jié)
以上是生活随笔為你收集整理的Netflix混沌工程手册Part 2:混沌工程原则的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Solidity】1.一个Solidi
- 下一篇: 聚焦一切关联需求-企业数字化转型:外部驱