linux内核有ebpf吗,聊聊很重要的内核技术eBPF
在2018年的 Linux Plumber 大會上,eBPF成了亮點,有24個議題提到了 eBPF,可以預計eBPF會成為一大技術熱點。
eBPF(Extended Berkeley Packet Filter) 的核心是駐留在 kernel 的高效虛擬機。最初的目的是高效網絡過濾框架,前身是 BPF。
Linux kernel 3.18版本開始包含了eBPF,相對于 BPF 做了一些重要改進,首先是效率,這要歸功于 JIB 編譯 eBPF 代碼;其次是應用范圍,從網絡報文擴展到一般事件處理;最后不再使用socket,使用map進行高效的數據存儲。
根據以上的改進,內核開發人員在不到兩年半的事件,做出了包括網絡監控、限速和系統監控。目前eBPF可以分解為三個過程:
以字節碼的形式創建 eBPF 的程序。編寫C代碼,將LLVM編譯成駐留在ELF文件中的eBPF字節碼。
將程序加載到內核中,并創建必要的 eBPF-maps。eBPF 具有用作 socket filter,kprobe 處理器,流量控制調度,流量控制操作,tracepoint 處理,eXpress Data Path(XDP),性能監測,cgroup 限制,輕量級tunnel的程序類型。
將加載的程序attach到系統中。根據不同的程序類型attach到不同的內核系統中。程序運行的時候,啟動狀態并且開始過濾,分析或者捕獲信息。
2016年10月的NetDev 1.2大會上,Netronome的Jakub Kicinski和Nic Viljoen發表了標題為“eBPF / XDP硬件卸載到SmartNIC”。 Nic Viljoen在其中介紹了Netronome SmartNIC上每個FPC每秒達到300萬個數據包,每個SmartNIC有72到120個FPC,可能最大支持eBPF吞吐量4.3 Tbps!(理論上)
eBPF 觸發了新一代網絡、安全性、應用程序配置/跟蹤和性能故障排除等領域的工具開發,這些工具不再依賴現有的內核功能,而是在不影響執行效率或安全性的情況下主動重新編程運行時行為。
那我們看看有哪些基于 eBPF 的工程,這些工程或許你已經知道,或是已經經常使用。
基于eBPF的項目
BCC是用于創建基于eBPF的高效內核跟蹤和操作程序的工具包,其中包括一些有用的命令行工具和示例。 BCC簡化了用C進行內核檢測的eBPF程序的編寫,包括LLVM的包裝器以及Python和Lua的前端。它還提供了用于直接集成到應用程序中的高級庫。
bpftrace是Linux eBPF的高級跟蹤語言。它的語言受awk和C以及DTrace和SystemTap等以前的跟蹤程序的啟發。 bpftrace使用LLVM作為后端將腳本編譯為eBPF字節碼,并利用BCC作為與Linux eBPF子系統以及現有Linux跟蹤功能和連接點進行交互的庫。
Cilium是一個開源項目,提供基于eBPF的聯網,安全性和可觀察性。它是從頭開始專門設計的,旨在將eBPF的優勢帶入Kubernetes的世界,并滿足容器工作負載的新可伸縮性,安全性和可見性要求。
Falco是一種行為活動監視器,旨在檢測應用程序中的異常活動。 Falco在eBPF的幫助下審核Linux內核層的系統。它使用其他輸入流(例如容器運行時度量標準和Kubernetes度量標準)豐富了收集的數據,并允許連續監視和檢測容器,應用程序,主機和網絡活動。
Katran是一個C ++庫和eBPF程序,用于構建高性能的第4層負載平衡轉發平面。 Katran利用Linux內核中的XDP基礎結構來提供用于快速數據包處理的內核功能。它的性能與NIC接收隊列的數量成線性比例,并且使用RSS友好的封裝轉發到L7負載平衡器。
Sysdig是提供深層系統可見性的簡單工具,并具有對容器的原生支持。
其他基于eBPF技術的項目還有很多,比如kubectl-trace?,ply?等,這里不再贅述。
如何編寫一個eBPF程序?
在很多情況下,不是直接使用eBPF,而是通過Cilium,bcc或bpftrace等項目間接使用eBPF,這些項目在eBPF之上提供了抽象,并且不需要直接編寫程序,而是提供了指定基于意圖的定義的功能,然后使用eBPF實施。
如果不存在更高級別的抽象,則需要直接編寫程序。 Linux內核希望eBPF程序以字節碼的形式加載。雖然當然可以直接編寫字節碼,但更常見的開發實踐是利用LLVM之類的編譯器套件將偽C代碼編譯為eBPF字節碼。
在編寫eBPF程序之前,需要簡單了解幾個概念。
1)map(映射) :BPF最令人著迷的方面之一是,內核上運行的代碼和加載了該代碼的程序可以在運行時使用消息傳遞相互通信。
BPF映射是駐留在內核中的鍵/值存儲。任何BPF程序都可以訪問它們。在用戶態中運行的程序也可以使用文件描述符訪問這些映射。只要事先正確指定數據大小,就可以在映射中存儲任何類型的數據。內核將鍵和值視為二進制 blobs,它并不關心您在映射中保留的內容。
BPF驗證程序包括多種保護措施,以確保您創建和訪問映射的方式是安全的。當我們解釋如何訪問這些映射中的數據時,我們也將解釋這些保護措施。
當然BPF映射類型有很多,比如哈希表映射,數組映射,Cgroup 數組映射等,分別滿足不同的場景。
2)驗證器
BPF驗證程序也是在您的系統上運行的程序,因此,對其進行嚴格審查是確保其正確執行工作的目標。
驗證程序執行的第一項檢查是對VM即將加載的代碼的靜態分析。第一次檢查的目的是確保程序有預期的結果。為此,驗證程序將使用代碼創建有向循環圖(DAG)。驗證程序分析的每個指令將成為圖中的一個節點,并且每個節點都鏈接到下一條指令。驗證程序生成此圖后,它將執行深度優先搜索(DFS),以確保程序完成并且代碼不包含危險路徑。這意味著它將遍歷圖的每個分支,一直到分支的底部,以確保沒有遞歸循環。
這些是驗證器在第一次檢查期間可能拒絕您的代碼的情形,要求有以下幾個方面:
該程序不包含控制循環。為確保程序不會陷入無限循環,驗證程序會拒絕任何類型的控制循環。已經提出了在BPF程序中允許循環的建議,但是截至撰寫本文時,沒有一個被采用。
該程序不會嘗試執行超過內核允許的最大指令數的指令。此時,可執行的最大指令數為4,096。此限制是為了防止BPF永遠運行。在第3章,我們討論如何嵌套不同的BPF程序,以安全的方式解決此限制。
該程序不包含任何無法訪問的指令,例如從未執行過的條件或功能。這樣可以防止在VM中加載無效代碼,這也會延遲BPF程序的終止。
該程序不會嘗試越界。
驗證者執行的第二項檢查是BPF程序的空運行。這意味著驗證者將嘗試分析程序將要執行的每條指令,以確保它不會執行任何無效的指令。此執行還將檢查所有內存指針是否均已正確訪問和取消引用。最后,空運行向驗證程序通知程序中的控制流,以確保無論程序采用哪個控制路徑,它都會到達BPF_EXIT指令。為此,驗證程序會跟蹤堆棧中所有訪問過的分支路徑,并在采用新路徑之前對其進行評估,以確保它不會多次訪問特定路徑。經過這兩項檢查后,驗證者認為程序可以安全執行。
3) hook : 由于eBPF是事件驅動的,所以ebpf是作用于具體的hook的。根據不同的作用,常用的有XDP,trace,套接字等。
4)幫助函數:eBPF程序無法調用任意內核功能。允許這樣做會將eBPF程序綁定到特定的內核版本,并使程序的兼容性復雜化。取而代之的是,eBPF程序可以調用幫助函數,該函數是內核提供的眾所周知且穩定的API。
總結
安全,網絡,負載均衡,故障分析,追蹤等領域都是eBPF的主戰場。對于云原生領域,Cilium 已經使用eBPF 實現了無kube-proxy的容器網絡。利用eBPF解決iptables帶來的性能問題。
整個eBPF生態發展比較好,社區已經提供了諸多工具方便大家編寫自己的eBPF程序。
總結
以上是生活随笔為你收集整理的linux内核有ebpf吗,聊聊很重要的内核技术eBPF的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信零钱通可以随时转出吗?可以随时提现吗
- 下一篇: 个人信用卡办理条件 财力证明多多益善