
譯者 | 陳豪
策劃 | 云昭
Extended Berkeley Packet Filter ( eBPF ) 是 Linux 內(nèi)核的一個相對較新的特性,它讓許多 DevOps 專業(yè)人士、SRE 和工程師興奮不已。eBPF 甚至可以與標(biāo)準(zhǔn)的Linux iptables 相提并論。但是,它真能成為滿足所有 Linux 內(nèi)核需求的“一站式商店”呢?
eBPF正當(dāng)時
過去,對內(nèi)核進(jìn)行更改是很困難的。開發(fā)者雖然可以調(diào)用 API 來獲取數(shù)據(jù),但卻無法影響內(nèi)核內(nèi)部的執(zhí)行代碼。相反,你必須向 Linux 社區(qū)提交補(bǔ)丁并等待其獲得批準(zhǔn)。使用 eBPF,可以將程序加載到內(nèi)核中,并在例如看到某個數(shù)據(jù)包或發(fā)生其他事件時指示內(nèi)核執(zhí)行程序。
eBPF 是Linux內(nèi)核中提供的一項功能,它允許你在內(nèi)核中運(yùn)行虛擬機(jī)。該虛擬機(jī)允許你安全地將程序加載到內(nèi)核中以自定義其操作。為什么這很重要?
使用 eBPF,內(nèi)核及其行為變得高度可定制,而不是固定的。在適當(dāng)?shù)那闆r下使用時,這可能是非常有益的。
典型用例
eBPF 有幾個典型用例,包括流量控制、創(chuàng)建網(wǎng)絡(luò)策略、連接時負(fù)載平衡和可觀測性。
流量控制
如果沒有 eBPF,數(shù)據(jù)包在到達(dá)最終目的地的途中會使用標(biāo)準(zhǔn)的 Linux 網(wǎng)絡(luò)路徑。如果一個數(shù)據(jù)包出現(xiàn)在 A 點,并且你知道該數(shù)據(jù)包需要到達(dá) B 點,你可以通過將其直接發(fā)送到 B 點來優(yōu)化 Linux 內(nèi)核中的網(wǎng)絡(luò)路徑。使用 eBPF,你可以利用額外的上下文來使內(nèi)核中的這些更改使數(shù)據(jù)包繞過復(fù)雜的路由并簡單地到達(dá)其最終目的地。
這在擁有大量網(wǎng)絡(luò)的 Kubernetes 容器環(huán)境中尤其重要。(除了主機(jī)網(wǎng)絡(luò)堆棧,每個容器都有自己的迷你網(wǎng)絡(luò)堆棧。)當(dāng)流量進(jìn)入時,它通常被路由到容器堆棧,并且必須經(jīng)過復(fù)雜的路徑,因為它從主機(jī)堆棧到達(dá)那里。可以使用 eBPF 繞過此路由。
創(chuàng)建網(wǎng)絡(luò)策略
創(chuàng)建網(wǎng)絡(luò)策略時,有兩種情況可以使用 eBPF:
1. eXpress 數(shù)據(jù)路徑 (XDP) –當(dāng)原始數(shù)據(jù)包緩沖區(qū)進(jìn)入系統(tǒng)時,eBPF 為你提供了一種有效的方法來檢查該緩沖區(qū)并快速決定如何處理它。
2. 網(wǎng)絡(luò)策略——eBPF 允許你有效地檢查數(shù)據(jù)包并為 pod 和主機(jī)應(yīng)用網(wǎng)絡(luò)策略。
連接時負(fù)載平衡
在 Kubernetes 中對服務(wù)連接進(jìn)行負(fù)載平衡時,端口需要與服務(wù)通信,因此必須進(jìn)行網(wǎng)絡(luò)地址轉(zhuǎn)換 (NAT)。一個數(shù)據(jù)包被發(fā)送到一個虛擬 IP,該虛擬 IP 將其轉(zhuǎn)換為支持該服務(wù)的 pod 的目標(biāo) IP;pod 然后響應(yīng)虛擬 IP,返回的數(shù)據(jù)包被翻譯回源。
使用 eBPF,你可以通過使用已加載到內(nèi)核中的 eBPF 程序并在連接源進(jìn)行負(fù)載平衡來避免這種數(shù)據(jù)包轉(zhuǎn)換。由于目標(biāo)網(wǎng)絡(luò)地址轉(zhuǎn)換 (DNAT) 不需要在數(shù)據(jù)包處理路徑上進(jìn)行,因此消除了服務(wù)連接的所有 NAT 開銷。
可觀測性
收集統(tǒng)計信息和深入調(diào)試內(nèi)核是 eBPF 可用于可觀測性的兩種有用方式。eBPF 程序可以附加到內(nèi)核中的許多不同函數(shù),提供對函數(shù)正在處理的數(shù)據(jù)的訪問,同時還允許修改該數(shù)據(jù)。例如,使用 eBPF,如果建立了網(wǎng)絡(luò)連接,你可以在創(chuàng)建套接字時收到調(diào)用。將套接字調(diào)用作為事件接收非常有用,通過 eBPF 在打開套接字的程序的上下文中提供這些調(diào)用,因此你可以獲得有關(guān)哪個進(jìn)程在打開它以及套接字發(fā)生了什么的信息。
性能的代價
那么eBPF比標(biāo)準(zhǔn)的Linux iptables更高效嗎?視情況而定。?
如果你要在應(yīng)用具有大量 IP 地址(即 ipsets)的網(wǎng)絡(luò)策略時對 iptables 的工作方式進(jìn)行微基準(zhǔn)測試,那么在許多情況下 iptables 比 eBPF 更好。
但是如果你想在 Linux 內(nèi)核中做一些需要改變內(nèi)核中的數(shù)據(jù)包流的事情,eBPF 將是更好的選擇。
標(biāo)準(zhǔn) Linux iptables 是一個復(fù)雜的系統(tǒng),當(dāng)然也有其局限性,但同時它提供了操縱流量的選項;如果你不清楚如何編寫 iptables 規(guī)則,進(jìn)展就會寸步難行。eBPF 則允許將自己的程序加載到內(nèi)核中以影響按需定制的行為,因而它比 iptables 更靈活,因為它不限于一組規(guī)則。
還有一點需要考慮的是,雖然 eBPF 允許你運(yùn)行程序、添加邏輯、重定向流和繞過處理——這絕對是一個勝利——但它是一個虛擬機(jī),因此必須轉(zhuǎn)換為字節(jié)碼。相比之下,Linux 內(nèi)核的 iptables 已經(jīng)編譯為代碼。
如你所見,將eBPF與iptables進(jìn)行簡單的比較意義不大。我們需要評估的是性能,這里要看的兩個關(guān)鍵因素是延遲(速度)和開銷。如果 eBPF 非常快但占用了你 80% 的資源,那么它就像一輛蘭博基尼——一輛昂貴的快車。如果這對你有用,那就太好了(也許你真的很喜歡昂貴、快速的汽車)。
注意,更多的 CPU 占用,意味著更多的錢花在你的云提供商上。因此,雖然蘭博基尼可能比許多其他汽車更快,但如果你需要遵守日常通勤的速度限制,它可能不是最好的花錢方式。
何時使用 eBPF(何時不使用)
想要獲得高性能,自然也需要付出一定的代價。使用eBPFizer之前需要通過計算其性能價格,來確定是否可以接受,從而在兩者之間找到平衡點。
下面是是一些使用 eBPF 的特定情況,包括適用和不適用的場景。
何時不使用eBPF
實施應(yīng)用層政策——由于價格與性能的權(quán)衡,使用 eBPF 執(zhí)行深度協(xié)議檢查和實施應(yīng)用層策略并不是很有效。
你可以利用 Linux 內(nèi)核的連接跟蹤器來實施策略,對每個流應(yīng)用一次策略(無論該流有 5 個數(shù)據(jù)包還是 5,000 個數(shù)據(jù)包),然后在 Linux conntrack 表中將其標(biāo)記為允許或拒絕。你無需繼續(xù)檢查流中的每個數(shù)據(jù)包。如果你要使用 eBPF 實施策略,它允許你在單個 TCP 連接上擁有多個 HTTP 事務(wù),你將需要檢查每個數(shù)據(jù)包以檢測這些事務(wù),然后實施第 7 層控制。為此,你需要執(zhí)行 CPU 周期,這將變得昂貴。
一個更有效的方法是獲得像 Envoy 這樣的代理,并使用 eBPF 優(yōu)化 Envoy 的流量,同時讓 Envoy 為你翻譯應(yīng)用程序協(xié)議。具有像 Envoy 這樣的代理的 iptables 是一個更好的設(shè)計,在這種情況下將是一個更好的選擇。
構(gòu)建??服務(wù)網(wǎng)格??控制平面——類似地,服務(wù)網(wǎng)格依賴于像 Envoy 這樣的代理。多年來,人們在設(shè)計這個過程中進(jìn)行了很多思考。這樣做的主要原因是,在許多情況下,以集群內(nèi)部的高速對 HTTP 等應(yīng)用程序協(xié)議進(jìn)行內(nèi)聯(lián)處理是不可行的。因此,你應(yīng)該考慮使用 eBPF 以一種有效的方式將流量路由到像 Envoy 這樣的代理,而不是使用它來替換代理本身。
逐包處理——使用 eBPF 執(zhí)行 CPU 密集型或逐包處理,例如加密流的解密和重新加密,效率不高,因為你需要構(gòu)建結(jié)構(gòu)并查找每個數(shù)據(jù)包,這是昂貴的。
何時使用
XDP—— eBPF 提供了一種在原始數(shù)據(jù)包緩沖區(qū)進(jìn)入系統(tǒng)時檢查它們的有效方法,使您可以快速決定如何處理它們。
連接時負(fù)載平衡——使用eBPF,您可以使用加載到內(nèi)核中的程序在源頭進(jìn)行負(fù)載平衡,而不是使用虛擬 IP。由于 DNAT 不需要在數(shù)據(jù)包處理路徑上進(jìn)行,因此消除了服務(wù)連接的所有 NAT 開銷。
可觀測性——eBPF 程序是在 Linux 內(nèi)核中添加探測器作為傳感器以獲取上下文豐富的數(shù)據(jù)的絕佳方式。這是一個巨大的好處,因為無需更改內(nèi)核即可啟用跟蹤和分析。您可以在打開套接字的程序的上下文中輕松接收套接字調(diào)用,或者添加程序以跟蹤內(nèi)核中的系統(tǒng)調(diào)用。在我們看來,可觀測性是 eBPF 最有益的用例。
寫在最后
eBPF 是 iptables 的替代品嗎?不完全是。很難想象使用eBPF和使用 iptables 一樣高效。目前,兩者共存,用戶可以根據(jù)自己的具體需求權(quán)衡性價比并決定何時使用哪個功能。
我們相信正確的解決方案是利用 eBPF 以及 Linux 內(nèi)核中的現(xiàn)有機(jī)制來實現(xiàn)你想要的結(jié)果。這就是一些開源方案支持標(biāo)準(zhǔn)Linux、Windows HNS、Linux eBPF等多個數(shù)據(jù)平面的原因。
既然我們已經(jīng)確定 eBPF 和 iptables 都是有用的,那么唯一合乎邏輯的事情就是同時擁抱這兩者。
譯者介紹
陳豪,51CTO社區(qū)編輯,具有6年工作經(jīng)驗的高級系統(tǒng)工程師。擅長技能有Linux內(nèi)嵌匯編語言,Python,C,C++,Java,Linux內(nèi)核分析,智能機(jī)器人軟件設(shè)計等。
原文標(biāo)題:??When (And When Not) to Use eBPF??,作者:Manish Sampat


























