基於 eBPF 的度自動化可觀測性實踐

語言: CN / TW / HK

本文為 DeepFlow 在首屆中國 eBPF 大會上的線上演講實錄。

大家好!我是來自雲杉網路的向陽,負責公司的雲原生可觀測性產品 DeepFlow。今天很高興能給大家分享我們基於 eBPF 的一些創新實踐,我們的產品已經有六年曆史,並且開源,希望能為雲原生應用開發者實現可觀測性帶來高度自動化的全新體驗

歡迎大家預約近期“雲原生可觀測性分享會”,分享 DeepFlow 使用 eBPF 為分散式追蹤帶來的革命性創新。藉助 eBPF 的零侵擾機制,開發者無需修改程式碼、無需重新發布、無需重啟服務,即可實現全景、全棧的分散式追蹤能力,覆蓋各類語言的微服務及基礎設施。

01|歷史和現狀

最近可觀測性是一個很火的名詞,這裡我也想稍微介紹一下它的歷史。追溯歷史我們會發現,實際上可觀測性是作為保障複雜系統可控的必要條件。61 年前,美國提出載人登月的豪言壯語,但屆時如何將高度複雜的載人飛船平穩地送到月球還只是人類的一個夢想。8 年之後,受益於 Rudolf Kalman 教授開創的可觀測性理論,人類終於完成了登月壯舉。Kalman 教授指出,一切系統具有可觀測性當且僅當:針對所有的狀態向量及控制向量,都可以在有限時間內,只根據輸出訊號來識別當前的狀態。注意這裡面的關鍵:外部輸出、內部狀態、有限時間。

可觀測性的歷史

可觀測性的歷史

時間回到 2022 年,現在的雲原生應用正是一個複雜度急劇增長的 IT 系統。隨著微服務的拆分,單個服務變得越來越簡單,服務釋出越來越快速,業務中的通用邏輯逐漸解除安裝至服務網格等基礎設施,開發語言和框架越來越自由。這些趨勢使得一方面服務的資料急劇增長,但更棘手的問題是連線服務的基礎設施路徑變得越來越長,路徑數量越來越多。開發者們發現,用於採集指標、追蹤、日誌三大支柱訊號的已有方案几乎都聚焦在業務程式碼和框架程式碼層面,而對於 N^2 複雜度的程序、Sidecar、節點、宿主機、閘道器、資料庫、訊息佇列就像黑盒一樣,雖然能暴露一些有限的指標和日誌,但是和應用是割裂的,應用開發者越來越難以觀測 IT 系統的執行狀況,其中面臨的挑戰也正是可觀測性理論所指出的:1)微服務的動態性對實時性提出的高要求;2)路徑的複雜性對多維度提出的高要求;3)服務實現的複雜性對零侵擾的提出的高要求

雲原生應用是一個複雜系統

雲原生應用是一個複雜系統

DeepFlow 就是希望來解決雲原生應用可觀測性問題的,希望能讓開發者輕鬆實現全棧可觀測性。下圖左上角是一個非常“簡單”的複雜雲原生業務系統,它是 OpenTelemetry 專案的官方 Demo,是一個用數十種語言實現的高速迭代的電商應用。DeepFlow 使用 OpenTelemetry、Prometheus 等標準化的採集方式,實現應用程式碼層面的可觀測性,同時使用 eBPF 技術,創新的實現了雲原生環境中高度自動化的全棧可觀測性,得益於 eBPF 的零侵擾特性,不需要開發人員插碼、重啟程序、修改配置。今天我的分享主要聚焦在 eBPF 的部分,主要介紹 DeepFlow 三個方面的能力:

  1. 從 cBPF 到 eBPF 的 AutoMetrics 能力,實現面向微服務的動態應用拓撲;

  2. 從 InProcess 到 Distributed 的 AutoTracing 能力,實現面向使用者請求的零侵擾分散式追蹤;

  3. 從 kprobe 到 uprobe 的 AutoLogging 能力,實現面向事件的細粒度回溯日誌。


DeepFlow 讓雲原生開發者輕鬆實現全棧可觀測性

02|AutoMetrics

首先我們來看一下 DeepFlow 是如何使用 eBPF 的。下面這張圖描述了雲原生應用的執行環境,應用程序執行在 Pod 內,可能伴隨著例如 Envoy 之類的 Service Mesh Sidecar,通過 iptables、ipvs 等元件接入到虛擬機器 Overlay 網路中,繼續通過 OvS、Linux Bridge 等元件接入到宿主機 Underlay 網路中,還可能會由一系列四七層閘道器為其服務。DeepFlow 同時用到了 cBPF 和 eBPF 的能力,使得能覆蓋逐跳路徑實現全棧可觀測性。第一步是採集,我們會從 cBPF 採集網絡卡流量、eBPF kprobe/tracepoint 採集 Syscall 資料、eBPF uprobe/USDT 採集 Function 資料。拿到這些資料後,第二步是聚合,從 Raw Data 中聚合得到網路流和應用會話,以降低資料量。第三步繼續從 Flow 和 Session 聚合生成全棧效能指標。第四步會從網路流和應用會話中提取結構化日誌,包括 FlowLog 和 RequestLog,其中後者可認為就是我們常說的 Span。最後第五步,利用一系列演算法將 Span 關聯生成分散式追蹤,這一步也是 DeepFlow 中一項顛覆性的創新

DeepFlow 如何使用 eBPF

DeepFlow 如何使用 eBPF

那麼下面我來介紹 DeepFlow 的第一部分能力:從 cBPF 到 eBPF 的 AutoMetrics 能力,實現面向微服務的動態應用拓撲。也就是上圖中的第三步。

我們來看一下效果,AutoMetrics 能力能做什麼呢?我們使用者大量反饋的第一個價值是自動繪製微服務動態應用拓撲,知曉任意微服務的上下游訪問關係。雲原生環境下業務混部共享一個伺服器、容器 SNAT 等是普遍現象,以往我們需要靠業務插碼解決的事情,現在通過 DeepFlow 可以很快速完成。比如我們一個網際網路使用者,使用 DeepFlow 從數萬個 Pod 中快速定位了對它的 RDS 造成最大訪問量的 Pod、服務乃至開發團隊。就算在應用程式碼中插碼,有些問題也難以回答,比如我們的金融使用者信用卡核心業務上雲受阻,使用 DeepFlow 快速發現了兩個服務之間 API 閘道器是效能瓶頸,而這個“透明”的服務通常是被開發者所忽略的。

我在訪問誰、誰在訪問我

我在訪問誰、誰在訪問我

除了拓撲本身之外,DeepFlow 對拓撲中每一條路徑的全棧觀測能力是另一個亮點。下圖左下角是兩個 Pod 之間最普通的訪問路徑,這裡面的程序、Pod、Node、KVM 宿主機都可能引發應用效能問題。DeepFlow 由於全棧覆蓋了服務之間的全路徑,能夠提供沿途每一跳的豐富性能指標。例如應用效能的請求/時延/異常,即我們常說的 RED 三大黃金指標;系統性能的新建/活躍/建連異常;網路效能的建連時延/系統時延/資料時延/吞吐/零窗/重傳/載荷長度等。我們支援對主流的應用協議進行識別,包括 HTTP/HTTPS、Dubbo/gRPC、MySQL/PostgreSQL/Redis、Kafka/MQTT、DNS 等。使用這個能力,DeepFlow 的使用者能快速定位應用請求在哪裡出問題了。例如我們一個網際網路使用者,快速定位了兩個服務之間 K8s 網路效能瓶頸造成的應用時延;一個金融使用者,快速定位了 ARP 異常導致的 Pod 概率性長時間無法 Ready;一個系統軟體使用者,快速定位了客戶端沒有及時收包導致的 gRPC 超時。得益於 eBPF 的零侵擾特性,這些定位過程不需要對線上應用做任何改變。

DeepFlow 中的全棧訪問路徑

DeepFlow 中的全棧訪問路徑

剛才還只是最簡單的場景,而在專有云網路中,訪問路徑會更加複雜,DeepFlow 的能力也更加豐富。DeepFlow 與阿里專有云、騰訊 TCE、華為 HCS 已經合作超過三年,進行了深度的適配。雲網絡中最複雜的就是 NFV 區域,可能存在十餘種雲網關、四五種種隧道封裝協議、十餘種通訊端點,組合起來形成上百種穿越 NFV 區的路徑。以往大家在排查應用問題時只能逐個抓包確認,過程非常痛苦,技能養成靠著老師傅傳幫帶。基於閘道器區 cBPF 獲取到的流量,DeepFlow 將應用訪問穿越閘道器區的整個路徑智慧推匯出來,無論中間經歷過多少次 SNAT、DNAT、FULLNAT,都能關聯至上一頁我講到的雲原生應用訪問路徑中。這裡的路徑追蹤方法,等會在第二部分的分散式追蹤中會做一個介紹。下圖右下角是我們基於 NAT 追蹤能力繪製的流量拓撲和鏈路拓撲。利用這個能力我們也有很多使用者案例,我們一個金融使用者,使用 DeepFlow 解決了困擾雲廠商工程師多日的路由環路,它造成了某個服務上雲下雲時延週期性飆升;另一個金融使用者快速定位了一個 NFV 閘道器例項對一組服務流量丟包,導致的客戶端頻繁重試。

追蹤專有云中 NFV 閘道器區域的訪問路徑

追蹤專有云中 NFV 閘道器區域的訪問路徑

03|AutoTracing

剛才介紹的是指標方面的能力,下面來介紹一下從 InProcess 到 Distributed 的 AutoTracing 能力,實現面向使用者請求的零侵擾分散式追蹤。這是 DeepFlow 中一項顛覆性的創新。

我們以一個 Demo 為例,左下角是 Istio 官方的 Bookinfo Demo,包含五種語言實現的微服務和 Sidecar,服務存在多個版本體現了迭代速度之快,所有服務使用 Service Mesh 連線。以往為了實現這樣一個簡單應用的分散式追蹤,我們不得不在各種語言和框架中進行打樁和插碼,利用 OpenTelemetry、SkyWalking 技術繪製分散式追蹤火焰圖。而現在大家看到的這張火焰圖是 DeepFlow 完全基於 eBPF 的 AutoTracing 能力得到的,覆蓋了一次使用者請求的整個生命週期,以及每一個微服務呼叫從客戶端程序到服務端程序的全路徑,而所有這些結果不依賴對應用做任何插碼、重啟、配置。相信雲原生開發者看到這個結果時是非常興奮的。

對 Istio Bookinfo Demo 的零侵擾分散式追蹤

對 Istio Bookinfo Demo 的零侵擾分散式追蹤

基於這個火焰圖,我們來詳細的展示一下 DeepFlow 的 AutoTracing 能力。首先 AutoTracing 是零插碼的,它不需要修改應用程式碼,不需要向 HTTP Header 中注入 TraceID、SpanID。這張火焰圖共由 38 個 Span 組成,包括 24 個 eBPF Span 和 14 個 cBPF Span,覆蓋了一次應用請求的全鏈路。火焰圖中覆蓋了 Java、Python、Ruby、Node.js、C、C++ 六種語言實現的微服務和閘道器,全部都能自動呈現在火焰圖中。對於我們一直提到的全棧能力,這裡也放大兩個區域看看。我們看到一個呼叫從客戶端程序,經過 Pod 網絡卡、Node 網絡卡,甚至是 KVM、NFVGW 等到達服務端程序的全過程,無論中間路徑如何複雜,新增過幾層隧道、做過幾次 NAT,都能清晰的展現在火焰圖中,快速判斷服務之間的效能問題是由哪個環節導致,並且結合之前介紹的 DeepFlow 指標體系,火焰圖可以快速關聯到應用、系統、網路各個層面的指標。再來看看另一個區域,我們看到一個呼叫從進入 Pod 被 Envoy 劫持,到被微服務接收,到微服務繼續請求下游並被 Envoy 劫持,在一個 Pod 內的全棧路徑也能非常清晰的體現出來。除此之外,我們也能發現以往應用程式碼插樁難以覆蓋的一些基礎服務,例如微服務對 DNS 解析、磁碟 IO 等過程在這個火焰圖中也體現了出來。基於這樣的全棧分散式追蹤能力我們也有很多使用者案例,例如一個網際網路使用者快速定位客戶端慢而服務端不慢的經典扯皮問題。

DeepFlow AutoTracing

DeepFlow AutoTracing

AutoTracing 是 DeepFlow 中一個開創性的能力,這個能力基於 eBPF,它與大家所熟知的一個程序內部的 Trace 不同,解決的是微服務分散式呼叫的追蹤問題。這裡我嘗試簡單的介紹一下我們的方法。實際上我們只需要解決兩個子問題:

  1. 如何追蹤一個服務前後的入出請求;

  2. 如何追蹤兩個服務之間的網路路徑。

對於第一個問題,又分為執行緒內追蹤、跨執行緒追蹤、跨協程追蹤。DeepFlow 利用 ThreadID ,以及為每個 Request 生成的 SyscallTraceID 關聯一個執行緒內的入向和出向請求,完美的解決了同線程的追蹤問題;跨執行緒有些複雜,基於為每個會話生成的 SessionID 和包頭中提取的 X-Request-ID,我們目前解決了一部分場景,相信未來能搞定越來越多的非同步呼叫;對於 Golang/Erlang 等協程語言同樣也非常困難,我們追蹤了 CoroutineID 之間的關係,這部分程式碼也正在合入中,預計在我們的 v6.2.0 版本中和大家見面。

那麼接下來如何追蹤兩個服務之間的網路路徑呢,簡單來講使用了 TCP Seq 序列號,並結合時間視窗等資訊。雖然原理簡單,但其中有很多細節的工程問題需要處理,以實現使用者函式呼叫、系統函式呼叫、網路流量的關聯。時間關係沒法展開,如果大家感興趣歡迎到 DeepFlow 社群群中交流。

DeepFlow 如何實現分散式追蹤

DeepFlow 如何實現分散式追蹤

04|AutoLogging

最後我們來介紹一下 DeepFlow 中的日誌能力,從 kprobe 到 uprobe 的 AutoLogging 能力,實現面向事件的細粒度回溯日誌

由於我們已經從 cBPF 和 eBPF 中拿到了所有微服務沿途的全棧資料,通過 Flow 和 Session 聚合,我們能提取出標準化、結構化的回溯日誌。例如對應用呼叫日誌我們能提取請求域名、Endpoint、請求 ID、響應碼、響應結果,也能提取 HTTP Header 中常見的客戶端真實 IP、UserAgent、Referer 等欄位。對於已經在應用內插碼追蹤的場景,也能從 cBPF 和 eBPF 資料中提取出 TraceID、SpanID 等欄位以關聯應用 Span。協議解析和欄位提取的能力我們也正在開發通過 WASM 和 LUA 提供外掛式的擴充套件能力,使得使用者可以解析和提取私有協議欄位。除了呼叫日誌以外,我們也採集了網路流日誌。在企業版中我們還支援以 1/10 的儲存代價壓縮儲存所有 TCP 包頭,以及壓縮儲存全包 PCAP 檔案。

這方面也有很多我們的使用者案例,例如政府使用者使用 DeepFlow 流日誌替代全包儲存,回溯查詢的速度和儲存時長都實現了數量級的提升;金融使用者使用 TCP 包頭時序圖快速發現了雲網關轉發 SYN 報文時延大導致的應用效能衰減。

DeepFlow AutoLogging

DeepFlow AutoLogging

下圖是 DeepFlow 當前的所有 eBPF hook 點,GitHub 上直接搜尋 DeepFlow 即可找到我們的倉庫,這裡也列出了幾條命令幫助大家檢視 DeepFlow 目前使用到的主要 uprobe、kprobe、tracepoint hook 點。

DeepFlow eBPF Hook 點

DeepFlow eBPF Hook 點

05|資料的標準化

好了,講完了指標、追蹤、日誌,最後來給大家介紹一下 DeepFlow 中的標籤注入能力。大家可能也關注到了前面我所講的內容中,DeepFlow 能以非常豐富的維度展現資料,我們通過 AutoTagging 機制為所有的可觀測性訊號注入豐富的標籤,包括資源池、雲資源、網路資源、容器服務、應用等相關的標準標籤,和 K8s Label、Annotation、ENV 等開發者自定義的標籤。依靠這些標籤我們能快速的在不同型別的可觀測性訊號之間切換,無論是 eBPF 採集到的資料,還是通過 Prometheus、OpenTelemetry 採集到的資料,完全消除不同資料來源之間的孤島。資料的標準化也有助於進一步的消費,DeepFlow 的使用者消費這些資料時,不再需要考慮複雜的標準化過程,我相信這也是實現智慧化的前提

DeepFlow AutoTagging 及 SmartEncoding

DeepFlow AutoTagging 及 SmartEncoding

大家可能會比較好奇,插入這麼多標籤是否會造成大量的資源消耗,這裡就要介紹 DeepFlow 的 SmartEncoding 機制了,簡單來講通過標籤和資料的分離採集、標籤的數值編碼、以及自定義標籤的讀時關聯,我們能將標籤寫入的資源消耗降低 10~50 倍。這裡有一些資料可以看一下,DeepFlow 預設使用 ClickHouse 儲存資料,在 SmartEncoding 的加持下,標註 Tag 的 CPU 和磁碟消耗相比 LowCard 儲存或直接儲存有一個數量級的優化,而由於自定義 Tag 不會隨資料寫入,在通常的場景下整體寫入資源消耗可降低 50 倍。因此實際上 DeepFlow 實現了 Tag without Limit,可以讓開發者盡情的注入豐富的標籤,充分挖掘資料的價值

最後,簡單介紹一下 DeepFlow 的軟體架構。DeepFlow 希望讓雲原生開發者能夠輕鬆實現全棧可觀測性,這個產品我們做了六年,今年七月份正式開源,目前已經是 CNCF Cloud Native Landscape ProjecteBPF Landscape Project。從下圖中可以看到 DeepFlow 社群版的架構非常精煉,主要包括 Agent 和 Server 兩個程序,前者是 Rust 實現的,後者是 Golang 實現的。Agent 使用 eBPF 的能力實現 AutoMetrics、AutoTracing、AutoLogging 能力,並基於 WASM 提供可程式設計性。Server 使用 AutoTagging 和 SmartEncoding,基於 Agent 採集到的元資料,向所有可觀測性訊號中高效能的注入標準化的標籤。除了 eBPF 之外,DeepFlow 還使用 Prometheus、OpenTelemetry、SkyWalking 等開放 Agent 採集資料,並且和 eBPF 的資料進行關聯。向上我們提供了易於使用的 SQL API、Grafana Datasource 和 Query Editor,未來也會支援 PromQL 等流行的查詢語言。

DeepFlow 社群版軟體架構

DeepFlow 社群版軟體架構

如果大家對 DeepFlow 感興趣,可以掃碼加入我們的開源社群微信群,希望能給你帶來全新的可觀測性體驗。謝謝大家!

06|什麼是 DeepFlow

DeepFlow[1] 是一款開源的高度自動化的可觀測性平臺,是為雲原生應用開發者建設可觀測效能力而量身打造的全棧、全鏈路、高效能資料引擎。DeepFlow 使用 eBPF、WASM、OpenTelemetry 等新技術,創新的實現了 AutoTracing、AutoMetrics、AutoTagging、SmartEncoding 等核心機制,幫助開發者提升埋點插碼的自動化水平,降低可觀測性平臺的運維複雜度。利用 DeepFlow 的可程式設計能力和開放介面,開發者可以快速將其融入到自己的可觀測性技術棧中。

GitHub 地址:https://github.com/deepflowys/deepflow

訪問 DeepFlow Demo[2],體驗高度自動化的可觀測性新時代。

參考資料

[1] DeepFlow: https://github.com/deepflowys/deepflow

[2] DeepFlow Demo: https://deepflow.yunshan.net/docs/zh/install/overview/