網易游戲AIOps實踐:異常檢測的優化策略與平臺化建設
本次分享主要介紹如下幾點:
- AIOps路線規劃
- ?異常檢測?
- 平臺化建設
- 故障管理智能化
AIOps即智能運維,是 Gartner 在2016年提出的概念。最初的定義是Algorithm IT Operations,指通過機器學習,數據倉庫以及大數據等技術手段,將人工智能應用于運維領域,基于運維產生的數據(日志,監控,應用等)進行分析決策,得出最佳的運維策略,并隨著技術的成熟,最終走向無人化運維。
一、AIOps路線規劃
1、AIOps能力階段
羅馬非一日建成,根據之前發布的企業級AIOps實施白皮書指出AIOps的發展主要有以下的五個階段,這個在我們目前的實踐過程也確實得到了驗證。
- 開始嘗試應用AI能力,還無較為成熟的單點應用。
- 具備單場景的AI運維能力,可以初步形成供內部使用的學件。
- 有由多個單場景AI運維模塊串聯起來的流程化AI運維能力,可以對外提供可靠的運維AI學件。
- 主要運維場景均已實現流程化免干預AI運維能力,可以對外提供供可靠的AIOps服務。
- 有核心中樞AI,可以在成本、質量、效率間從容調整,達到業務不同生命周期對三個方面不同的指標要求,可實現多目標下的最優或按需最優。
網易游戲智能運維團隊于2018年開始進行算法研究以及具體落地場景的選擇,后續在在線人數、異常檢測、日志異常檢測方面嘗試單點應用突破,并取得顯著的成效。目前通過串聯各維度運維信息和報警信息來進村后故障發現和故障自愈的目的,達到多個單場景AI運維模塊串聯的流程化AI運維能力。
這里的學件指的是AI運維組件,由南京大學周志華老師原創,是指模型+規約,具有可重用、可演進、可了解的特性。
AIOps階段
2、人員結構
相較于Devops,AIOps的人員結構肯定也發生了一些變化,最顯著的變化就是加入了算法工程師這個角色。有的團隊會傾向于叫算法開發研發工程師,也就是既具備算法的能力也具備平臺開發能力的工程師。當然如果一個算法工程師能夠具備良好的工程能力,這個對于整體的團隊發展肯定是有正向影響的。但很抱歉,一個團隊里要求每個算法工程師都具備良好的工程能力其實是比較困難的,特別的是在招人的時候會發現,算法和工程還是有一定割裂的。
所以我們團隊的配置,更多是下面這三個角色:運維工程師,也可以說是我們的用戶,他們負責向算法工程師提供具體的業務場景及需求,挖掘潛在的智能化場景,同時向平臺研發工程提供平臺開發的場景需求。另外就是平臺研發工程師與算法工程師,一個主要負責工程化以及平臺化的建設,懂一點算法,但其主要職責更多偏向工程開發。而算法工程師則注重算法對應業務的調研,開發以及調優,這種結構也是為做到術業有專攻的目的。
實際合作下來,這種合作方式極大地提升了業務開發的效率,但也存在一定技術盲區的問題。
3、業務領域
1)時間序列異常檢測
時間序列數據是按時間順序排列的、隨時間變化且相互關聯的數據序列。由于運維場景的特殊性,運維數據天生便與時間序列密切相關。AIOps提供的時間序列智能分析的能力,即是通過研究歷史數據的變化趨勢和內在性質,來實現時間序列預測,異常數據監測等無需人工參與的智能分析功能。
2)故障定位與根因分析
隨著微服務的發展,業務組網愈加復雜,問題的定界定位分析變得尤為困難。故障的識別和診斷是運維場景中智能分析的核心部分。AIOps提供的故障識別和根因定位能力,即是通過數據挖掘的手段,綜合故障數據和人工經驗自動提取故障特征,自動定位故障。
3)文本處理分析
文本的處理有廣闊的空間。AIOps提供了范圍極廣的文本處理分析的能力,涵蓋信息提取,語義分析,智能搜索,對話系統等領域,提供可直接應用于產品策略的NLP技術能力。
4)聚類與相似性分析
將物理或抽象對象的集合分成由類似的對象組成的多個類的過程被稱為聚類。聚類即是根據某種相似性進行抽象的過程。AIOps提供的聚類和相似性分析服務,能夠使用有監督或無監督算法,結合統計學特征,對給定格式的數據進行相似性聚類,從而極大的降低數據的識別和處理成本。
二、異常檢測
1、問題
傳統的靜態閾值目前已經難以適配多變的業務場景,閾值過高會遺漏告警,閾值過低會引發告警風暴。時間序列指標的異常檢測,不同于傳統的靜態閾值,用戶不需要自己手動配置。AIOps通過機器學習算法結合人工標注結果,實現自動學習閾值,自動調節參數,提高告警的精確度和召回率。異常檢測能夠更適配業務多樣化的需求,覆蓋更多的異常類型。
2、適用場景
1)異常閾值難以定義
- 難以明確定義正常、異常數據,沒有明顯的閾值界限。
- 在不同的時間段有不同的閾值。
- 有一些數據的異常突變沒有達到預定義的閾值。
- 需要識別的異常是與歷史數據的某種表現模式的異常,無法設置閾值來檢測。
2)人工配置成本高
- 不同的曲線配置不同的閾值,曲線很多的情況下人工配置成本很高。
- 隨著業務變化,預定義的閾值需要隨之變化,運維成本高。
- 本身含有噪聲,難以區分噪聲和異常數據,需要花費大量人力檢測。
對于異常檢測,其實網上很多文檔或者書籍都給出了一些常用的算法或者工具,我們這方面相應用的也是這些算法或工具,當然了也做了許多相應的算法優化和調整,我這里給出一些我們團隊的在這方面的思考跟策略。
在模型是線上我們選擇統計+規則的無監督方案,主要優勢在于:
- 無監督無數據標注成本
- 統計+規則的方式可解釋性強
- 模型預測時延較低
- 受曲線時間粒度的影響較小
3)毛刺異常
毛刺異常表現為在某個時刻,KPI曲線上突然出現的一個不具有周期性的局部極大值毛刺。如果僅用KPI的幅值進行閾值判斷,很多時候無法準確找到異常值,因為KPI值本身也可能存在一定的趨勢。使用一階差分可以有效去除趨勢項,使得異常能夠暴露出來。此外,SR算法對于此類的異常也具有較好的檢測效果。
4)突升突降異常
突升突降異常表現為當KPI曲線上出現異常突升或突降,并未馬上恢復,KPI的值持續保持在該異常值附近的異常。這是一種持續異常,很多業務如在線人數、CPU使用率等都非常關注這類的異常。識別此類的異常可通過異常點兩端窗口內的均值偏移來識別。
但是由于KPI本身具有趨勢和周期,正常點兩端窗口也存在均值偏移。此時,可以使用STL對時間序列進行分解,然后對殘差部分進行均值偏移的計算,即可降低趨勢項和季節項帶來的誤報。另外,大毛刺也會產生均值偏移,容易產生誤報。因此在計算兩端窗口均值前,用esd檢驗來進行異常值的去除,這樣可以去除大毛刺對均值的影響,減少模型的誤報。
5)頻率變化異常
頻率異常表現為持續的毛刺異常,此時曲線的震蕩加大,也屬于一種持續異常。雖然此類曲線比較少見,但是也是業務比較關心的異常類型。
可以使用窗口內一階差分異常計數值來進行判定。
3、異常判定方法
在設計出各類檢測模型后,需要根據模型的輸出進行異常判定,從而確定當前點是否為異常。針對瞬時異常和持續異常,需要使用不同的方法進行異常判定。
1)分布法
根據對數據分布的假設,設定閾值,適用于瞬時異常的判定。我們使用3sigma和箱型圖來判定瞬時異常,經測試,在大部分曲線上具有較魯棒的判定結果。
2)業務計數閾值法
根據業務需求,設定計數閾值,適用于持續異常的判定。我們為持續異常設定計數閾值,如果異常計數超過該閾值的時候,就進行報警。如魯棒回歸時統計實際曲線和預測曲線差值異常的計數;如窗口內一階差分異常的計數等均可直接通過計數閾值來判斷。
此外,為了融合不同模型的輸出,得到更魯棒的判定結果,可以把分布法、業務計數閾值法通過線性轉換轉化為0-1之間的分數,此時模型融合可以通過分數加權的方式得到,融合分數超過0.5的即為異常,可以在不同的曲線中保持較優的異常判定效果,也具有較強的魯棒性。
三、平臺化建設
AIOps本身也是一個迭代式的開發模式,在平臺化期間我們也遇到了一些問題。首先是算法和工程邊界比較模糊,算法工程師希望能夠專注算法的開發和調優,不想花過多的時間在工程上。還有就是算法包跟工程強耦合,算法的每次調優和參數變化都需要工程配合發版。
我們希望算法,工程能夠更好的解耦,既能滿足算法快速迭代的的需求,也能滿足工程平臺開發穩定性的要求。
另外我們還發現AIOps使用到的數據可能是多種多樣的,就異常檢測一個場景來說,基礎指標數據、日志數據、模板數據都不同。
擴展到故障定位可能還需要用到配置相關的數據,比如業務拓撲網絡拓撲的CMDB數據,甚至再結合到異常事件,變更事件這一類事件信息數據等等。
1、系統架構設計
基于以上的問題和目標,我們設計如圖所示的五層系統架構,其核心目標是可按需加載不同的算法,編排不同的檢測流程,在保障高可用的同時,達到提供多種服務類型但是又能統一管理,各個業務之間甚至進程之間隔離,通過統一的平臺進行調度,為了節省資源,對算力進行動態調整,保證整個服務的運行效率。
1)數據接入層
最下面的數據接入層負責對各類監控指標,系統日志,業務日志以及業務指標進行實時的采集。對于系統及業務指標,可以通過我們監控團隊自主開發的agent進行數據收集,一般在各服務器初始化的時候就會自動安裝配置。
2)數據層
由上面數據接入層采集到的數據會寫入到HDFS進行持久,同時該層也會負責將采集到的數據進行預處理、ETL、聚合等等。為了提高性能和可用性,指標數據會根據冷熱數據的區別分別存儲在TSDB和Redis中,而我們的檢測用到的歷史數據就是從這里面獲取的。
3)服務層
這里主要通過離線的方式對模型進行模型訓練,將訓練完成的模型上傳到S3上進行存儲,當模型迭代或者算法策略變更時,算法工程師可以自主的完成全鏈路的開發測試,不需要平臺工程師的接入。由于模型是從平臺框架中抽離出來出來的,可以進行獨立的配置和管理,更進一步的降低了算法和工程的耦合。另外當有新的業務場景接入的時候,算法和工程師可以通過約定接口的方式,各自獨立進行代碼開發,各自上線。
4)應用層
區別于網絡服務的應用層,這里更多是指各個不同的saas平臺的功能性應用,基礎運維負責反應真是的指標波動情況,通過數據層對數據進行聚合,目前我們監控團隊已經做到了秒級監控的數據展示。而AIOps平臺也是嵌入在這一層里面的,其主要的功能是通過實時流,任務調度等方式,通過調用相應的模型對數據進行各種算法檢測。
5)展示層
用于檢測結果展示,已單個事件或數據圖譜形式展示。
2、檢測流程設計
這里主要介紹一下應用層的檢測平臺內部實現思路,整體的一個數據流向如這張圖所示。用戶會在我們的運維門戶網站上建立相應的檢測任務,并將配置同步到flink規則數據庫中進行保存,這個時候agent會采集相應的指標數據發送到flink里進行預處理,flink根據規則數據庫中配置對數據進行前置的過濾與預處理。
處理后的數據還會經過一個算法編排的模塊,這個模塊主要是根據之前用戶的配置以及我們預設的匹配規則,為檢測的數據增加上一些編排,任務,策略相關的信息,這類信息決定了算法所用到的模型,歷史數據,特征等信息。隨后根據這些信息,動態的加載模型進行調用并輸出結果。
算法模型作為算法的抽象,可通過注冊上傳的方式將模型上傳至S3種進行存儲,注冊完成后的算法模型會相應的生成編排,訓練的組件。平臺與組件之間,通過定義算法的唯一標識,接口,輸入輸出類進行交互。平臺調度引擎會根據上述配置,動態的加載相應的算法模型進行檢測調度。
具體檢測架構實現思路如圖所示,首先算法模型作為一個可插拔的算法包存在服務當中,每個算法包擁有獨立的線程資源,利用python的類加載方式可根據需要進行下載和更新,實現算法模型的熱部署。
框架本身相當于一個調度管理工具,負責加載不同版本的算法,執行算法路由以及策略計算。同時我們設計一套相關的編排調度協議,將具體的參數配置及編排模式開放給工程師自己進行定義,進一步解耦了算法和工程,業務和平臺之間的關聯。
如一些業務場景往往需要用到歷史數據,歷史數據的獲取跟預處理其實算法工程師并不在意,這類的操作一般都交給平臺工程師來處理。
我們在平臺內部將歷史數據獲取的邏輯進行了抽象化,具體業務數據的獲取和存儲由平臺工程師根據業務需要編寫相應的輸入輸出,算法調用模塊通過協議獲取一些關鍵的參數與配置,內部自動調用這些具體的類和方法獲取數據,并將數據傳遞給模型進行檢測。
其實在對歷史數據獲取和處理的過程中,歷史數據的抽取往往會成為瓶頸,比如算法可能需要7~8天的歷史數據作為輸入,那隨著檢測數量的增加,這對于TSDB是有巨大壓力的,再加上計算歷史特征可能需要的輸入量不盡相同,冷熱數據,讀寫分離都能以解決,對我們平臺內部也維護了一套歷史數據的內存存儲,通過pipeline加數據壓縮的方式進行歷史數據緩存。同時將部分的計算特征通過內存進行存儲,減少實時計算模塊的壓力。
這里是我們抽象化類圖的實現方式,基礎類里面提供了存儲,編排,更新等基本操作,平臺開發工程師根據業務場景自行定義數據以來,通過組合這些獨立的功能,從而滿足各種不同的業務需求。
在用戶體驗方面我也做出了一定的改變,首先是異常標注的方式,我看許多的平臺都是以事件和同環比的形式展示出來,因為我們本來就有了一個報警平臺兄弟系統,而且實際使用下來發現這種單個事件同環比的形式很容易給用戶造成誤解,所以我們用像grafna的大圖形式進行異常的展示和標注。
另外其實用戶反饋和標注是很重要的,很大程度上決定了模型的調優,提升算法的準確性,有的時候用戶其實挺懶的,往往疏忽了標注這件事,我們通過內部的消息工具popo,直接將檢測結果與標注鏈接發送給用戶,培養用戶標注的好習慣。
四、故障管理智能化
隨著游戲及系統架構的日漸復雜,運維人員收到的報警信息也變得多種多樣,在面對故障時,紛雜的報警信息令運維人員一時難以理清邏輯,甚至顧此失彼,無法在第一時間解決最核心的問題。在與我們程序與SRE交流過程中,我們發現他們面對故障主要存在以下痛點:
- 游戲架構日漸復雜,出現故障后排查鏈路比較長。
- 故障產生后,往往會引發多個報警,但是這些報警比較零散,沒有按照一定的規則去分類和可視化。導致排查過程中需要人工先去梳理,和過濾報警。
- 目前故障定位依賴人工經驗,這些經驗難以被復用。
眾所周知,業務指標是最直觀反應故障情況的手段,日志記錄是記錄應用程序運行狀態的重要工具。我們希望在保留細節的同時,將上述泛化的報警信息通過聚類的方式進行概括,使得在報警發出后,結合指標、日志、tracing、變更事件等信息,通過故障傳播鏈關聯起來,找到最有可能造成故障的原因。
業務指標是整個故障定位的觸發源,我們選擇了游戲SLO中的重要指標,按照群組的維度進行分類。由于SLO業務指標毛刺較多,直接用普通的毛刺無監督模型會產生較多的誤報,只有異常持續抬升或者下降一段時間,才能被認為是異常,因此SLO異常檢測模型使用抬升異常檢測。
抬升異常檢測主要由兩個模型構成,一個是均值偏移模型,另一個是預測均偏移模型,最終的結果會融合兩個模型的輸入輸出。
1)均值偏移模型
- 計算左右兩側給定數量的均值差。
- 當差值大于或者小于一定閾值時,則認為出現抬升異常。
2)均值預測偏移模型
- 先用左側、右側給定數量的點分別進行線性回歸,預測右、左兩側給定數量的點的值。
- 再將其與右、左兩側真實值作差。
- 對這些差值求均值。
- 當該均值大于或小于一定閾值時,則認為出現抬升異常。
在業務指標異常后,啟動故障定位,開始機器指標異常檢測及排序。通過異常分數排序的方式得出最有可能的異常根因。
- 當業務指標出現異常的時候,在當前時間點往前推的20min的區間內對所有指標進行毛刺異常檢測,計算異常檢測分數。
- 異常檢測分數乘上時間衰減系數,作為根因分數,即越早發生的異常越有可能是根因。
- 輸出20min內根因分數的最大值作為該指標的根因分數,然后在機器名范圍內進行排序,在僅考慮單根因的前提下,異常最多的機器作為根因機器,其中指標的異常按照根因分數排序輸出指標根因列表。
在對機器指標進行異常根因排序的同時,我們還會掃描相關saas的機器指標與報警信息,最終結合日志異常檢測及分類,將根因結果展示給用戶。
Q&A
Q1: 上智能化運維前期規劃上有什么好的方向及規劃建議?
A1:首先智能運維不是一個一蹴而就的過程,是作為一個長期演進的系統存在,其根基還是運維自動化,數據收集,分析,監控等基礎運維工具。在前期規劃上需要解決的問題包括海量數據的存儲,分析與處理,數據倉庫的搭建,基礎監控的實踐經驗等。好的數據往往比模型更具有價值。在完成上述基礎建設后,可與具體業務人員了解其最關注的SLO,通過這方面進行異常檢測建設。在模型選擇方面,盡管有監督的標注成本會很高,但有監督模型比無監督模型更加容易貼近業務需求,在后期更新迭代上占有絕對優勢。
Q2:AIOps基礎肯定是大量的歷史監控數據,數據的收集規則與建模規則你們怎么設計?
A2:目前我們已基本完全采用了prometheus的接入方式,并在此基礎上建設了數據采集中心。其主要收集規則基于收集器與適配器模式,用戶通過收集器進行數據上傳,適配器對數據進行重新組裝直接發送到相應的消息隊列中等待存儲。數據模型統一使用json標識,數據格式則采用prometheus的數據格式。
Q3:日志的采集規則,您能講講嗎?現在日志檢測的思路的是怎樣的?
A3:用戶通過我們自定義的client定義相關日志指標,自行采集數據,sdk單獨開啟進程定期讀取內存中數據,組裝成日志格式,由我們這邊的日志團隊進行數據收集。具體數據格式如上一個問題。對于容器日志收集的方法,一般是通過以下幾種方法:
- 容器內收集日志:容器進程自行寫出;agent收集。
- 容器外部收集:docker logs api及docker log-dr;日志收集agent;掛載volumes;自行開發agent。
我們目前日異常檢測算法主要依賴日志智能分類算法,需要在獲得日志實時分類模板后,根據各模板的日志量的歷史數據使用3sigma與箱線圖進行異常判定,從而發現其中的異常模式,并將對應的異常通過告警發送給用戶。
Q4:做告警收斂,都有哪些思路,哪些效果比較好?
A4:告警收斂的方式主要有幾種:
- 基于預設好的規則進行收斂。比如A、B報警來自于相同機器/模塊,就將AB收斂合并。
- 基于報警時間/報警次數的收斂。如將5min內報警合并發送。
以上兩種是策略型,可以將部分的報警進行收斂,但不能得到報警之間的關聯性。
- 基于拓撲收斂。根據拓撲結構將報警進行關聯,達到收斂效果。 可以得到報警之間的關聯性,利于排障。但一般比較難獲取到拓撲。
- 基于關聯規則挖掘的收斂。根據歷史報警信息,挖掘出頻繁同步出現報警規則,進行合并。 可以得到報警之間的關聯性,但依舊沒有形成故障現場,有一定的排障效果,并不依賴于拓撲。
- 構建報警知識圖譜,進行收斂。理想化方式,效果最佳。但需要拓撲和歷史數據積累,和專家知識,較難實現。
Q5:基于互聯網電商應用監控的動態閾值算法怎么選型?
A5:主要可分為有監督選型和無監督選型:
- 有監督異常檢測的方案可采用先利用CNN+AutoEncoder模型對曲線進行分類,并建立無監督模型來抽樣找出異常樣本,從而建立起樣本庫。并利用建立在經驗基礎上選取的一系列特征,作為有監督模型的數據輸入。最后,使用集成模型對數據進行訓練來以保證模型的穩定性。
- 無監督異常檢測的方案采用通過建立包括3-sigma,百分位數分布和箱型圖等的集成模型,計算對歷史數據中特征的多個分布來判斷該特征在當前的異常可能性,然后把不同特征計算出來的異常分數,按比例結合起來,與按照經驗設定的異常閾值比較,檢測異常。