Uber:大規模系統下如何構建可伸縮的告警生態系統

Uber的軟件架構包含上千個微服務,它們能夠讓團隊快速迭代並支撐公司的全球化增長。這些微服務支撐着各種解決方案,比如移動應用、內部與基礎設施服務、產品等,它們有着非常複雜的配置,這些配置會在城市和子城市級別對產品的行爲產生影響。

爲了維持我們的增長和架構,Uber的可觀察性(Observability)團隊構建了一個健壯的、可伸縮的指標和告警管道,當服務出現問題時,它負責探測、緩解和通知相關的工程師。具體來講,我們構建了兩個數據中心內的告警系統,稱爲uMonitor和Neris,它們會流入相同的通知和告警管道。uMonitor是我們基於度量指標的告警系統,它會基於度量數據庫M3運行檢查,而Neris主要查找主機級別的告警。

Neris和uMonitor利用一個公共管道發送通知和去重。我們將深入研究這些系統,並討論採取更多的緩解行動、名爲Origami的新告警去重平臺以及在創建高信噪比告警等方面所面臨的挑戰。

除此之外,我們還開發了一個黑盒告警系統,當我們的內部系統出現故障或數據中心完全不可用時,該系統可以從數據中心外部檢測出高級別的中斷。以後的博客文章將討論這種設置。

Uber的告警

圖1:在我們的告警架構中,服務會發送度量指標到M3。uMonitor會檢查M3,獲取基於度量指標的告警。主機的檢查會發送到Neris上,用於聚合和告警。在Uber外部,會採用黑盒的方式測試API基礎設施。

在Uber這種規模的公司中,監控和告警不能按照傳統的現成解決方案進行思考。Uber的告警系統是從Nagios開始的,使用源控制腳本對carbon指標進行Graphite閾值檢查。由於Carbon metrics集羣的可伸縮性問題,我們決定構建自己的大規模度量平臺M3。爲了提高告警系統的可用性,我們開發了uMonitor,這是我們自行開發的基於時間序列的度量指標告警系統,它所針對的是存儲在M3中的度量數據。對於沒有存儲在M3中的度量指標,我們構建了Neris來執行主機級別的告警檢查。

uMonitor在構建時考慮到了靈活性和使用場景的多樣性。有些告警信息是基於標準的度量指標自動生成的,比如端點錯誤和CPU/內存消耗。其他的告警由度量指標相關的各個團隊來創建。我們將uMonitor構建成一個平臺,滿足各種不同的使用場景,具體來說:

  • 簡單的告警管理:對於每個告警,迭代確定適合的函數和閾值;
  • 靈活的操作:各種通知機制,比如網絡短信(paging)、Email和聊天工具。支持自動緩解,比如回滾到上次部署以及配置修改;
  • 處理高基數:能夠針對最小範圍內的嚴重問題發出告警,但是不會在出現更大範圍故障時,對團隊成員形成通知風暴。

使用uMonitor實現基於度量指標的告警

uMonitor有三個獨立的組件:一個存儲服務,它具有告警管理的API,幷包裝了我們的Cassandra告警和狀態存儲;一個調度器,跟蹤所有的告警,針對每個告警要求,每隔一分鐘分發告警檢查任務給worker;worker,針對每個告警所定義的底層度量指標,執行告警檢查。

worker會在Cassandra存儲中維護告警檢查的狀態,並通過一個主動重試機制確保通知至少能夠成功發送一次。worker會間隔一定的時間(通常是一個小時)對持續出現的告警重新發出警報。目前,uMonitor擁有12.5萬個告警配置,每秒檢查7億個數據點,超過140萬個時間序列。

圖2:度量指標由服務發送給M3,uMonitor的檢查由worker基於調度器來執行,如果違反了閾值的話,將會發送通知。

告警的定義包含一個M3查詢( Graphite或M3QL)和閾值,用來判斷告警是否違反了閾值。查詢將會返回一個或多個時序,閾值將會應用到每個底層的時序上。如果查詢違反了閾值的話,就會發送警報。Cassandra會存儲告警的狀態,在它的幫助下,worker會維護一個狀態機,確保通知至少能夠成功發送一次,如果告警持續觸發的話,它會定期重新發送通知,如果問題得到了緩解,告警將會變更爲已解決的狀態。

閾值有兩種類型:靜態閾值和異常閾值。對於具有特定穩定狀態的指標,或者是可以通過構建查詢返回一致值(藉助一定的值計算,比如成功/失敗的百分比)的指標,我們通常會使用靜態閾值。對於週期性的指標,如每個城市的出行次數和其他業務指標,uMonitor會利用我們的異常檢測平臺Argos基於歷史數據生成動態閾值,這個動態閾值代表了異常的度量指標值。

使用Neris進行主機告警

Neris是我們內部基於主機的告警系統,它針對的是高密度、高基數的主機度量指標,在M3中,這是並未實現的。主機度量指標並未存放到M3中有兩個主要原因。首先,在每個數據中心的40000臺主機上檢查每分鐘生成的150萬個主機度量指標要比查詢中心化的度量指標存儲更高效。在前者的方案中,攝取和存儲度量指標的開銷就能避免了。其次,直到最近,M3的數據保留策略會導致每10秒鐘的指標要存儲48個小時,每分鐘的指標會存儲30天,對於高密度的主機指標來說,這樣的保留策略是沒有必要的。鑑於Nagios需要爲每項檢查編寫代碼,並且需要單獨部署,這樣無法隨着我們的基礎設施增長進行擴展,所以我們決定自行構建一個系統。

Neris會有一個代理(agent),運行在我們數據中心的每個主機上,它會定期(每分鐘)針對主機本身執行告警檢查。代理會將檢查結果發送到一個聚合層,這個聚合層會將聚合後的結果發送給Origami。Origami會基於規則確定要將哪些告警發送出去,這個規則會查看故障告警的數量以及底層告警的緊急程度來進行判斷。藉助Origami,Neris能夠在每個數據中心的主機羣中每分鐘運行大約150萬次檢查。

當代理在主機上啓動時,Neris會從一箇中央配置存儲中拉取關於該主機的告警定義信息,這個中央配置名爲Object Config,它廣泛應用於Uber的低層級基礎設施服務中。給定主機要運行哪些告警取決於它的角色。例如,運行Cassandra的主機應該檢查Cassandra的狀態、磁盤使用以及其他度量指標。大多數這種主機級別的檢查是由基礎設施平臺團隊創建和維護的。

圖3:藉助Neris,會對數據中心中的每個主機進行檢查,並由Neris聚合器進行聚合,然後Origami會發送告警通知。

處理基數

對於我們的告警系統來說,高基數一直是最大的挑戰。在傳統做法中,可以運行一個告警查詢並返回多個序列,然後可以針對該告警運行簡單的規則,如果違反閾值的序列超出了特定的百分比,就會發送該告警信息。uMonitor還允許用戶基於其他告警的結果而發送告警。假設一個告警所跟蹤的範圍依賴於一個範圍更大的告警,如果範圍更大的告警已經發出的話,依賴它的告警就會被抑制。

如果查詢只返回數量有限的序列,那麼上述技術能夠運行地非常好,依賴也能很容易地進行定義。但是,Uber隨着增長,需要運維跨數百個城市的衆多產品線,基數方面所面臨的挑戰需要一個更加通用的解決方案。我們使用Origami來幫助我們處理高基數方面的問題。Neris使用Origami作爲其主要的數據去重和通知引擎,它爲uMonito告警實現了統一的通知。

對於業務指標,當我們希望爲每個城市、每個產品、每個版本的應用提供告警時,Origami就非常有用了。Origami允許用戶爲城市、產品和應用程序版本組合創建底層的告警/檢查,並根據聚合策略發出告警,以便於接收基於每個城市/產品/應用程序版本的通知。在出現更大規模的停機情況時(例如,當許多城市同時出現問題時),Origami將發送累積的通知,它代表了底層告警的觸發列表。

在主機告警的場景中,Origami能夠根據聚合的不同狀態發送不同嚴重程度的通知。以Cassandra集羣的磁盤使用爲例,在這個場景下,Origami的通知策略可能會像如下所示:

  • 如果三個以下的主機磁盤使用率爲70%,使用Email進行通知;
  • 如果三個以上的機磁盤使用率爲70%,使用短信(Send A Page,通過網絡發送文字通知-譯註)進行通知;
  • 如果有一個或更多的主機磁盤使用率達到了90%,使用短信進行通知。

告警通知

在擴展我們的告警系統時,有用的警報信息是最大的挑戰。告警操作一般會從通知開始,比如針對高優先級的問題,爲值班工程師發送短信,對於信息級別的問題,給他們發送郵件或進行線上聊天工具通知。我們現在的焦點工作已經轉移到爲這些問題構建緩解操作。大多數故障和中斷都是由於配置更改或部署而引發的。在緩解操作方面,uMonitor爲回滾最近的配置和部署環境提供了良好的支持。對於具備更復雜緩解操作的團隊來說,我們會支持webhook的方式,它會針對某個端點發起一個POST調用,在調用中會包含告警的完整上下文信息,在這個請求處理中可以運行緩解問題的操作。除此之外,通過使用Origami中的去重管道,我們可以在出現更大範圍的停機狀況時,抑制粒度更細的通知。

除了以上提到的功能,我們一直在努力使通知更加具有相關性,也就是讓它們針對最合適的個人。最近的一項工作涉及到識別配置/部署的更改者,並在他們所修改的服務出現告警時,直接聯繫到這些修改人。通過將Jaeger的跟蹤信息與告警信息相結合,我們能夠在爲出現故障的服務發送告警通知時獲取更多的上下文信息。

告警管理

如前文所述,我們一直致力於將uMonitor打造成爲一個平臺,讓其他的團隊都能根據特定的使用場景基於它來進行構建。主機告警的設置和管理通常是比較專業化的,由維護專屬硬件的團隊和爲公司構建基礎設施平臺的團隊來進行管理,包括存儲、度量指標以及計算解決方案。告警是在團隊的Git倉庫中進行配置的,它們會同步到Object Config中。

如果從較高的級別來進行區分,uMonitor有三種類型的告警:

  • 針對所有的服務,根據CPU、磁盤使用情況和PRC統計數據等標準度量指標自動生成的告警;
  • 通過UI創建的一次性告警,主要用來探查特定的問題;
  • 通過腳本或基於uMonitor的外部配置系統創建和管理的告警。

我們看到,增長最快的是最後一種告警,因爲團隊都致力於在最細的粒度探查可告警的問題。對這種粒度的需求來源於Uber的全球化增長。對於支撐Uber移動應用的服務來說,代碼變更通常只涉及特定的一組城市,並且只會在幾個小時內有效。所以,非常重要的一點在於,我們需要在城市級別監控平臺的健康狀況,從而能夠在問題大範圍擴散之前將其定位出來。除此之外,每個城市的配置參數都是不同的,這些配置是由工程團隊和當地的運維團隊所控制的。例如,遊行或其他的事件會導致交通狀況的變化,騎行者在街道上可能被攔阻。

很多團隊都基於uMonitor構建了告警生成方案以解決此類問題。這些工具所解決的挑戰包括:

  1. 跨不同維度,迭代生成告警;
  2. 根據特定的業務信息確定告警的時間安排,比如特定國家或城市的節假日,要將這些信息配置在uMonitor中,以避免出現虛假告警;
  3. 在靜態或當前異常閾值都無法發揮作用的情況下,根據過去的數據或底層度量數據的複雜查詢來確定閾值,這些閾值會用到特定的業務線上(關於告警查詢,參見下文的介紹)。

除此之外,很多這樣的方案都會生成儀表盤,它們會與生成告警保持同步。

uMonitor還提供了UI,用於編輯告警和展現根本原因。UI化的編輯和實驗性功能非常重要,因爲指標具有變化性和峯值,所以大多數的指標不能原樣作爲告警進行發送。可觀察團隊提供瞭如何創建查詢更適合作爲告警的指南。

告警查詢

Graphite查詢語言和M3QL提供了大量的功能,以便於支持更加可定製化的方案。如下是一些樣例,列出瞭如何讓查詢返回更加一致的值,從而能夠讓度量指標更加具備告警的能力:

  1. 告警要反映幾分鐘的移動平均值(movingAverage),以消除指標峯值的影響;
  2. 將上述操作與一定的持續時間結合起來,只有當在一定的時間內持續違反閾值的時候,纔會發送通知;
  3. 對於具有上升和下降模式的指標,使用導數函數,確保兩個方向的峯值都不會變化太劇烈;
  4. 針對百分比或比例進行告警,這樣度量指標就不會受到量級變化影響。

未來計劃

在擴展系統時,我們剛剛使其具備檢測分鐘級問題的能力,並且能夠做到只爲用戶顯示恰當的信息,抑制掉不必要的告警。我們正在致力於將該功能應用於管道的各個組成部分中,包括更有效地收集度量指標、擴展性以及流程化告警執行的基礎設施,並構建跨各種資源協調信息的UI和接口。

英語原文:https://eng.uber.com/observability-at-scale/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章