前世BPF
在介紹eBPF (Extended Berkeley Packet Filter)之前,我們先來(lái)了解一下它的前身-BPF (Berkeley Packet Filter)伯克利數(shù)據(jù)包過(guò)濾器。
BPF最早由Van Jacobson在1992年開(kāi)發(fā),用于在Unix操作系統(tǒng)中過(guò)濾和捕獲網(wǎng)絡(luò)數(shù)據(jù)包。它運(yùn)行在內(nèi)核中,通過(guò)提供一個(gè)簡(jiǎn)單而強(qiáng)大的虛擬機(jī),可以在網(wǎng)絡(luò)協(xié)議層上進(jìn)行高效的數(shù)據(jù)包處理操作。BPF通過(guò)把過(guò)程轉(zhuǎn)換成指令序列來(lái)實(shí)現(xiàn),這些指令直接在內(nèi)核中執(zhí)行,從而避免了用戶空間和內(nèi)核空間之間頻繁的切換。
基于BPF開(kāi)發(fā)的工具庫(kù)有l(wèi)ibpcap、tcpdump等工具。
BPF在網(wǎng)絡(luò)性能監(jiān)測(cè)和安全策略實(shí)施方面具有廣泛的應(yīng)用。然而,由于其指令集的限制和功能的局限性,它無(wú)法支持更加復(fù)雜和靈活的數(shù)據(jù)包處理需求。
今生eBPF
正是為了克服BPF的限制,eBPF應(yīng)運(yùn)而生。eBPF于2014年(3.18版本)年首次引入Linux內(nèi)核,并在此后的幾年中經(jīng)歷了快速的發(fā)展和完善。
eBPF是一個(gè)高度可擴(kuò)展的、運(yùn)行在內(nèi)核中的虛擬機(jī),具備與傳統(tǒng)BPF相似的指令集,但功能更加強(qiáng)大且更加靈活。eBPF可以在運(yùn)行時(shí)即時(shí)編譯,從而能夠處理更加復(fù)雜和動(dòng)態(tài)的數(shù)據(jù)包處理任務(wù),如網(wǎng)絡(luò)流量分析、安全檢測(cè)和性能優(yōu)化等。
eBPF的靈活性和可擴(kuò)展性體現(xiàn)在它可以與各種用戶空間程序(如tcpdump、Wireshark、Suricata等)和工具(如網(wǎng)絡(luò)監(jiān)控、調(diào)試器等)無(wú)縫集成。eBPF還可以與系統(tǒng)的其他組件(如網(wǎng)絡(luò)協(xié)議棧、調(diào)度器等)交互,從而實(shí)現(xiàn)更加細(xì)粒度的性能優(yōu)化和安全策略。
此外,eBPF的開(kāi)發(fā)和使用也得到了廣泛的支持和推動(dòng)。社區(qū)中有許多致力于eBPF的開(kāi)發(fā)者和貢獻(xiàn)者,他們不斷改進(jìn)和擴(kuò)展eBPF的功能。同時(shí),一些知名的大型技術(shù)公司,如Facebook、Netflix和Google等,也在其產(chǎn)品和基礎(chǔ)設(shè)施中廣泛使用eBPF。
eBPF的發(fā)展史
2014 年初,Alexei Starovoitov 實(shí)現(xiàn)了eBPF。新的設(shè)計(jì)針對(duì)現(xiàn)代硬件進(jìn)行了優(yōu)化,所以eBPF生成的指令集比舊的 BPF 解釋器生成的機(jī)器碼執(zhí)行得更快。擴(kuò)展版本也增加了虛擬機(jī)中的寄存器數(shù)量,將原有的 2 個(gè) 32 位寄存器增加到10 個(gè) 64 位寄存器。由于寄存器數(shù)量和寬度的增加,開(kāi)發(fā)人員可以使用函數(shù)參數(shù)自由交換更多的信息,編寫更復(fù)雜的程序。總之,這些改進(jìn)使eBPF版本的速度比原來(lái)的 BPF 提高了 4 倍。
eBPF是一項(xiàng)具有革命性的技術(shù),源自于Linux內(nèi)核,可以在特權(quán)環(huán)境中運(yùn)行受沙盒保護(hù)的程序,例如操作系統(tǒng)內(nèi)核。它被用于安全有效地?cái)U(kuò)展內(nèi)核的功能,而無(wú)需更改內(nèi)核源代碼或加載內(nèi)核模塊。
在歷史上,操作系統(tǒng)一直是實(shí)現(xiàn)可觀察性、安全性和網(wǎng)絡(luò)功能的理想場(chǎng)所,這是因?yàn)閮?nèi)核具有特權(quán)能力,可以監(jiān)督和控制整個(gè)系統(tǒng)。與此同時(shí),由于內(nèi)核在系統(tǒng)中的核心地位以及對(duì)穩(wěn)定性和安全性的高要求,操作系統(tǒng)內(nèi)核的演進(jìn)往往很困難。因此,與操作系統(tǒng)外部實(shí)現(xiàn)的功能相比,操作系統(tǒng)層面的創(chuàng)新速度傳統(tǒng)上較低。
eBPF從根本上改變了這個(gè)共識(shí)。通過(guò)在操作系統(tǒng)內(nèi)運(yùn)行受沙盒保護(hù)的程序,應(yīng)用開(kāi)發(fā)人員可以在運(yùn)行時(shí)運(yùn)行eBPF程序,為操作系統(tǒng)添加額外的功能。操作系統(tǒng)會(huì)利用即時(shí)編譯器和驗(yàn)證引擎的幫助來(lái)保證安全性和執(zhí)行效率,就像本地編譯一樣。這導(dǎo)致了一系列基于eBPF的項(xiàng)目的涌現(xiàn),涵蓋了各種用例,包括下一代網(wǎng)絡(luò)、可觀測(cè)性和安全功能。
如今,eBPF被廣泛應(yīng)用于驅(qū)動(dòng)各種用例:在現(xiàn)代數(shù)據(jù)中心和云原生環(huán)境中提供高性能的網(wǎng)絡(luò)和負(fù)載均衡,以低開(kāi)銷提取細(xì)粒度的安全可觀測(cè)性數(shù)據(jù),幫助應(yīng)用開(kāi)發(fā)人員追蹤應(yīng)用程序、提供性能故障排除的見(jiàn)解,進(jìn)行預(yù)防性應(yīng)用程序和容器運(yùn)行時(shí)安全執(zhí)行等等。可能性是無(wú)限的,eBPF正在釋放出的創(chuàng)新力量才剛剛開(kāi)始。
Hook Overview
eBPF程序是事件驅(qū)動(dòng)的,當(dāng)內(nèi)核或應(yīng)用程序通過(guò)某個(gè)掛鉤點(diǎn)時(shí)運(yùn)行。預(yù)定義的掛鉤點(diǎn)包括系統(tǒng)調(diào)用、函數(shù)入口/退出、內(nèi)核追蹤點(diǎn)、網(wǎng)絡(luò)事件等等。
eBPF使用中遇到的問(wèn)題
1
內(nèi)核適應(yīng)性,老版本是否某些功能不可用?
eBPF 最低要求版本為L(zhǎng)Inux 4.1,eBPF的最低內(nèi)核版本要求是 Linux 4.1,這是在 2015 年發(fā)布的內(nèi)核版本。在這個(gè)版本之前的內(nèi)核不支持 eBPF。
對(duì)于Linux4.1版本之前的監(jiān)控
擎創(chuàng)對(duì)于Linux 4.1.0 之前的版本采用BPF采集HTTP 1數(shù)據(jù)以及DNS解析請(qǐng)求,進(jìn)行可觀測(cè)統(tǒng)計(jì)。
對(duì)于Linux4.1版本之后的監(jiān)控
為了保證eBPF程序在各個(gè)linux內(nèi)核版本之間的可移植性,我們編寫eBPF程序的時(shí)候采用了CORE技術(shù),CORE技術(shù)目前只有在 Linux 4.9.0 之后才會(huì)支持。
如果用戶內(nèi)核版本低于4.9.0或者內(nèi)核未開(kāi)啟CO-RE, 我們能夠提供linux內(nèi)核升級(jí)包。
2
權(quán)限、安全要求
eBPF權(quán)限
需要具備root權(quán)限或CAP_SYS_ADMIN能力,這意味著只有能夠加載內(nèi)核模塊的用戶才能加載eBPF程序。
eBPF執(zhí)行安全
在執(zhí)行安全方面,eBPF 在加載之前會(huì)通過(guò)eBPF驗(yàn)證器對(duì)要執(zhí)行的字節(jié)碼文件進(jìn)行校驗(yàn),包括但不限于以下方面:
(1)程序不包含控制循環(huán)
(2)程序不會(huì)執(zhí)行超過(guò)內(nèi)核允許的最大指令數(shù)
(3)程序不包含任何無(wú)法到達(dá)的指令
(4)程序不會(huì)跳轉(zhuǎn)到程序界限之外
3
uprobe 和 kprobe 差異
kprobe的優(yōu)劣分析
優(yōu)勢(shì):
(1)更簡(jiǎn)單實(shí)現(xiàn)和更易維護(hù)。它不依賴于其他庫(kù)的具體實(shí)現(xiàn)細(xì)節(jié)
劣勢(shì):
(1)用戶程序可能會(huì)將單個(gè)請(qǐng)求分割成多個(gè)系統(tǒng)調(diào)用,重新組裝這些請(qǐng)求會(huì)帶來(lái)一些復(fù)雜性
(2)與TLS不兼容, 無(wú)法解包TLS
uprobe的優(yōu)劣分析
優(yōu)勢(shì):
(1)我們可以訪問(wèn)和捕獲應(yīng)用程序上下文,如堆棧跟蹤
(2)我們可以構(gòu)建uprobes以在解析完成后捕獲數(shù)據(jù),避免在跟蹤器中重復(fù)工作
(3)可以比較容易捕獲https 請(qǐng)求,對(duì)TLS兼容性較好
劣勢(shì):
(1)對(duì)于使用的底層庫(kù)版本敏感。無(wú)法在剝離了符號(hào)的二進(jìn)制文件上運(yùn)行
(2)需要為每個(gè)庫(kù)實(shí)現(xiàn)不同的探針(每種編程語(yǔ)言可能都有自己的一組庫(kù))
(3)會(huì)導(dǎo)致額外的調(diào)用性能開(kāi)銷
4
性能消耗
雖然內(nèi)核社區(qū)已經(jīng)對(duì) eBPF 做了很多的性能調(diào)優(yōu),跟蹤用戶態(tài)函數(shù)(特別是鎖爭(zhēng)用、內(nèi)存分配之類的高頻函數(shù))還是有可能帶來(lái)很大的性能開(kāi)銷。因此,我們?cè)谑褂?uprobe,kprobe 時(shí),應(yīng)該盡量避免長(zhǎng)時(shí)間跟蹤高頻函數(shù)。
我們以監(jiān)控一個(gè)Golang 程序HTTP 1通信過(guò)程為例子,在分別開(kāi)啟uprobe和kprobe時(shí)候?qū)υ摮绦蜻M(jìn)行壓力測(cè)試:
從結(jié)果可以看出,如果HTTP延遲大于1毫秒,引入的開(kāi)銷可以忽略不計(jì),在大多數(shù)情況下只是噪音。這對(duì)于kprobes和uprobes都是類似的,盡管我們重新解析了所有數(shù)據(jù),但kprobes的性能稍微好一些。請(qǐng)注意,開(kāi)銷有時(shí)是負(fù)值,這很可能只是測(cè)量中的噪音。在這里的關(guān)鍵要點(diǎn)是,如果您的HTTP處理程序正在進(jìn)行任何實(shí)際的工作(大約1毫秒計(jì)算時(shí)間),引入的開(kāi)銷基本上可以忽略不計(jì)。
5
能否追蹤所有用戶態(tài)/內(nèi)核態(tài)函數(shù)
調(diào)用的入?yún)⒑头祷刂?/strong>
用戶態(tài)
eBPF可以追蹤指定函數(shù)調(diào)用入?yún)⒑头祷刂怠ook點(diǎn)可以為指定函數(shù)名稱或者地址。如果可執(zhí)行文件的符號(hào)被優(yōu)化,則需要使用一些逆向手段定位指定函數(shù)的地址。
內(nèi)核態(tài)
我們可以使用bpftrace -l了解可以hook的鉤子點(diǎn)。
bpftrace是通過(guò)讀取(下方代碼)獲取kernel層所有的可跟蹤點(diǎn)。
/sys/kernel/debug/tracing/available_filter_functions
6
是否有丟失事件的風(fēng)險(xiǎn)
kprobe和uprobe本身的事件觸發(fā)并不會(huì)丟失
kprobe是一種內(nèi)核探測(cè)機(jī)制,它允許用戶在內(nèi)核函數(shù)執(zhí)行前或執(zhí)行后插入代碼。uprobe是一種對(duì)用戶空間函數(shù)進(jìn)行探測(cè)的機(jī)制,它允許用戶在用戶空間函數(shù)的入口或出口處插入代碼。
eBPF通過(guò)將用戶編寫的處理邏輯加載到內(nèi)核中,在事件發(fā)生時(shí)執(zhí)行此邏輯,以實(shí)現(xiàn)用戶級(jí)的觀察和處理。由于eBPF的虛擬機(jī)技術(shù)提供了一種安全可隔離的方式來(lái)在內(nèi)核中執(zhí)行用戶代碼,因此kprobe和uprobe事件不會(huì)丟失。
bpf_perf_event會(huì)有丟失事件的風(fēng)險(xiǎn)
內(nèi)核態(tài)的eBPF代碼將收集到的事件寫入 bpf_perf_event 環(huán)形緩沖區(qū),用戶態(tài)程序進(jìn)行收集上報(bào)。當(dāng)讀寫速度不匹配時(shí),就會(huì)丟失事件:
(1)寫速度過(guò)快:例如每個(gè)HTTP transaction都作為一個(gè)event寫入緩沖區(qū),這樣比批量寫的風(fēng)險(xiǎn)更高。
(2)讀速度過(guò)慢:例如用戶態(tài)代碼沒(méi)有在專門線程中讀取緩沖區(qū),或者系統(tǒng)負(fù)載過(guò)高。
bpf_map會(huì)有丟失事件的風(fēng)險(xiǎn)
eBPF map有大小限制,當(dāng)map被寫滿的時(shí),將無(wú)法寫入新的數(shù)據(jù)
(1)丟失數(shù)據(jù):由于map已滿,新的寫入操作將無(wú)法成功,導(dǎo)致數(shù)據(jù)丟失。這可能會(huì)影響到程序的正確性和完整性。
(2)性能下降:當(dāng)map寫滿時(shí),寫入操作將被阻塞,導(dǎo)致系統(tǒng)的性能下降。這會(huì)影響到整體的系統(tǒng)響應(yīng)時(shí)間和吞吐量。
展望
隨著eBPF的不斷發(fā)展和壯大,我們可以看到它在網(wǎng)絡(luò)和系統(tǒng)領(lǐng)域的巨大潛力。eBPF已經(jīng)被證明是一種強(qiáng)大且高效的工具,可以用于實(shí)現(xiàn)各種高級(jí)網(wǎng)絡(luò)和系統(tǒng)功能。
在未來(lái),我們有理由相信eBPF將繼續(xù)發(fā)展,并被越來(lái)越多的開(kāi)發(fā)者和組織使用。隨著eBPF功能的不斷擴(kuò)展和完善,我們可以期待更多創(chuàng)新的網(wǎng)絡(luò)應(yīng)用和系統(tǒng)工具的出現(xiàn),從而推動(dòng)整個(gè)行業(yè)向前發(fā)展。
總之,eBPF的前世今生令人振奮,它不僅繼承了BPF的優(yōu)點(diǎn),還擁有更強(qiáng)大和靈活的功能。我們期待看到eBPF為網(wǎng)絡(luò)和系統(tǒng)帶來(lái)更多的創(chuàng)新和改進(jìn),為我們的數(shù)字化世界帶來(lái)更強(qiáng)大的支撐。
審核編輯:劉清
-
UNIX操作系統(tǒng)
+關(guān)注
關(guān)注
0文章
13瀏覽量
15327 -
虛擬機(jī)
+關(guān)注
關(guān)注
1文章
937瀏覽量
28426 -
過(guò)濾器
+關(guān)注
關(guān)注
1文章
432瀏覽量
19734 -
LINUX內(nèi)核
+關(guān)注
關(guān)注
1文章
316瀏覽量
21742 -
調(diào)度器
+關(guān)注
關(guān)注
0文章
98瀏覽量
5298
原文標(biāo)題:聊聊eBPF的前世今生
文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論