聊聊最近很火的eBPF

若是非要說當前計算機領域最有前途的兩個基礎軟件技術,那非eBPF和wasm莫屬了。前端

什麼是eBPF?

Linux內核一直是實現監視/可觀察性,網絡和安全性的理想場所。不幸的是,這一般是不切實際的,由於它須要更改內核源代碼或加載內核模塊,並致使彼此堆疊的抽象層。 eBPF是一項革命性的技術,能夠在Linux內核中運行沙盒程序,而無需更改內核源代碼或加載內核模塊。經過使Linux內核可編程,基礎架構軟件能夠利用現有的層,從而使它們更加智能和功能豐富,而無需繼續爲系統增長額外的複雜性層。ios

eBPF致使了網絡,安全性,應用程序配置/跟蹤和性能故障排除等領域的新一代工具的開發,這些工具再也不依賴現有的內核功能,而是在不影響執行效率或安全性的狀況下主動從新編程運行時行爲。git

若是直接解釋eBPF,有點不明因此。那咱們就看看有哪些基於eBPF的工程,這些工程或許你已經知道,或是已經常用,也許你會明白eBPF距離咱們並不遙遠。github

基於eBPF的項目

1:bcc編程

BCC是用於建立基於eBPF的高效內核跟蹤和操做程序的工具包,其中包括一些有用的命令行工具和示例。 BCC簡化了用C進行內核檢測的eBPF程序的編寫,包括LLVM的包裝器以及Python和Lua的前端。它還提供了用於直接集成到應用程序中的高級庫。後端

2:bpftrace數組

bpftrace是Linux eBPF的高級跟蹤語言。它的語言受awk和C以及DTrace和SystemTap等之前的跟蹤程序的啓發。 bpftrace使用LLVM做爲後端將腳本編譯爲eBPF字節碼,並利用BCC做爲與Linux eBPF子系統以及現有Linux跟蹤功能和鏈接點進行交互的庫。安全

3:Cilium網絡

Cilium是一個開源項目,提供基於eBPF的聯網,安全性和可觀察性。它是從頭開始專門設計的,旨在將eBPF的優點帶入Kubernetes的世界,並知足容器工做負載的新可伸縮性,安全性和可見性要求。架構

4:Falco

Falco是一種行爲活動監視器,旨在檢測應用程序中的異常活動。 Falco在eBPF的幫助下審覈Linux內核層的系統。它使用其餘輸入流(例如容器運行時度量標準和Kubernetes度量標準)豐富了收集的數據,並容許連續監視和檢測容器,應用程序,主機和網絡活動。

5:Katran

Katran是一個C ++庫和eBPF程序,用於構建高性能的第4層負載平衡轉發平面。 Katran利用Linux內核中的XDP基礎結構來提供用於快速數據包處理的內核功能。它的性能與NIC接收隊列的數量成線性比例,而且使用RSS友好的封裝轉發到L7負載平衡器。

6:Sysdig

Sysdig是提供深層系統可見性的簡單工具,並具備對容器的原生支持。

其餘基於eBPF技術的項目還有不少,好比kubectl-traceply 等,這裏再也不贅述。

如何編寫一個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程序。

相關文章
相關標籤/搜索