如何理解 Site Reliability ?

  • 2019 年 11 月 5 日
  • 筆記

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

先拋個很多人都說好但可能沒思考過為什麼的問題:  Gmail到底好在哪裡?    這個牛逼的郵件客戶端2004年愚人節橫空出世,  優點很多:介面簡潔,容量超大,免費安全,基於Google主業實現的優秀搜索、標籤分類等等功能,  最重要的是順帶激活了之前半死不活的Javascript語言,而今前端工程師如此火爆真的要感謝下Google當時的翻牌。  既然本文談的是Reliability, 那大家就可以考慮下,  如何能讓用戶量超過10億+, 免費用戶15G容量上限,如此海量郵件數據和系統的高可靠,  結合下文讀者自己去思考下應該怎麼做。

What is SRE

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

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

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

從官方定義可以提煉出幾個基本關鍵字:關注高可用,高可靠,性能,必備系統和軟體開發能力,全棧能力和優秀的學習能力寫到這,突然感覺這些也是架構師的必備技能呢… 如同敏捷中經常提到的擁抱變化,SRE其中一個指導思想叫「擁抱風險」,這樣才能驅動SRE不斷的創新和快速試錯,因為風險就像BUG永遠消滅不了,基於一個可信的「風險容忍度」指標,SRE可以通過管理風險來提高系統可靠程度。

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

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

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

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

如何理解站點可靠

先澄清下,「站點可靠」絕對不是問百度搜出一堆網站,不知道哪個是可靠的,導致都不敢點進去。這裡的「可靠」指的是系統在特定的時間跨度內執行系統功能返回期望結果的可能性,也就是說「可靠」是個可度量值,一般通過下面兩個基本的公式來計算:

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

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

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

分散式監控

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

– 監控什麼?

  • 基礎資源(如虛機/頻寬/磁碟/DB/Redis等)的健康檢查
  • 應用系統的健康檢查,不能僅僅是靜態頁面,最好有應用正常啟動後才能訪問的ping介面
  • 業務指標項統計
  • 微服務調用鏈上的響應時間,異常統計等
  • 安全相關(如惡意頻繁請求IP)的數據統計
  • 業務/技術指標的長期趨勢

– 怎麼監控?

這裡說的「怎麼」監控不是問怎麼實現,具體方案本來就可能千人千面。這裡問的是監控的指導思想是什麼,怎麼去遵照才算比較好的監控。 比如健康檢查類的介面或者日誌收集的Agent,務必要評估清楚這些額外進程會對核心的應用系統正常運轉的影響範圍和影響程度;

  • 所有需要通過埋點實現監控的基礎組件要求能非同步就堅決不能同步,對埋點應用的性能影響降低到最小;
  • 對實時性要求特別高的指標項(比如介面響應時間,某些核心業務指標等), 能夠做到准實時到實時的統計告警;對監控服務端的數據處理和並發能力提出了特別嚴苛的要求;
  • 監控端必須有豐富的UI展示和報表輸出,因為監控還有一項重要目的就是可以用於線上排障(What is down & Why it's down),若監控資訊都清晰的渲染在頁面上,不管是人工排障還是自動化排障(提供API),都是有絕佳益處的;
  • 針對長期/一個時間窗口內的數據能夠預見大部分指標項的波動指數和趨勢,並據此不斷調整預警的區間參數,這就可以做到我們說的「事前」發現可能故障。
  • 如何監控我們的監控系統保證高可用呢?筆者也不能說目前自己在用的是萬能方案,只能說相對靠譜。可以引入另一個監控系統來做個環形監控,比如CAT做應用監控,Zabbix做基礎資源監控,它倆完全可以做一個互相之間的監控,兩個都掛的可能性應該小很多了吧?
  • 監控後的告警數量一定要保證規模,過多的告警等於沒有告警,應該做到只要是告警就應該有清晰的處理和修復機制去規範。

– 監控目標?

報告老師,監控的目標是「告警」。 答錯,坐下。

監控的結果展現形式之一是「告警」,但絕不是監控的目標。目標當然是保證站點高可靠咯!所以我們監控了那麼多的指標,通過告警這個手段通知到相關干係人;其他的目標上一章節也穿插的提到過的「排障定位」,「預警」,「統計報表」。而真正要提高可靠性,關鍵是拿到監控數據後的工作:

  • 故障重複出現,應該如何推動系統負責人去儘早修復?而不是任由告警發霉。
  • 預警的基準線區間是基於什麼計算出來的?隨著數據量的累計,如何不斷更新這些預警值?
  • 監控到的一些常見異常如何正回饋到各團隊,更新他們的checklist,確保不重複犯錯;
  • 第一次需要人工介入排障和處理的故障,第二次以及日後類似故障如何通過技術手段做到自動識別和自動修復?

智慧告警

我們已經收集了很多監控指標數據了,告警是水到渠成的事。就告警本身而言是沒有難度,但是如何告,何時告,告的內容詳細到什麼程度。這些和上面的監控描述的基本一致。這裡重點提下「智慧」的告警。

– 告警規則的設計

一條通用的告警規則可以抽象為這麼幾個要素:

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

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

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

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

– 批量告警的篩選

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

在 SlidingTimeWindow 內的大量告警進行合併和排重,節約網路頻寬,更加可以讓報警接收人迅速關注到明確的資訊;

上面兩條篩選都必須基於警告的一些屬性和標籤進行過濾,那麼警告的屬性需要儘可能的攜帶一些必要參數,比如應用名,業務功能模組等等。

– 告警資訊如何描述

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

自動排障和修復

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

發布協調師

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

特別說明:這裡說的是「變更部分」的依賴關係,而不是微服務之間固有的依賴關係。微服務之間固有的依賴關係我們確實可以通過調用鏈分析來做到,而每次上線對於變更部分的功能依賴會遠少於固有關係依賴,這部分如何能夠做到盡量的智慧評估,也是我們在攻關的一個環節。

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

數據完整性

– 備份還是恢復

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

– 保障完整性的手段

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

知識庫和事後總結

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

結 語

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