如何理解 Site Reliability ?

作為谷廠出品的神書《SRE Google運維解密》, 筆者早有耳聞并斷斷續(xù)續(xù)閱讀過部分內(nèi)容,最近終于靜心品閱了一遍(作為拖延癥患者, 寫完此文與閱讀完原書已間隔約半年),里面的很多理念確實值得細細品味(部分章節(jié)沒有實際操作空間,快讀略過)。
5月底恰逢IT內(nèi)部調(diào)整組織架構(gòu),其中一個開發(fā)運營團隊順手更名為了SRE,不求完美COPY谷歌文化,但求走出符合自己特色的站點可靠工程文化。試運行一段時間后,我想應該會再回頭重溫一下這本書,一定會有不同的理解。
個人理解SRE三個字母,S+R是一塊內(nèi)容,E是另一塊。本文不會講太多關(guān)于E即工程化的內(nèi)容,而重點說說“站點可靠”需要做什么。

先拋個很多人都說好但可能沒思考過為什么的問題:
Gmail到底好在哪里?

這個牛逼的郵件客戶端2004年愚人節(jié)橫空出世,
優(yōu)點很多:界面簡潔,容量超大,免費安全,基于谷歌主業(yè)實現(xiàn)的優(yōu)秀搜索、標簽分類等等功能,
最重要的是順帶激活了之前半死不活的Javascript語言,而今前端工程師如此火爆真的要感謝下谷歌當時的翻牌。
既然本文談的是Reliability, 那大家就可以考慮下,
如何能讓用戶量超過10億+, 免費用戶15G容量上限,如此海量郵件數(shù)據(jù)和系統(tǒng)的高可靠,
結(jié)合下文讀者自己去思考下應該怎么做。

What is SRE

那么,最近大火的SRE到底是個什么崗位? 首先要說SRE概念的流行很大一部分原因是源自Google的最佳實踐,才導致業(yè)界的各種跟風。其實甚至SRE這個名詞的發(fā)明人Ben Treynor 也從來沒有給它公布過一個清晰的定義。
https://landing.google.com/sre/#sre
我先把Google官方 SRE 網(wǎng)頁翻譯部分節(jié)選讓大家有個直觀感覺。

基本上發(fā)生在,當你要求一個軟件工程師設計一個運維功能的時候。(牛人說話需要細細揣摩)
-- Ben Treynor Sloss, founder of Google SRE

當你把運維視作一個軟件問題的時候,SRE就是你所需要的。我們的任務是保護、提供支持和推進藏在所有公有服務背后的軟件和系統(tǒng),永遠警惕關(guān)注它們的可用性、延遲、性能和容量。
我們是一種在業(yè)界任何他處還沒發(fā)現(xiàn)的復合型工種。類似于傳統(tǒng)的運維團隊,我們需要保證重要的、核心盈利的系統(tǒng)運行正常(up and running) ,不管面對龍卷風、帶寬中斷或者配置錯誤。又不同于傳統(tǒng)運維團隊,我們把軟件所為第一生產(chǎn)力工具,以此管理、維護和關(guān)注我們的應用系統(tǒng);為了達到這個目標,我們必須擁有源碼級別的訪問權(quán)限和道德權(quán)威(moral authority), 方可修復、擴展和分布式化代碼使其不僅僅可工作,甚至更加健壯地面對互聯(lián)網(wǎng)的各種異常行為,然后可以開發(fā)我們自己全球規(guī)模(planet-scale)的平臺。作為SRE, 從細粒度的磁盤驅(qū)動器IO調(diào)度,到跨大洲級別的多系統(tǒng)&海量用戶服務能力的宏觀規(guī)劃,我們可以無縫切換。

從官方定義可以提煉出幾個基本關(guān)鍵字:關(guān)注高可用,高可靠,性能,必備系統(tǒng)和軟件開發(fā)能力,全棧能力和優(yōu)秀的學習能力。
寫到這,突然感覺這些也是架構(gòu)師的必備技能呢...
如同敏捷中經(jīng)常提到的擁抱變化,SRE其中一個指導思想叫“擁抱風險”,這樣才能驅(qū)動SRE不斷的創(chuàng)新和快速試錯,因為風險就像BUG永遠消滅不了,基于一個可信的“風險容忍度”指標,SRE可以通過管理風險來提高系統(tǒng)可靠程度。

很多人可能要問了,SRE跟DevOps到底有什么區(qū)別么?別是 Google 自己炒的一個概念吧?其實兩者還是有區(qū)別的,不然筆者也不會真的架設了SRE和DevOps這兩個團隊了。

有篇英文的對比文章, 部分觀點筆者并不贊同,讀者有興趣可以去閱讀一下(https://devops.com/sre-vs-devops-false-distinction/

個人總結(jié)的區(qū)別如下:
DevOps 更多是一種理念,用于幫助IT組織架構(gòu)以敏捷的角度進行調(diào)整和演進的方法論,在開發(fā)和運維團隊中架設起一個健康的合作橋梁。字面其實就可以看出來,很多時候,Dev想要保證盡快的發(fā)布和快速迭代,Ops只想確保線上的穩(wěn)定,否則出問題電話爆掉的是Ops,所以Ops會盡可能的要求放慢節(jié)奏...這也算是DevOps的由來吧。DevOps主要關(guān)注ITIL、ITSM、Agile、持續(xù)交付CD等方面。上方英文作者提到DevOps發(fā)現(xiàn)生產(chǎn)故障只是拋出而不是修復,且偏保守,這個筆者完全不贊同,DevOps必須具備處理生產(chǎn)故障的能力。目前筆者的DevOps團隊偏向于基礎系統(tǒng)(虛擬化、網(wǎng)絡、數(shù)據(jù)庫)、持續(xù)交付工具等的自動化開發(fā)運維。
SRE 的定位相對更加的具體,就是
a) 面向生產(chǎn)環(huán)境進行可靠性需求的自我發(fā)現(xiàn)
b) 應用自動化運維的軟件工程實現(xiàn)
c) 一切影響可靠性的行為通報推進修復
d) 架構(gòu)師視野,參與新項目的線上方案可靠性評估
目前筆者的SRE團隊更偏向于線上應用的全鏈路監(jiān)控、技術(shù)/業(yè)務數(shù)據(jù)收集、運維軟件研發(fā)、自動化排障修復和架構(gòu)設計方案評審等。

【吐槽】最近 DevOps 又開始跟敏捷、精益綁定輸出了很多新概念,且有愈演愈烈之勢。新瓶裝舊酒筆者并不反對,但是在你把邊界界定清楚,職責劃分清楚之前,能不能別在“糊涂”外面再包裝一層“忽悠”?看到此類文章,筆者都免不了吐槽一番...

如何理解站點可靠

先澄清下,“站點可靠”絕對不是問百度搜出一堆網(wǎng)站,不知道哪個是可靠的,導致都不敢點進去。這里的“可靠”指的是系統(tǒng)在特定的時間跨度內(nèi)執(zhí)行系統(tǒng)功能返回期望結(jié)果的可能性,也就是說“可靠”是個可度量值,一般通過下面兩個基本的公式來計算:

失敗平均時間 = 可正確服務的總時長 / 失敗次數(shù)
失敗率 = 失敗次數(shù) / 可正確服務的總時長*

通過公式很容易得知要提高可靠性,只要盡可能的減少失敗次數(shù),縮短失敗時長。但這兩點說起來簡單,做起來卻只能通過不斷實踐和摸索來實現(xiàn)了。
那具體到底應該如何做呢?開發(fā)工程師把應用的穩(wěn)定性、并發(fā)和性能優(yōu)化到極致是不是就是高可靠了呢?這當然可以作為提高可靠性的手段之一,但線上環(huán)境千差萬別,基于某些特定條件的本地優(yōu)化很多時候只可能淪為紙上談兵。下文將羅列一些常見的提高可靠性的一些手段供大家參考(也是目前米么團隊的一些經(jīng)驗之談)。

小貼士:Reliability vs Availability
很多人們會將可靠性和可用性混淆,其實這是兩個完全不同的概念,上文解釋過可靠性和計算公式。而可用性更多是一個衡量可用時間的運維參數(shù),計算公式是:
=正常運行時長 / 總時長(正常運行+故障停機)

分布式監(jiān)控

有人要說了我們要提高系統(tǒng)可靠性,最優(yōu)的方法肯定是“事前”就想到一些隱患并做好預防或補救措施,而不是通過監(jiān)控這種明顯“事后”錯誤去實現(xiàn)。首先要說這種理解是片面的,監(jiān)控也可以做到預警,做到“事前”(事故發(fā)生前),其次并不是所有故障都可以提前就想透的,最后監(jiān)控確實是在軟件系統(tǒng)不夠成熟的情況下,相對容易實施和實現(xiàn)的一種提高可靠性的手段。
只要是搞互聯(lián)網(wǎng)應用,分布式、微服務這些概念就鐵定繞不開,而與它們綁定的監(jiān)控也就更具挑戰(zhàn)性。為什么要監(jiān)控?監(jiān)控什么?怎么監(jiān)控?監(jiān)控目標是什么?

- 監(jiān)控什么?

  • 基礎資源(如虛機/帶寬/磁盤/DB/Redis等)的健康檢查

  • 應用系統(tǒng)的健康檢查,不能僅僅是靜態(tài)頁面,最好有應用正常啟動后才能訪問的ping接口

  • 業(yè)務指標項統(tǒng)計

  • 微服務調(diào)用鏈上的響應時間,異常統(tǒng)計等

  • 安全相關(guān)(如惡意頻繁請求IP)的數(shù)據(jù)統(tǒng)計

  • 業(yè)務/技術(shù)指標的長期趨勢

- 怎么監(jiān)控?

這里說的“怎么”監(jiān)控不是問怎么實現(xiàn),具體方案本來就可能千人千面。這里問的是監(jiān)控的指導思想是什么,怎么去遵照才算比較好的監(jiān)控。
比如健康檢查類的接口或者日志收集的Agent,務必要評估清楚這些額外進程會對核心的應用系統(tǒng)正常運轉(zhuǎn)的影響范圍和影響程度;

  • 所有需要通過埋點實現(xiàn)監(jiān)控的基礎組件要求能異步就堅決不能同步,對埋點應用的性能影響降低到最??;

  • 對實時性要求特別高的指標項(比如接口響應時間,某些核心業(yè)務指標等), 能夠做到準實時到實時的統(tǒng)計告警;對監(jiān)控服務端的數(shù)據(jù)處理和并發(fā)能力提出了特別嚴苛的要求;

  • 監(jiān)控端必須有豐富的UI展示和報表輸出,因為監(jiān)控還有一項重要目的就是可以用于線上排障(What is down & Why it's down),若監(jiān)控信息都清晰的渲染在頁面上,不管是人工排障還是自動化排障(提供API),都是有絕佳益處的;

  • 針對長期/一個時間窗口內(nèi)的數(shù)據(jù)能夠預見大部分指標項的波動指數(shù)和趨勢,并據(jù)此不斷調(diào)整預警的區(qū)間參數(shù),這就可以做到我們說的“事前”發(fā)現(xiàn)可能故障。

  • 如何監(jiān)控我們的監(jiān)控系統(tǒng)保證高可用呢?筆者也不能說目前自己在用的是萬能方案,只能說相對靠譜??梢砸肓硪粋€監(jiān)控系統(tǒng)來做個環(huán)形監(jiān)控,比如CAT做應用監(jiān)控,Zabbix做基礎資源監(jiān)控,它倆完全可以做一個互相之間的監(jiān)控,兩個都掛的可能性應該小很多了吧?

  • 監(jiān)控后的告警數(shù)量一定要保證規(guī)模,過多的告警等于沒有告警,應該做到只要是告警就應該有清晰的處理和修復機制去規(guī)范。

- 監(jiān)控目標?

報告老師,監(jiān)控的目標是“告警”。
答錯,坐下。

監(jiān)控的結(jié)果展現(xiàn)形式之一是“告警”,但絕不是監(jiān)控的目標。目標當然是保證站點高可靠咯!所以我們監(jiān)控了那么多的指標,通過告警這個手段通知到相關(guān)干系人;其他的目標上一章節(jié)也穿插的提到過的“排障定位”,“預警”,“統(tǒng)計報表”。而真正要提高可靠性,關(guān)鍵是拿到監(jiān)控數(shù)據(jù)后的工作:

  • 故障重復出現(xiàn),應該如何推動系統(tǒng)負責人去盡早修復?而不是任由告警發(fā)霉。

  • 預警的基線區(qū)間是基于什么計算出來的?隨著數(shù)據(jù)量的累計,如何不斷更新這些預警值?

  • 監(jiān)控到的一些常見異常如何正反饋到各團隊,更新他們的checklist,確保不重復犯錯;

  • 第一次需要人工介入排障和處理的故障,第二次以及日后類似故障如何通過技術(shù)手段做到自動識別和自動修復?

智能告警

我們已經(jīng)收集了很多監(jiān)控指標數(shù)據(jù)了,告警是水到渠成的事。就告警本身而言是沒有難度,但是如何告,何時告,告的內(nèi)容詳細到什么程度。這些和上面的監(jiān)控描述的基本一致。這里重點提下“智能”的告警。

- 告警規(guī)則的設計

一條通用的告警規(guī)則可以抽象為這么幾個要素:

EffectTime - 規(guī)則生效的時間窗口
Interval - 數(shù)據(jù)統(tǒng)計的時間窗口
Variables - 規(guī)則對應的變量
Expression - 邏輯表達式(與或非)
Level - 告警級別

舉個例子:常規(guī)工作時間(EffectTime=9:00 - 18:00) 1分鐘(Interval=1min)內(nèi)的異常數(shù)量(Variable=ExpCnt)不能超過5個(Expression=ExpCnt < 5),超過就嚴重告警(Level=Critical)
當然示例基本是最簡單的一種告警規(guī)則了,要做好較好的規(guī)則解析,就需要完善的規(guī)則解析器,甚至可以做出一個UI友好的界面,供運維人員以所見即所得的方式拖曳生成一個告警規(guī)則,并自動上線,這個終極目標也是我們目前努力的方向。

很多時候的規(guī)則并不是基于特別具體的變量,而是基于各種時間窗口的對比,比如今天9點的訂單數(shù),昨天9點的訂單數(shù)和前一周9點的訂單平均數(shù)進行比較,才能做出一個告警判斷。當然這些也可以抽象為一個一個的變量,但是對于變量的設計需要更加的細致。

其實Google Borgmon對于告警還有一個時間窗口的概念,叫做“最小持續(xù)時間值”(筆者命名為滑動時間窗口 SlidingTimeWindow, 下文還會提到),用作當警報持續(xù)時間超過這個值的時候才會發(fā)送警報,這樣不會觸發(fā)太多的報警。而實現(xiàn)相同功能的這個值在點評CAT中配置名叫 SuspendTime, 完全是從另一個角度考慮的,也就是當前報警觸發(fā)后,CAT就會暫停/掛起一段時間后,再繼續(xù)匯總這個時間窗口內(nèi)的告警信息進行報警。所以說,你看,同一個事情理解和設計角度不同,卻實現(xiàn)了同樣的功能,怎么理解都很順暢,這就是架構(gòu)設計的美妙之處。

- 批量告警的篩選

一般的監(jiān)控平臺(比如CAT,PinPoint) 后面都會再掛一個告警平臺,用來做告警渠道的對接。這個告警平臺絕對不是簡單的報文拼裝后的報警,它的職能邊界還包括:
在 SlidingTimeWindow 內(nèi)進行各類告警的優(yōu)先級排序,如果量比較大,可以抑制某些低級別的告警,保證嚴重告警不會被淹沒

在 SlidingTimeWindow 內(nèi)的大量告警進行合并和排重,節(jié)約網(wǎng)絡帶寬,更加可以讓報警接收人迅速關(guān)注到明確的信息;

上面兩條篩選都必須基于警告的一些屬性和標簽進行過濾,那么警告的屬性需要盡可能的攜帶一些必要參數(shù),比如應用名,業(yè)務功能模塊等等。

- 告警信息如何描述

這個筆者就不舉例來說了,無非其一是讓報警接收人可以一眼通過標題或簡述大約看懂這是一個什么告警和什么嚴重級別的告警,其二告警的詳細描述盡量攜帶讓人可以盡快定位或找到排障線索信息,并添加一些外鏈可以讓人一鍵跳轉(zhuǎn)到具體的數(shù)據(jù)展示頁面,這樣我覺得就差不多了。

自動排障和修復

自動排障目前筆者團隊已經(jīng)可以將日志、數(shù)據(jù)庫、監(jiān)控數(shù)據(jù)等各類數(shù)據(jù)源融合起來,做出一個匯總的報告,并給出一些初步的故障可能根源和建議修復方案等,人工只要介入一下即可。
而自動修復暫時限定在某些業(yè)務場景,比如通過用戶的手機號在數(shù)倉內(nèi)找到所有的動作軌跡,來確定該用戶的問題是卡在哪一步,然后調(diào)用驗證過的數(shù)據(jù)修復功能模塊自動修復數(shù)據(jù),進而讓用戶繼續(xù)進行下去。
這個話題太大,而且需要大量故障知識庫的總結(jié)才能梳理出根源和方案,否則自動修復再引入一些BUG,那就真的尷尬了。本文不再展開。

發(fā)布協(xié)調(diào)師

Google內(nèi)部是有設置發(fā)布協(xié)調(diào)師這個崗位的(LCE, Launch Coordination Engineering),實際上米么IT雖然沒有明確的架設這個崗位,但由PMO的項目經(jīng)理們兼任了這項職能。比如有個大版本的上線涉及到10多個微服務,服務之間的依賴關(guān)系,上線順序都特別的關(guān)鍵。每逢這種時候都會安排一個大版本上線規(guī)劃會,集合所有服務的負責人,將變更部分的依賴關(guān)系梳理清楚,最終生成一份上線計劃提交給運維團隊。

特別說明:這里說的是“變更部分”的依賴關(guān)系,而不是微服務之間固有的依賴關(guān)系。微服務之間固有的依賴關(guān)系我們確實可以通過調(diào)用鏈分析來做到,而每次上線對于變更部分的功能依賴會遠少于固有關(guān)系依賴,這部分如何能夠做到盡量的智能評估,也是我們在攻關(guān)的一個環(huán)節(jié)。

大家不要小看這個協(xié)調(diào)的事情,并不是所有公司都做的好敏捷,并做到保證各服務接口可以兼容上線的,很多時候發(fā)生一些不兼容的上線依賴,這種協(xié)調(diào)工作是非常有必要且重要的。其實Google賦予了LCE更重要的職能,因為LCE必須對各種系統(tǒng)之間的依賴和可能的隱患相比單個系統(tǒng)負責人有更清晰的認識,意味著LCE可以從業(yè)務架構(gòu)師的角色中挑選人擔任,甚至LCE應該參與各系統(tǒng)的架構(gòu)設計評審,這種專業(yè)意見由了解大部分系統(tǒng)架構(gòu)細節(jié)的人來給出,更加的有說服力。

數(shù)據(jù)完整性

- 備份還是恢復

這其實是個老生常談的問題,就算有些老司機也會在備份這個概念上翻船。大家現(xiàn)在就去看一下自己的系統(tǒng)數(shù)據(jù)是否做好了備份,假設你確認備份好了,是否就可以松一口氣了呢?實際上備份只是第一步,能從備份能恢復出數(shù)據(jù)來才是最終目的。而不少工程師只是做到了備份,等真的要用到這些數(shù)據(jù)做恢復的時候,發(fā)現(xiàn)有損壞或者各種抓瞎,那備份的意義在哪里呢?

- 保障完整性的手段

Google SRE給出了24中數(shù)據(jù)完整性的事故組合, 如下圖,保障手段分三層:第一層是軟刪除,就是我們在數(shù)據(jù)庫表設計中常見的刪除字段,這樣可以保護數(shù)據(jù)不能被意外真的被物理刪除掉;第二層是備份和對應的恢復機制;第三層是復制機制,也就是冗余的概念,將備份再來一次冗余,提高安全性。

知識庫和事后總結(jié)

其實知識庫和事后總結(jié)是所有工程師都應該具備的基本素養(yǎng),但是這點對于SRE的意義更加突出一些,因為很多方案是只能是通過大量的故障記錄、歸類和總結(jié)中得出。目前筆者團隊記錄了大量的故障信息和總結(jié),但是問題就出在故障的記錄和總結(jié)還沒有形成一個統(tǒng)一規(guī)范,導致進行故障合并歸類的時候,出現(xiàn)極大的困難,當然這個是一個逐步演進的過程,是無法直接跨過去的。如果你已經(jīng)具備大量的運維經(jīng)驗,這些抽象提前做好也不是很難的問題。

結(jié) 語

本文借鑒了Google運維解密一書中的部分觀點,并結(jié)合自己團隊的一些實踐和思考,希望把站點可靠文化更加堅實的做下去。現(xiàn)階段筆者也是跟團隊一起在摸索,更多的新思路還希望大家一起加入探討。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容