利用 DeepFlow 為傳統 APM 開啟全棧追蹤能力

雲杉網路發表於2023-03-27

傳統 APM 聚焦在程式碼層面,不具備全棧多維度無盲點看問題的能力,同時由於插碼的阻礙往往難以覆蓋所有微服務,DeepFlow 依靠 eBPF 零程式碼修改採集全棧追蹤資料並聚合生成了呼叫關係,可以增強傳統 APM 的資料,大大縮短問題定界時間。對於已經使用傳統 APM 工具的使用者,可以考慮使用 DeepFlow 提供的 API 來增強應用依賴拓撲及呼叫追蹤,以獲得全棧資料追蹤能力。

本文以 SkyWalking 為例從落地實現角度來描述,如何將在傳統 APM 中整合 DeepFlow 的資料,增強傳統 APM 資料能力, 主要從以下兩個角度來:

  • 依賴拓撲:增強檢視某歷史時間範圍內服務(POD)到服務(POD)全棧路徑拓撲以及全景上下游拓撲。
  • 呼叫鏈追蹤:增強檢視某個應用 Span 對應系統 Span、網路 Span 時延消耗以及追蹤未插碼服務的能力。

開啟下文的閱讀之前,需要對 DeepFlow 目前已有的資料及術語有了解,下文預設讀者都有一定的認知。

01|全棧路徑拓撲-介面

增強檢視某歷史時間範圍內服務(POD)到服務(POD)應用和網路指標量能力,可以快速回答在某一段時間內端到端路徑是否存在瓶頸點,下面將結合 Skywalking 介紹產品 UI 介面如何融合

第一步:聚焦需要檢視的路徑(以下舉例透過拓撲圖路徑點選,大家可以根據環境的實際情況來定義使用流程)

圖片
聚焦需要檢視的路徑

圖片
點選全棧路徑拓撲

第二步:檢視全棧路徑拓撲(增強能力)

圖片
檢視全棧路徑拓撲

上圖拓撲中每一個節點都對應一個統計位置(tap_side),統計位置的說明參考 DeepFlow 官網的線上文件[1],以客戶端容器節點舉例說明具體的含義,表達是 cartservice 服務訪問 redis-cart 服務,在 cartservice 對應 POD 所在的容器節點上採集到的訪問資料,然後聚合的指標量。上圖檢視的指標量為響應時延,不難看出瓶頸在服務端容器網路,判斷過程如下:

  • 客戶端時延:④=204.31ms,為請求服務端的總時延,由以下幾部分組成

    • 客戶端容器網路:路徑①(也就是⑤-④),圖中所示為38.14us
    • 雲網路:路徑②(也就是⑥-⑤),圖中所示為273.13us
    • 服務端容器網路:路徑③(也就是⑦-⑥),圖中所示為204.25ms
    • 服務端:即圖中⑦,為372.83us

02|全棧路徑拓撲-API

結合 API 看看如何實現,DeepFlow 的所有資料均可透過 SQL API 獲取。

呼叫方輸入客戶端名稱、服務端名稱、指標量以及時間範圍作為 API 的搜尋條件即可獲得全棧路徑拓撲資料。

第一步:獲取 Skywalking 路徑的客戶端服務及服務端名稱,根據需求明確需要檢視的指標量及檢視的時間範圍

圖片
Skywalking 輸入

第二步:查詢 DeepFlow 獲取應用/網路統計位置的資料,SQL 呼叫參考 DeepFlow 官網的線上文件[2]

SELECT Avg(`request`), /* 需要檢視的指標量 */        pod_service_0,  /* 客戶端服務名稱,客戶端為 POD,則替換為 pod_0 */       tap_side,        pod_service_1 /* 服務端服務名稱,服務端為 POD,則替換為 pod_1 */FROM vtap_app_edge_port  /* 檢視應用指標使用 vtap_app_edge_port;檢視網路指標切換到 vtap_flow_edge_port */WHERE time>=1678760220 AND time<=1678762020 AND       pod_service_0='deepflow-server' AND  /* 過濾客戶端 */      pod_service_1='deepflow-server'   /* 過濾服務端 */GROUP BY pod_service_0,          tap_side,          pod_service_1,

第三步:根據返回資料繪製拓撲圖

每個 tap_side 對應一個節點,節點根據 c-app/app/c-p/c/c-nd/c-hv/c-gw-hv/c-gw/local/rest/s-gw/s-gw-hv/s-hv/s-nd/s/s-p/s-app 從左到右排序,每個節點獨立顯示指標資料。

03|全景上下游拓撲-介面

增強某節點檢視全景上下游拓撲的能力,可快速發現未插碼範圍內被誰訪問了(比如追蹤上游的 Nginx 閘道器、安全策略未防住的訪問等等),以及自身訪問了誰,下面也將結合 Skywalking 介紹產品 UI 介面如何融合

第一步:聚焦需要檢視的節點(以下舉例透過拓撲圖節點點選,大家可以根據環境的實際情況來定義使用流程)

圖片
點選全景上下游拓撲

第二步:檢視全景上下游拓撲(增強能力)

圖片
檢視全景上下游拓撲

上圖為 tikcet-web 服務的全景上下游拓撲,其中 ① 是未插碼的 ingress-nginx-controller 服務,表明 ticket-web 服務對外都是透過 ingress 來訪問的,其中 ② 為未插碼的 kube-dns 服務,經常訪問服務慢,可能是因為 DNS 解析慢,而在應用拓撲是無法看出來此資訊的。

04|全景上下游拓撲-API

呼叫方輸入服務名稱、指標量以及時間範圍作為 API 的搜尋條件即可獲得全景上下游拓撲資料,需要兩次呼叫的 DeepFlow API,分別獲取到上游和下游的資料如下:

獲取上游資料

SELECT Avg(`request`), /* 需要檢視的指標量 */        pod_service_0,  /* 客戶端服務名稱,客戶端為 POD,則替換為 pod_0 */       tap_side,        pod_service_1 /* 服務端服務名稱,服務端為 POD,則替換為 pod_1 */FROM vtap_app_edge_port  /* 檢視應用指標使用 vtap_app_edge_port;檢視網路指標切換到 vtap_flow_edge_port */WHERE time>=1678760220 AND time<=1678762020 AND       pod_service_1='deepflow-server'   /* 需要檢視上游資料的服務 */GROUP BY pod_service_0,          tap_side,          pod_service_1,

獲取下游資料

SELECT Avg(`request`), /* 需要檢視的指標量 */        pod_service_0,  /* 客戶端服務名稱,客戶端為 POD,則替換為 pod_0 */       tap_side,        pod_service_1 /* 服務端服務名稱,服務端為 POD,則替換為 pod_1 */FROM vtap_app_edge_port  /* 檢視應用指標使用 vtap_app_edge_port;檢視網路指標切換到 vtap_flow_edge_port */WHERE time>=1678760220 AND time<=1678762020 AND       pod_service_0='deepflow-server'   /* 需要檢視下游資料的服務 */GROUP BY pod_service_0,          tap_side,          pod_service_1,

05|呼叫鏈追蹤-產品

在開始介紹如何增強呼叫追蹤的資料之前,先結合一張圖說明一些後續要使用到的術語

圖片
資料介紹圖

圖中 A 表示應用 Span(來源傳統 APM);S 表示網路 Span(來源 DeepFlow);N 表示網路 Span(來源 DeepFlow)圖中黑色部分為發起全棧呼叫追蹤的的應用 Span,後續統稱為 應用 Span Y圖中藍色部分為透過 應用 Span Y 追蹤的路徑中的系統和網路 Span圖中綠色部分為透過 應用 Span Y 追蹤的下游未插碼的 Span圖中紅色部分為透過 應用 Span Y 追蹤的上游未插碼的 Span

接下來將分別來討論上圖中藍色/綠色/紅色部分如何基於 SkyWalking 產品做 UI 融合(注:以下產品 UI 部分僅為示意圖):

第一步:聚焦需要檢視的應用 Span(以下舉例透過點選 Span,大家可以根據環境的實際情況來定義使用流程)

圖片
聚焦需要檢視的路徑

圖片
點選全棧呼叫追蹤

第二步:檢視全棧呼叫拓撲(增強能力)

圖片
檢視全棧呼叫拓撲

06|呼叫鏈追蹤-API

接下來看下結合 DeepFlow 的 SQL API 如何實現,基於前面的術語介紹圖,可知傳統 APM 結合 DeepFlow 的資料來完成全棧呼叫追蹤的能力,需要分藍色、綠色和紅色三部分來實現,接下來將分開介紹這三部分的資料實現。

藍色部分:根據 應用 Span 的 TraceID + SpanID 追蹤 DeepFlow 的系統 Span 和網路 Span,可以方便的檢視某次呼叫在系統和網路分佈消耗的時延,快速定界問題。可以透過 TraceID、SpanID 作為搜尋條件獲取 DeepFlow 的系統和網路 Span

圖片
藍色部分-追蹤圖

SELECT response_duration,       start_time,       end_time,       resource_gl0_0, /* 客戶端 */       resource_gl0_1, /* 服務端 */       tap_port_type,  /* eBPF、NIC ... */       tap_port,       /* NIC Name */       trace_id,       span_idFROM l7_flow_logWHERE trace_id = 'c5ad367da7ed41fc97921d91a0584bd8.63.16620935428909473' AND      span_id = 'e05ee7a06d674085a16dfea36ed11b98.169.16620935428971714-2' AND /* 非必須,精確搜尋 */      time >= 1662093572 AND time <= 1662095372 /* 加速搜尋 */

此部分的細節部分可以參考DeepFlow 讓 SkyWalking 分散式追蹤無盲點[3]。
紅色部分:增強某個應用 Span 上游的 Span,對於插碼範圍以外(之前)的部分,例如追蹤出來從未插碼的客戶端 Span

圖片
紅色部分-追蹤原理解釋圖

對於這部分資料的追蹤,需要分幾個步驟來逐一進行關聯

  • ① 根據應用 Span Y 的 TraceID + SpanID 追蹤 DeepFlow 的系統 Span,此時可能會得到多個系統 Span,只需要獲取與應用 Span Y緊鄰的系統 Span X繼續往下追蹤即可(可透過總時延最長來判斷)
  • ② 獲取系統 Span X的 syscall_trace_id_request 作為其他系統 Span 的搜尋條件,得到系統 Span Z
SELECT response_duration,  /* SELECT 欄位可以根據需求自定義即可*/       l7_protocol,       Enum(request_type),       request_resource,       process_kname_0,       process_kname_1,       tap_side,       req_tcp_seq,        resp_tcp_seq,       Enum(auto_instance_type_0) AS `client_Enum(auto_instance_type_0)`,       auto_instance_0,         Enum(auto_instance_type_1) AS `server_Enum(auto_instance_type_1)`,        auto_instance_1, FROM l7_flow_log  WHERE time>=1678764261 AND /*追蹤開始時間,建議設定比系統 Span X 的開始時間早 3min*/      time<=1678767861 AND /*追蹤結束時間,建議設定比系統 Span X 的結束時間晚 3min*//      (syscall_trace_id_request=16787489195430278) /* 16787489195430278 為 系統 Span Y 的 syscall_trace_id_request */ORDER BY `end_time` 

③ 獲取系統 Span Z 的 req_tcp_seq/resp_tcp_seq 作為其他系統 Span 和網路 Span 的搜尋條件,得到網路 Span Z.1/Z.2 以及系統 Span Q,此處邏輯特別注意:

req_tcp_seq !=0 & resp_tcp_seq !=0 則需要同時滿足 req_tcp_seq 和 resp_tcp_seq;如果其中一個為 0,則任意滿足一個即可
SELECT response_duration,  /* SELECT 欄位可以根據需求自定義即可*/       l7_protocol,       Enum(request_type),       request_resource,       process_kname_0,       process_kname_1,       tap_side,       req_tcp_seq,        resp_tcp_seq,       Enum(auto_instance_type_0) AS `client_Enum(auto_instance_type_0)`,       auto_instance_0,         Enum(auto_instance_type_1) AS `server_Enum(auto_instance_type_1)`,        auto_instance_1, FROM l7_flow_log  WHERE time>=1678764261 AND       time<=1678767861 AND       (type=2 AND       req_tcp_seq=3575241005 AND /* 3575241005 為系統 Span Z 的 req_tcp_seq*/      resp_tcp_seq=995863176) /* 995863176 為系統 Span Z 的 resp_tcp_seq*/ORDER BY `end_time` 

④ 接下來可繼續追蹤系統 Span Q 的上游系統 Span,這裡將分兩種情況,如果上游的系統 Span 與系統 Span Q 在同一個執行緒,則重複步驟 [2]/[3] 即可,如果在不同執行緒/程式中,目前僅支援閘道器設定了 X-Request-ID 的情況下繼續追蹤,獲取系統 Span Q的 x-request-id 作為查詢其他系統 Span 和網路 Span 的搜尋條件,得到其上游的系統 Span M

SELECT response_duration,  /* SELECT 欄位可以根據需求自定義即可*/       l7_protocol,       Enum(request_type),       request_resource,       process_kname_0,       process_kname_1,       tap_side,       req_tcp_seq,        resp_tcp_seq,       Enum(auto_instance_type_0) AS `client_Enum(auto_instance_type_0)`,       auto_instance_0,         Enum(auto_instance_type_1) AS `server_Enum(auto_instance_type_1)`,        auto_instance_1, FROM l7_flow_log  WHERE time>=1678764261 AND       time<=1678767861 AND       x_request_id=6e903947-5ef0-4c63-91a8-a2a599171633 /* 6e903947-5ef0-4c63-91a8-a2a599171633 為系統 Span Q 的 x_request_id*/ORDER BY `end_time` 

⑤ 到此,已經根據上述步驟追蹤得到所有的上游 Span,接下來將確定父子關係,可直接根據總的響應時延,按從大到小降序排列即可

綠色部分:增強某個應用 Span 下游的 Span,對於插碼範圍以外(之後)的部分追蹤,例如追蹤出來未插碼的服務端 Span(DNS),此追蹤過程與紅色部分非常相似,僅步驟 ② 中的syscall_trace_id_request換成syscall_trace_id_response即可,此處不在贅述。

圖片
綠色部分-追蹤圖

07|什麼是 DeepFlow

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

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

訪問 DeepFlow Demo[5],體驗高度自動化的可觀測性新時代。
參考資料

[1] 統計位置的說明參考 DeepFlow 官網的線上文件: https://deepflow.io/docs/zh/auto-metrics/metrics-without-inst...

[2] SQL 呼叫參考 DeepFlow 官網的線上文件: https://deepflow.io/docs/zh/server-integration/query/sql/

[3] DeepFlow 讓 SkyWalking 分散式追蹤無盲點: https://deepflow.io/blog/007-skywalking-distributed-tracing-w...

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

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

相關文章