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