鄭杰生,謝彬瑜,吳廣財,陳 非,花 磊
(1.廣東電力信息科技有限公司,廣東 廣州 510000; 2.蘇州博納訊動軟件有限公司,江蘇 蘇州 215000)
微服務架構由于具有開發效率高、部署敏捷、彈性伸縮等優勢,越來越多地用于開發各類應用[1]。云計算數據中心近年來廣泛部署基于微服務架構的軟件應用,相應的基礎架構(如Kubernetes,Mesos)也隨之快速發展以支撐和管理大規模微服務[2]。由于多樣化的微服務應用具有不同的資源需求和行為特點,數據中心管理更加關注服務及應用特征,以針對不同應用類型制定管理策略。微服務生態系統具有異構性,包括開源軟件(如Nginx,Redis)、第三方服務和特定領域應用,剖析和理解微服務應用以保障可靠性具有挑戰性[3]。已有微服務分析方法通常研究單個微服務以分析特定應用屬性,如可執行文件名稱、端口號、配置文件、容器鏡像元數據。但是,這些屬性不是微服務的固有屬性,可以進行隱藏或調整,并且會隨著軟件技術的發展而動態擴展,因此這種面向特定應用的分析方法具有不可靠性或不完整性;基于包檢查的應用分析方法計算效率低下,無法以較小開銷及時分析實際部署微服務的運行時行為,難以在代碼級準確解析微服務特征;另外,嚴格的租戶隱私標準禁止對租戶的微服務進行侵入性分析或檢測,增加了準確分析微服務的難度。
該文以統一、高效、非侵入的方式監測微服務應用的運行時行為。對于以進程形式運行的微服務,搜集微服務與主機操作系統交互時(如訪問文件系統和網絡,同步線程)發出的系統調用;對于基于容器(如Docker,LXC)部署的微服務,監測服務器操作系統內的系統調用,與應用無關且對微服務透明,可以對不同微服務應用實現統一的非侵入式低開銷的系統調用監測。
為了應對實際環境中不斷增長的多種類型的微服務應用,該文提出了一種監督式貝葉斯學習模型,將系統調用序列刻畫為k階馬爾可夫鏈,使用k階轉移概率表示序列化的微服務行為歷史記錄,對系統調用執行序列進行精細劃分,以刻畫不同類型微服務應用的特點。進而,面向特定微服務應用類型,使用自監督式的自動編碼器建模微服務應用的行為,通過該模型檢測當前應用的系統調用序列是否出現異常。
微服務通常作為獨立進程或在容器內部執行,每次調用微服務會產生相應的系統調用流。將微服務執行單元集合表示為U={u1,u2,…,un},其中,ui為進程或容器形態的微服務執行單元,n為執行單元數量。當ui調用發生時,會生成有序的系統調用序列,建立模型以表示微服務執行的隨機過程,通過系統調用間的轉移概率表示微服務應用類型的行為特征。方法具體包括以下步驟:

而后,評估系統調用條件概率。使用訓練序列數據集估計條件概率,pj(vj|v)表示在微服務執行單元uj調用序列中,系統調用行為v之后vj出現的概率。對于0階序列模型,執行單元uj的系統調用v的概率為pj(v)。對于k階序列模型,當前動詞依賴于最近k個動詞,行為v的調用概率為pj(vj|v)。一旦從訓練序列中計算得到執行單元uj的條件概率,可以依次遞歸估計該序列中各系統調用行為的條件概率。

基于貝葉斯的系統調用序列建模的計算開銷隨著微服務數量線性增長,在實際部署環境中,服務執行單元數量通常較高,因此會具有較高的計算開銷。此外,高階貝葉斯模型在uj上計算k階條件概率矩陣將產生指數級訓練時間,并且矩陣計算會占用較多內存。為了解決此可伸縮性問題,以分層方式進行微服務類型分析。首先,使用分層聚類方法[4]將執行單元uj分為N組。使用Minkowski距離計算兩個執行單元之間的距離,并基于距離度量執行聚類操作。
算法1具體描述了文中使用基于深度學習的自動編碼器進行異常檢測。在訓練過程中,將系統調用序列表示為固定長度的特征向量,使用訓練數據集構建自動編碼器以重建原始訓練數據。在測試過程中,如果當前系統調用序列數據的特征向量為異常序列數據,自動編碼器會產生較高的重建損失。對于微服務執行單元uj,將訓練得到的自動編碼器表示為AEj,測試序列產生的重建損失應在隨機變量Lj的置信區間[5],否則將該序列數據檢測為異常系統調用序列。因此,需要選擇合理的損失閾值L,以最大程度減少假陽性和假陰性檢測錯誤。
算法:基于模式識別的異常檢測。
輸入:Seq //微服務系統調用序列。
輸出:AnomalyScore //微服務異常值。
過程:
AnomalyScore=loss //異常值初始化為當前編碼器的損失值
for eachAEiinGdo //遍歷編碼器集合G
loss=evaluate(AEi,Seq) //使用編碼器計算最小損失值
if AnomalyScore>loss then
AnomalyScore=loss
end if
end for
如圖1所示,文中實現了提出的異常檢測方法的原型系統,主要包括監測代理、系統調用監測器、微服務分析器和異常檢測器等四個模塊。

圖1 微服務異常檢測系統架構
在實際部署中,系統調用追蹤技術通常采用ptrace軟件工具,對于每個系統調用,被追蹤的進程會暫停兩次,因此會引入巨大的資源和性能開銷。為了以較小開銷實現非侵入系統調用監測,該文使用eBPF內核虛擬化技術,無需自定義內核,將用戶定義的字節碼程序動態注入到內核掛鉤函數,以監測關注的內核事件,支持即時編譯以在內核中以主機速度運行。使用基于eBPF的系統調用追蹤程序vltrace,確定每個系統調用的進入和退出位置,并記錄系統調用的眾多參數。但vltrace采用重量級監測方案,不提供運行時的靈活性,一旦eBPF程序被編譯并加載到內核中,其追蹤行為便會保持不變,因而難以在每個微服務上動態啟用/禁用追蹤以最小化開銷。該文僅在每個系統調用中,記錄系統調用的ID和時間戳,并且進行擴展以收集特定于系統調用上下文(例如,用于打開、讀取、寫入等文件描述符)的細粒度系統調用監測信息。動態打開/關閉不同PID追蹤,無需重新加載eBPF追蹤工具軟件,只需寫入訪問的內核PID表。當加載新的微服務時,Docker容器運行時環境會將主要PID通知給用戶空間信息收集器的守護程序。然后,將所有PID記錄在進程樹的PID表中,特定的PID積累足夠的追蹤數據時,將PID標記為停止追蹤,并匯總記錄信息。
微服務的中心數據庫從系統調用監測器收集系統調用序列以持久化存儲。監督式貝葉斯學習模型由訓練和檢驗兩個階段構成。在訓練模式下,系統調用監測器向模塊提供系統調用序列訓練數據集,并且將其標識為特定微服務執行單元的訓練數據。微服務分析器模塊檢查大小為k的輸入序列,并為微服務建立k階轉換矩陣。如果已經學習了該微服務類型,那么就存在相應的轉移矩陣,新的序列數據將會增強該模塊,而后將矩陣的轉換次數歸一化,使用Dirichlet優先級將其初始化。在檢驗模式下,測試序列輸入到該模塊,對于每個訓練的微服務,使用k階矩陣計算序列的概率分布。選擇最高概率的微服務類型,并聲明該序列數據屬于該微服務類型。微服務之間的概率分布隨測試序列長度的增加而變化,如果微服務已成功分類,則該微服務的概率將迅速收斂。
對于每個微服務執行單元uj,實現序列到序列的自動編碼器AEj集合,重構原始輸入序列為輸出序列,對新添加的序列數據進行異常檢測。輸入序列在輸入自動編碼器之前轉換為編碼矢量;自動編碼器將此序列編碼為64維特征向量;輸出重復L次以構建中間序列(L為輸入序列長度);中間序列經過具有softmax激活函數的時間分布Dense層,被另一個具有64個輸出單元解碼為原始的編碼輸入序列。
實驗環境部署7臺虛擬機(VM),每臺VM具有2.40 GHz虛擬CPU內核,32 GB內存,運行在CentOS 8.0,啟動了bcc和eBPF JIT以監測微服務運行。
本節評價原型系統對資源和性能的影響。對于CPU資源開銷,基于eBPF的內核追蹤程序監測微服務的每個進程的前N個系統調用,忽略后續系統調用,比較了兩種不同設置下服務器的CPU使用率。首先,在裸服務器上部署微服務,不啟動eBPF與監測數據搜集器,監測服務器的總CPU時間。而后,運行eBPF追蹤器和監測數據收集器,但是禁用對微服務的追蹤。重復產生相同負載,MySQL、MongoDB、WordPress、ownCloud、Joomla的CPU時間開銷分別為3.47%、2.58%、4.17%、4.86%、3.08%,微服務監測的CPU時間開銷低于5%。
在性能開銷方面,本節運行三個基準程序iperf、dd和gzip,分別模擬網絡I/O、磁盤I/O與CPU密集的微服務,分別啟動和不啟動系統調用監測。iperf模擬網絡I/O密集微服務,性能衰減5.17%;dd模擬磁盤I/O密集的微服務,性能衰減7.26%;gzip模擬CPU密集微服務,性能衰減3.14%。實驗結果表明,對于不同類型的工作負載,監測系統引入了較少的性能開銷。
通過在原型上部署各種實際的微服務以評估原型系統的分類能力。該文選取NoSQL數據庫、SQL數據庫、KV數據庫、HTTP服務器、文件系統、遠程訪問、內容檢索、內容服務等八類24個典型微服務,產生工作負載,搜集系統調用序列數據以構成訓練數據集合。選取的微服務中有一些具有更高的相似度,例如,MariaDB和MySQL都是執行數據庫相關操作;Nextcloud從ownCloud派生而來,繼承了其許多功能;WordPress和Drupal都是在Apache HTTP服務器上運行的基于PHP的Web應用程序,具有共享相同的PHP API和請求處理機制。
使用特定于微服務的工作負載生成器或手動訪問微服務執行單元來生成工作負載,從而收集系統調用序列數據。當微服務啟動多個進程時,從各PID收集單獨的系統調用序列,而后將其連接起來以形成每個微服務的長序列。由于工作負載的重復系統調用行為會在條件概率矩陣中產生偏差,序列中連續重復的最大數量限制為12。在不同的微服務中,所得序列的長度范圍從18K到450K。將每個微服務獲得的序列細分為訓練和測試序列數據,前者輸入到模型進行訓練,而后者則用于評估該模型執行的分類準確性。
選擇三種不同的微服務類別,包括Web應用、SQL數據庫和NoSQL數據庫,檢測是否可以準確識別不同類型。圖2表示微服務分類精度與序列長度的關系。為了生成不同長度的測試序列,從收集的原始測試序列中提取長度為N的隨機子序列。對于每個長度N,使用180個測試序列樣本進行分類,并計算準確率。實驗結果表明,隨著測試序列長度的增加能夠正確區分微服務類型,NoSQL數據庫、Web應用和SQL數據庫分別需要長度約800、1 000和1 200的系統調用序列。

圖2 微服務分類準確率
該文評估基于自動編碼器的異常值檢測的性能。異常值檢測過程依賴于自動編碼器產生的重建損失,因此需要設置合理的損失閾值,使得最小化漏報率,即異常測試實例檢測為正常(false negative,FN)和錯報率(false positive,FP),即正常測試實例檢測為異常。該文使用此前搜集的24個微服務的系統調用序列數據集來評估,以800個輸入序列訓練每個AEj,每個序列的長度為1 000。
采用單一自動編碼器學習現有所有執行單元生成的系統調用序列集合,然后針對給定的測試序列進行檢測,如果自動編碼器返回的重建損失高于L,則檢測為異常。圖3顯示了損失閾值對異常檢測準確性的影響,從24個微服務中刪除了2個微服務,并為剩下的22個微服務訓練了一個自動編碼器。然后,對于經過訓練的自動編碼器,將刪除的微服務所產生的系統調用序列視為異常值。據此方法,準備了24個自動編碼器,每個編碼器將缺失的微服務產生的系統調用序列檢測為異常值。對于特定的損失閾值L,從24個服務中隨機選擇一個微服務,使用準備好的自動編碼器執行異常檢測,每個實驗重復執行180次,計算異常檢測精度。如果將閾值L設置過高,則會將更多的異常序列錯誤分類為正常(即,假陰性)。如果將閾值L設置過低,則會將正常序列錯誤分類為異常(即假陽性)。使用單一自動編碼器無法同時將假陽性和假陰性最小化,可達到的準確度低于53%。為每個微服務類型訓練一個單獨的自動編碼器,實現兩級異常檢測。將前面使用的24個微服務分為六組,根據異常類型將異常檢測應用于每個分組,而后檢測每個微服務類型異常檢測的準確性。異常檢測的準確性隨損失閾值而變化,實驗結果表明,當合理選擇損失閾值,可以實現零假陽性和假陰性錯誤。

圖3 異常檢測準確率對比
系統調用監測主要用于異常入侵和惡意軟件檢測,著重于識別與正常系統行為偏離的異常?;谙到y調用監測,當前研究工作提出了許多異常檢測模型,例如子序列分析[6]、行為馬爾可夫模型[7]、有限狀態自動機[8]、動態貝葉斯網絡[9]和深度神經網絡[10]。文獻[11]提出了一種在系統調用級別的強制執行安全策略,捕獲正常應用程序行為自動生成的安全策略,可以在每個系統調用的基礎上實現簡單的準入控制,而無需考慮跨系統調用序列的依賴性。以上方法的適用性僅限于網絡應用或網絡協議[12],而文中的方法則普遍適用于應用程序的多種工作負載。文獻[13-14]提出了基于半監督學習的離群值檢測方法,針對標記樣本和未標記樣本混合的情況,通過k-means算法聚類以識別離群值,但以上方法只適用于系統規模較小的情況,難以應對微服務類型眾多、依賴復雜的應用實際部署場景[15]。
微服務架構的異構性和動態性對數據中心的運維管理帶來了挑戰,已有運行監測技術通常采用統一模型分析應用運行狀態,然而多樣化微服務的軟件行為差異巨大,難以通過單一模型刻畫。針對以上問題,提出一種基于系統調用模式識別的微服務異常檢測方法。使用非侵入的輕量級系統調用追蹤技術監測微服務的運行狀態,基于貝葉斯學習刻畫微服務行為,根據微服務行為特點進行分類,在特定微服務類型下,學習微服務運行狀態模型,基于自動編碼器檢測微服務行為異常。實驗結果表明,該方法具有較低的性能開銷,能夠有效區分微服務類型,并且準確檢測微服務異常。