使用 Ebpf 加速 Istio 數據平面
介紹:
服務網格是處理服務間通信的基礎設施層。它負責構成現代云原生應用程序的復雜服務拓撲來可靠地交付請求。Istio 是迄今為止最受歡迎的服務網格,因為它有非常豐富的功能。本文提出了一種優化默認數據平面的方法,并使用新的內核定制機制——EBPF 來加速它。這篇文章是三部曲的第一部分。它介紹了背景知識以更好地理解我們的想法,并概括了實現加速目標的一些關鍵步驟。
EBPF
Extended Berkeley Packet Filter (eBPF) 是 Linux 內核中一種高度靈活和高效的虛擬式構造,允許它以安全的方式在各種掛鉤點執行字節碼。它在很多 Linux 內核子系統中被使用,而且它是最突出的是網絡、跟蹤和安全的工具。
eBPF 的工作流程圖如上
PROGRAM TYPE
目前,有很不同的 Berkeley Packet Filter (BPF) 程序類型可用;下面的幾個小節解釋了兩種主要的聯網方式。
SOCK_OPS
BPF_PROG_TYPE_SOCK_OPS(簡稱sock_ops)允許這種類型的BPF程序訪問socket的一些字段(如IP地址、端口等)。它在網絡堆棧代碼的不同位置被多次調用。
此外,它使用現有的 BPF cgroups 基礎結構,因此程序可以附加到每個 cgroup 并具有完全繼承支持。我們使用 sock_ops 來捕獲滿足我們要求的套接字并相應地將它們添加到映射中。
SOCK_MSG
BPF_PROG_TYPE_SK_MSG(簡稱sock_msg)可以附加到sockhash map上,捕獲map中socket發送的每一個數據包,并根據msg的字段(如IP地址、端口等)確定其目的地。
HELPER FUNCTION
輔助函數使 BPF 程序能夠查詢核心內核定義的一組函數調用,以從內核檢索數據或將數據推送到內核。每種 BPF 程序類型的可用輔助函數可能不同。例如,與附加到 TC 層的 BPF 程序相比,附加到套接字的 BPF 程序只允許調用幫助程序的子集。下面解釋了一個輔助函數。
BPF_MSG_REDIRECT_HASH
此幫助程序用于在套接字級別實現策略的程序。如果消息 msg 被允許通過(即如果判定 eBPF 程序返回 SK_PASS),則使用哈希 key 將其重定向到 map(類型 BPF_MAP_TYPE_SOCKHASH)引用的套接字.
MAP
映射是駐留在內核空間中的高效鍵/值存儲??梢詮?BPF 程序訪問它們以保持多個 BPF 程序調用之間的狀態。它們也可以從用戶空間通過文件描述符訪問,并且可以與其他 BPF 程序或用戶空間應用程序任意共享。
SOCKHASH
Sockhash 和 Sockmap 是用于存儲內核打開的套接字的數據結構。Sockmap 當前由一個數組支持,并將鍵強制為四個字節。這適用于許多用例。但是,在 Sockhash 更合適的更大用例中,這已成為限制。當調用Sockhash上的Sock_msg程序重定向msg時,5元組查找鍵可以保證盡快找到對端socket。
ISTIO 中的數據平面
Istio 服務網格在邏輯上分為數據平面和控制平面??刂破矫婀芾砗团渲么硪月酚闪髁?。數據平面由一組部署為邊車的智能代理 (Envoy) 組成。這些代理中介和控制微服務之間的所有網絡通信,這是我們優化的重點。
邊車模式
在 pod 的啟動階段,一個 sidecar 容器和一個 init 容器被注入到應用程序清單中。流量從應用程序服務傳入和傳出這些 sidecar,開發人員無需擔心。Sidecar 代理通過在 pod 命名空間中設置 iptable 規則來獲取進出容器的入站和出站流量。
進入應用程序 pod 命名空間并獲取配置的 iptables,如下所示。
$ nsenter -t 4215 -n iptables -t nat -S
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-N ISTIO_INBOUND
-N ISTIO_IN_REDIRECT
-N ISTIO_OUTPUT
-N ISTIO_REDIRECT
-A PREROUTING -p tcp -j ISTIO_INBOUND
-A OUTPUT -p tcp -j ISTIO_OUTPUT
-A ISTIO_INBOUND -p tcp -m tcp --dport 80 -j ISTIO_IN_REDIRECT
-A ISTIO_IN_REDIRECT -p tcp -j REDIRECT --to-ports 15001
-A ISTIO_OUTPUT ! -d 127.0.0.1/32 -o lo -j ISTIO_REDIRECT
-A ISTIO_OUTPUT -m owner --uid-owner 1337 -j RETURN
-A ISTIO_OUTPUT -m owner --gid-owner 1337 -j RETURN
-A ISTIO_OUTPUT -d 127.0.0.1/32 -j RETURN
-A ISTIO_OUTPUT -j ISTIO_REDIRECT
-A ISTIO_REDIRECT -p tcp -j REDIRECT --to-ports 15001
ISTIO中APP和SIDECAR之間的流量
Pod 流量可以分為三類,按其方向定義:Inbound、Outbound 和 Envoy to Envoy。我們將在下面的小節中使用從客戶端服務到服務器服務的請求示例來解釋這三個類別。
Outbond
當應用程序向遠程服務發送請求消息時,該消息通過另一個應用程序(客戶端)創建的套接字作為內核空間中的套接字緩沖區(SKB)發送。它遍歷網絡堆棧,直到被 iptables 規則在 netfilter 級別攔截。它使用新目的地完成網絡堆棧中剩余的旅行路徑。套接字在 Envoy 創建的環回接口上偵聽具有靜態 ip 和端口 (127.0.0.1:15001) 的出站流量。
ENVOY TO ENVOY (同一主機)
在 Envoy 處理完請求消息后,它會相應地向托管服務器服務的 pod 發送一條消息。SKB
通過在服務器端網絡命名空間中設置的 iptables 規則攔截消息,并將其重定向到 Envoy 正在偵聽的默認端口 (pod_ip:15006)
以處理入站流量。
Inbond
Envoy 處理完請求消息后,使用環回地址(127.0.0.1)訪問服務器服務。SKB經過兩次網絡棧,最終到達服務器端。
加速的工作原理
套接字到套接字的重定向
eBPF 允許我們將 SKB 從套接字重定向到套接字,從而節省了遍歷網絡堆棧其余部分的成本。下圖說明了加速后的交通流量。
區分套接字對并將其添加到HASHMAP
Sock_ops 允許我們根據連接信息(例如 IP 地址、端口號等)來區分套接字。要從套接字重定向到套接字,我們需要連接的套接字對,然后將它們添加到 sockhash 映射中以備下一步使用。
哈希映射中套接字的重定向
SKB_ops 附加到一個哈希映射,捕獲映射中套接字發送的每個 SKB 并確定其目的地。要將 SKB 發送到對等套接字,請將目標的 4 元組信息(src ip、src 端口、dest ip、dest 端口)作為參數傳遞給重定向輔助函數。它在 sockhash 映射中搜索對等套接字并在它找到了。否則,它會像過去一樣繼續遍歷網絡堆棧。
概括
本文開頭介紹了eBPF及其組件,包括Program Type、Helper Function、Map。然后我們介紹了 Istio 中的幾個概念:控制平面和數據平面,sidecar 模式,以及它如何使用 iptables 抓取入站和出站流量。
此外,我們將從客戶端到服務器的流量路徑分為三類,并解釋了每一類中 SKB 發生了什么。最后,我們解釋了如何加速 app 和 sidecar 之間的流量。
參考:
·揭秘Istio的Sidecar注入模型:https ://istio.io/latest/blog/2019/data-plane-setup/
· BPF 和 XDP 參考指南:https://docs.cilium.io/en/latest/bpf/
原文:
https://01.org/blogs/xuyizhou/2021/accelerate-istio-dataplane-ebpf-part-1