預計財政收入
作者 | 李煌東
當 Kubernetes 成為雲原生事實標準,可觀測性挑戰隨之而來
當前,雲原生技術以容器技術為基礎,通過標準可擴充套件的排程、網路、儲存、容器執行時介面來提供基礎設施。同時,通過標準可擴充套件的宣告式資源和控制器來提供運維能力,兩層標準化推動了開發與運維關注點分離,各領域進一步提升規模化和專業化,達到成本、效率、穩定性的全面優化。
在這樣的大技術背景下,越來越多的公司引入了雲原生技術來開發、運維業務應用。正因為雲原生技術帶來了越發紛繁複雜的可能性,業務應用出現了微服務眾多、多語言開發、多通訊協議的鮮明特徵。同時,雲原生技術本身將複雜度下移,給可觀測性帶來了更多挑戰:
1、混沌的微服務架構,多語言和多網路協議混雜
業務架構因為分工問題,容易出現服務數量多,呼叫協議和關係非常複雜的現象,導致的常見問題包括:
- 無法準確清晰瞭解、掌控全域性的系統執行架構;
- 無法回答應用之間的連通性是否正確;
- 多語言、多網路呼叫協議帶來埋點成本呈線性增長,且重複埋點 ROI 低,開發一般將這類需求優先順序降低,但可觀測資料又不得不採集。
2、下沉的基礎設施能力遮蔽實現細節,問題定界越發困難
基礎設施能力繼續下沉,開發和運維關注點繼續分離,分層後彼此遮蔽了實現細節,資料方面不好關聯了,出現問題後不能迅速地定界問題出現在哪一層。開發同學只關注應用是否正常工作,並不關心底層基礎設施細節,出現問題後需要運維同學協同排查問題。運維同學在問題排查過程中,需要開發同學提供足夠的上下游來推進排查,否則只拿到“某某應用延遲高”這麼籠統的表述,這很難有進一步結果。所以,開發同學和運維同學之間需要共同語言來提高溝通效率,Kubernetes 的 Label、Namespace 等概念非常適合用來構建上下文資訊。
3、繁多監測系統,造成監測介面不一致
複雜系統帶來的一個嚴重副作用就是監測系統繁多。資料鏈路不關聯、不統一,監測介面體驗不一致。很多運維同學或許大多都有過這樣的體驗:定位問題時瀏覽器開啟幾十個視窗,在 Grafana、控制檯、日誌等各種工具之間來回切換,不僅非常耗時巨大,且大腦能處理的資訊有限,問題定位效率低下。如果有統一的可觀測性介面,資料和資訊得到有效地組織,減少注意力分散和頁面切換,來提高問題定位效率,把寶貴時間投入到業務邏輯的構建上去。
解決思路與技術方案
為了解決上述問題,我們需要使用一種支援多語言,多通訊協議的技術,並在產品層面儘可能覆蓋軟體棧端到端的可觀測性需求,通過調研,我們提出一種立足於容器介面和底層作業系統,向上關聯應用效能監測的可觀測性解決思路。
要採集容器、節點執行環境、應用、網路各個維度的資料挑戰非常大,雲原生社群針對不同需求給出了 cAdvisor、node exporter、kube-state-metics 等多種方式,但仍然無法滿足全部需求。維護眾多采集器的成本也不容小覷,引發的一個思考是能否有一種對應用無侵入的、支援動態擴充套件的資料採集方案?目前最好的答案是 eBPF。
1、「資料採集:eBPF 的超能力」
eBPF 的超能力體現在能訂閱各種核心事件,如檔案讀寫、網路流量等,執行在 Kubernetes 中的容器或者 Pod 裡的一切行為都是通過核心系統呼叫來實現的,核心知道機器上所有程序中發生的所有事情,所以核心幾乎是可觀測性的最佳觀測點,這也是我們為什麼選擇 eBPF 的原因。另一個在核心上做監測的好處是應用不需要變更,也不需要重新編譯核心,做到了真正意義上的無侵入。當叢集裡有幾十上百個應用的時候,無侵入的解決方案會幫上大忙。
但作為新技術,人們對 eBPF 也存在些許擔憂,比如安全性與探針效能。為了充分保證核心執行時的安全性,eBPF 程式碼進行了諸多限制,如最大堆疊空間當前為 512、最大指令數為 100 萬。與此同時,針對性能擔憂,eBPF 探針控制在大約在 1%左右。其高效能主要體現在核心中處理資料,減少資料在核心態和使用者態之間的拷貝。簡單說就是資料在核心裡算好了再給使用者程序,比如一個 Gauge 值,以往的做法是將原始資料拷貝到使用者程序再計算。
2、可程式設計的執行引擎天然適合可觀測性
可觀測性工程通過幫助使用者更好的理解系統內部狀態來消除知識盲區和及時消除系統性風險。eBPF 在可觀測性方面有何威力呢?
以應用異常為例,當發現應用有異常後,解決問題過程中發現缺少應用層面可觀測性,這時候通過埋點、測試、上線補充了應用可觀測性,具體的問題得到了解決,但往往治標不治本,下一次別的地方有問題,又需要走同樣的流程,另外多語言、多協議讓埋點的成本更高。更好的做法是用無侵入方式去解決,以避免需要觀測時沒有資料。
eBPF 執行引擎可通過動態載入執行 eBPF 指令碼來採集可觀測性資料,舉個具體例子,假設原本的 Kubernetes 系統並沒有做程序相關的監測,有一天發現了某個惡意程序(如挖礦程式)在瘋狂地佔用 CPU,這時候我們會發現這類惡意的程序建立應該被監測起來,這時候我們可以通過整合開源的程序事件檢測庫來是實現,但這往往需要打包、測試、釋出這一整套流程,全部走完可能一個月就過去了。
相比之下,eBPF 的方式顯得更為高效快捷,由於 eBPF 支援動態地載入到核心監聽程序建立的事件,所以我們可以將 eBPF 指令碼抽象成一個子模組,採集客戶端每次只需要載入這個子模組裡的指令碼完成資料採集,再通過統一的資料通道將資料推送到後端。這樣我們就省去了改程式碼、打包、測試、釋出的繁瑣流程,通過無侵入的方式動態地實現了程序監測這樣的需求。所以,eBPF 可程式設計的執行引擎非常適合用來將增強可觀測性,將豐富的核心資料採集上來,通過關聯業務應用,方便問題排查。
從監測系統到可觀測性
隨著雲原生浪潮,可觀測性概念正深入人心。但仍離不開日誌、指標、鏈路這三類可觀測領域的資料基石。做過運維或 SRE 的同學經常遇到這樣的問題:半夜被拉到應急群裡,披頭蓋地地被質問為什麼資料庫不工作了,在沒有上下文的情況下,無法立刻抓住問題核心。我們認為好的可觀測性平臺應該幫助使用者很好地反饋上下文,就像 Datadog 的 CEO 說的那樣:監測工具不是功能越多功能越好,而是要思考怎樣在不同團隊和成員之間架起橋樑,儘可能把資訊放在同一個頁面中(to bridge the gap between the teams and get everything on the same page)。
因此,在可觀測性平臺產品設計上需要以指標、鏈路、日誌為基本,向外整合阿里雲自家的各類雲服務,同時也支援開源產品資料接入,將關鍵上下文資訊關聯起來,方便不同背景的工程師理解,進而加速問題排查。資訊沒有有效地組織就會產生理解成本,資訊粒度上以事件->指標->鏈路->日誌由粗到細地組織到一個頁面中,方便下鑽,不需要多個系統來回跳轉,從而提供一致體驗。
1、端到端:展開說就是應用到應用,服務到服務,Kubernetes 的標準化和關注點分離,各自開發運維各自關注各自領域,那麼端到端的監測很多時候成了”三不管“區域,出現問題的時候很難排查鏈路上哪個環節出了問題。因此從端到端的角度來看,兩者呼叫關係是關聯的基礎,因為系統呼叫才產生了聯絡。通過 eBPF 技術非常方便地以無侵入的方式採集網路呼叫,進而將呼叫解析成我們熟知的應用協議,如 HTTP、GRPC、MySQL 等,最後將拓撲關係構建起來,形成一張清晰的服務拓撲後方便快速定位問題,如下圖中閘道器->Java 應用->Python 應用->雲服務的完整鏈路中,任意一環出現延時,在服務拓撲中應能一眼看出問題所在。這是第一個管線點端到端。
2、自頂向下全棧關聯:以 Pod 為媒介,Kubernetes 層面關聯 Workload、Service 等物件,基礎設施層面可以關聯節點、儲存裝置、網路等,應用層面關聯日誌、呼叫鏈路等。
1、永不過時的黃金指標
黃金指標是用來監測系統性能和狀態的最小集合。黃金指標有兩個好處:一,直接瞭然地表達了系統是否正常對外服務。二,能快速評估對使用者的影響或事態的嚴重性,能大量節省 SRE 或研發的時間,想象下如果我們取 CPU 使用率作為黃金指標,那麼 SRE 或研發將會奔於疲命,因為 CPU 使用率高可能並不會造成多大的影響。
Kubernetes 監測支援這些指標:
- 請求數/QPS
- 響應時間及分位數(P50、P90、P95、P99)
- 錯誤數
- 慢呼叫數
如下圖所示:
2、全域性視角的服務拓撲
諸葛亮曾言“不謀全域性者,不足謀一域 ”。隨著當下技術架構、部署架構的複雜度越來越高,發生問題後定位問題變得越來越棘手,進而導致 MTTR 越來越高。另一個影響是對影響面的分析帶來非常大的挑戰,通常會造成顧此失彼。因此,有一張像地圖一樣的拓撲大圖非常必要。全域性拓撲具有以下特點:
- 系統架構感知:系統架構圖是程式設計師瞭解一個新系統的重要參考,當拿到一個系統,起碼需要知曉流量入口在哪裡,有哪些核心模組,依賴了哪些內部外部元件等。在異常定位過程中,有一張全域性架構的圖對異常定位程序有非常大推動作用。
- 依賴分析:有一些問題是出現在下游依賴,如果這個依賴不是自己團隊維護就會比較麻煩,當自己系統和下游系統沒有足夠的可觀測性的時候就更麻煩了,這種情況下就很難跟依賴的維護者講清楚問題。在我們的拓撲中,通過將黃金指標的上下游用呼叫關係連起來,形成了一張呼叫圖。邊作為依賴的視覺化,能檢視對應呼叫的黃金訊號。有了黃金訊號就能快速地分析下游依賴是否存在問題。
3、分散式 Tracing 助力根因定位
協議 Trace 同樣是無入侵、語言無關的。如果請求內容中存在分散式鏈路 TraceID,能自動識別出來,方便進一步下鑽到鏈路追蹤。應用層協議的請求、響應資訊有助於對請求內容、返回碼進行分析,從而知道具體哪個介面有問題。如需檢視程式碼級別或請求界別的詳情,可點選 Trace ID 下鑽到鏈路追蹤分析檢視。
4、開箱即用的告警功能
開箱即用的告警模板,各個不同層次全覆蓋,不需要手動配置告警,將大規模 Kubernetes 運維經驗融入到告警模板裡面,精心設計的告警規則加上智慧降噪和去重,我們能夠做到一旦告警就是有效的告警,並且告警裡面帶有關聯資訊,可以快速定位到異常實體。告警規則全棧覆蓋的好處是能及時、主動地將高風險事件報給使用者,使用者通過排查定位、解決告警、事後覆盤、面向失敗設計等一系列手段,最終逐步達成更好的系統穩定性。
5、網路效能監測
網路效能問題在 Kubernetes 環境中很常見,由於 TCP 底層機制遮蔽了網路傳輸的複雜性,應用層對此是無感的,這對生產環境定位丟包率高、重傳率高這種問題帶來一定的麻煩。Kubernetes 監測支援了 RTT、重傳&丟包、TCP 連線資訊來表徵網路狀況,下面以 RTT 為例,支援從名稱空間、節點、容器、Pod、服務、工作負載這幾個維度來看網路效能,支援以下各種網路問題的定位:
- 負載均衡無法訪問某個 Pod,這個 Pod 上的流量為 0,需要確定是否這個 Pod 網路有問題,還是負載均衡配置有問題;
- 某個節點上的應用似乎效能都很差,需要確定是否節點網路有問題,通過對別的節點網路來達到;
- 鏈路上出現丟包,但不確定發生在那一層,可以通過節點、Pod、容器這樣的順序來排查。
Kubernetes 可觀測性全景視角
有了上述產品能力,基於阿里巴巴在容器、Kubernetes 方面有著豐富且極具深度的實踐,我們將這些寶貴生產實踐歸納、轉化成產品能力,以幫助使用者更有效、更快捷地定位生產環境問題。使用這個排查全景圖可以通過以下方法:
- 大體結構上是以服務和 Deployment(應用)為入口,大多數開發只需要關注這一層就行了。重點關注服務和應用是否錯慢,服務是否連通,副本數是否符合預期等
- 再往下一層是提供真正工作負載能力的 Pod。Pod 重點關注是否有錯慢請求,是否健康,資源是否充裕,下游依賴是否健康等
- 最底下一層是節點,節點為 Pod 和服務提供執行環境和資源。重點關注節點是否健康,是否處於可排程狀態,資源是否充裕等。
1、網路問題
網路是 Kubernetes 中最棘手、最常見的問題,因為以下幾個原因給我們定位生產環境網路問題帶來麻煩:
- Kubernetes 的網路架構複雜度高,節點、Pod、容器、服務、VPC 交相輝映,簡直能讓你眼花繚亂;
- 網路問題排查需要一定的專業知識,大多數對網路問題都有種天生的恐懼;
- 分散式 8 大謬誤告訴我們網路不是穩定的、網路拓撲也不一成不變的、延時不可忽視,造成了端到端之間的網路拓撲不確定性。
Kubernetes 環境下場景的網路問題有:
- conntrack 記錄滿問題;
- IP 衝突;
- CoreDNS 解析慢、解析失敗;
- 節點沒開外網。(對,你沒聽錯);
- 服務訪問不通;
- 配置問題(LoadBalance 配置、路由配置、device 配置、網絡卡配置);
- 網路中斷造成整個服務不可用。
網路問題千千萬萬,但萬變不離其宗的是網路有其表徵其是否正常執行的”黃金指標“:
- 網路流量和頻寬;
- 丟包數(率)和重傳數(率);
- RTT。
下面的示例展示了因網路問題導致的慢呼叫問題。從 gateway 來看發生了慢呼叫,檢視拓撲發現調下游 product 的 RT 比較高,但是 product 本身的黃金指標來看 product 本身服務並沒有問題,進一步檢視兩者之間的網路狀況,發現 RTT 和重傳都比較高,說明網路效能惡化了,導致了整體的網路傳輸變慢,TCP 重傳機制掩蓋了這個事實,在應用層面感知不到,日誌也沒法看出問題所在。這時候網路的黃金指標有助於定界出問題,從而加速了問題的排查。
2、節點問題
Kubernetes 做了大量工作,儘可能確保提供給工作負載和服務的節點是正常的,節點控制器 7x24 小時地檢查節點的狀態,發現影響節點正常執行的問題後,將節點置為 NotReady 或不可排程,通過 kubelet 把業務 Pod 從問題節點中驅逐出去。這是 Kubernetes 的第一道防線,第二道防線是雲廠商針對節點高頻異常場景設計的節點自愈元件,如阿里雲的 node repairer:發現問題節點後,執行排水驅逐、置換機器,從而做到自動化地保障業務正常執行。即便如此,節點在長期使用過程中不可避免地會產生各種奇奇怪怪的問題,定位起來比較費時耗力。常見問題分類和級別:
針對這些繁雜的問題,總結出如下排查流程圖:
3、服務響應慢
造成服務響應非常多,場景可能的原因有程式碼設計問題、網路問題、資源競爭問題、依賴服務慢等原因。在複雜的 Kubernetes 環境下,定位慢呼叫可以從兩個方案去入手:首先,應用自身是否慢;其次,下游或網路是否慢;最後檢查下資源的使用情況。如下圖所示,Kubernetes 監測分別從橫向和縱向來分析服務效能:
- 橫向:主要是端到端層面來看,首先看自己服務的黃金指標是否有問題,再逐步看下游的網路指標。注意如果從客戶端來看呼叫下游耗時高,但從下游本身的黃金指標來看是正常的,這時候非常有可能是網路問題或者作業系統層面的問題,此時可以用網路效能指標(流量、丟包、重傳、RTT 等)來確定。
- 縱向:確定應用本身對外的延時高了,下一步就是確定具體哪個原因了,確定哪一步/哪個方法慢可以用火焰圖來看。如果程式碼沒有問題,那麼可能執行程式碼的環境是有問題的,這時可以檢視系統的 CPU/Memory 等資源是否有問題來做進一步排查。
4、應用/Pod 狀態問題
Pod 負責管理容器,容器是真正執行業務邏輯的載體。同時 Pod 是 Kubernetes 排程的最小單元,所以 Pod 同時擁有了業務和基礎設施的複雜度,需要結合著日誌、鏈路、系統指標、下游服務指標綜合來看。Pod 流量問題是生產環境高頻問題,比如資料庫流量陡增,當環境中有成千上萬個 Pod 時,排查流量主要來自哪個 Pod 就顯得特別困難。
總結
通過 eBPF 無侵入地採集多語言、多網路協議的黃金指標/網路指標/Trace,通過關聯 Kubernetes 物件、應用、雲服務等各種上下文,同時在需要進一步下鑽的時候提供專業化的監測工具(如火焰圖),實現了 Kubernetes 環境下的一站式可觀測性平臺。
如果您在架構雲原生監測的過程中,有以下困擾,那麼請毫不猶豫的聯絡我們一起探討:
- 對 Kubernetes 不熟悉,需要一整套完整的統一監測方案;
- Prometheus、Alertmanager、Grafana 等多個系統的資料割裂和上手難;
- 容器環境下應用、基礎設施埋點成本過高,正在尋找低成本或無侵入的解決方案;
本文為阿里雲原創內容,未經允許不得轉載。