Kindling 之 eBPF 基礎設施庫技術選型

eBPF 技術正以令人難以置信的速度發展,作爲一項新興技術,它具備改變容器網絡、安全、可觀測性生態的潛力。eBPF 作爲更加現代化的內核技術,相較於內核模塊,它的編寫難度已經有了較大的降低,但是不可否認對於普通開發者還是有一定門檻。因此,很多雲原生軟件會在 eBPF 系統調用 (函數) 和 libbpf 之上封裝一層更加簡單易用的 api,比如 falco 的 libs、bcc 的 libbcc、cilium 的 cilium-ebpf。筆者將這些依賴庫稱之爲 eBPF 的基礎設施。

Kindling 專注於雲可觀測性領域,致力於排查各種複雜故障,包括但不限於網絡、文件、內存、on-off cpu 堆棧,解決上述問題是 Kindling 第一優先級目標,本着不重複造輪子的原則,Kindling 無意於再創造一個 eBPF 的基礎設施。

豐富的 eBPF 基礎設施庫

當下有很多庫可以供開發者選擇,比如 libbcc、dropbox 的 goebpf、cilium 的 ebpf 庫、calico 的底層庫、falco 的 lib 庫。這些庫主要協助完成以下功能:

基於此,我們分別選擇了 2 個基於 c 和 go 的基礎設施庫來對比:

zTIJiy

在這 4 個比較對象中,libbcc 和 gobpf 一脈同源,gobpf 是 libbcc 的 go 實現,其原理是用 cgo 包裝了 libbcc 和 libelf。faclo-libs 是純 c 語言的實現,cilium-ebpf 則是純 go 語言的實現。在功能實現方面,這些庫都實現了 eBPF 程序加載使用的基本流程。不過這些庫分別也擁有一些其獨有的優勢,比如:

Kindling 選擇 falco-libs 的 N 大理由

既然基礎的功能這些庫都能實現,並且在細節方面 cilium 更加出色,那麼爲什麼 Kindling 依舊選擇 falco-libs 作爲 eBPF 基礎設施呢?理由如下:

01 對低版本內核的支持

衆所周知,eBPF 在 4.14 內核版本以上才能使用。但是現階段很多發行版比如 centOS7 的內核版本都是 3.x,無法使用 eBPF(centOS7.6 以上已經通過 eBPF patch 支持)。Falco-libs 使用內核模塊實現了和 eBPF 相同的功能,且性能表現更加出色,Kindling 認爲 centOS7.4 等版本在國內現階段還是廣泛應用的,在低版本內核中體驗到 Kindling 可觀測性的功能是非常重要的。
由於採用了 faclo-libs,Kindling 支持的發行版本如下表所示:

AE60VH

內核模塊更出色的性能表現(圖出自 falco-libs github):

faclo 社區的性能測試結果

02 對於系統調用的精細化整理

Falco-libs 是 syscall 方面的專家,而 Kindling 對 syscall 的分析需求也必不可少。

Syscall 是 Kindling 可觀測性事件的重要來源,syscall 可以分析出一次網絡調用的時間、具體網絡報文,一次文件讀寫等指標。在 Kindling 未來的功能規劃裏,oncpu offcpu 剖析也需要用到 futex、write、epoll 等 syscall。
Facalo-libs 梳理了 300 多個 syscall,將其中的主要參數從內核數據結構轉換成如下類似事件結構:

/* PPME_SOCKET_GETSOCKOPT_E */{"getsockopt", EC_NET, EF_MODIFIES_STATE | EF_DROP_SIMPLE_CONS, 0 },
/* PPME_SOCKET_GETSOCKOPT_X */{"getsockopt", EC_NET, EF_USES_FD | EF_MODIFIES_STATE| EF_DROP_SIMPLE_CONS, 6, {{"res", PT_ERRNO, PF_DEC}{"fd", PT_FD, PF_DEC}{"level", PT_FLAGS8, PF_DEC, sockopt_levels}{"optname", PT_FLAGS8, PF_DEC, sockopt_options}{"val", PT_DYN, PF_DEC, sockopt_dynamic_param, PPM_SOCKOPT_IDX_MAX}{"optlen", PT_UINT32, PF_DEC}}},
/* PPME_SOCKET_SENDMSG_E */{"sendmsg", EC_IO_WRITE, EF_USES_FD | EF_WRITES_TO_FD | EF_MODIFIES_STATE, 3, {{"fd", PT_FD, PF_DEC}{"size", PT_UINT32, PF_DEC}{"tuple", PT_SOCKTUPLE, PF_NA} } },
/* PPME_SOCKET_SENDMSG_X */{"sendmsg", EC_IO_WRITE, EF_USES_FD | EF_WRITES_TO_FD | EF_MODIFIES_STATE, 2, {{"res", PT_ERRNO, PF_DEC}{"data", PT_BYTEBUF, PF_NA} } },

03 Falco-libs 對事件的豐富化

Falco-libs 會根據內核事件的 tid,fd 等信息自動補全事件的以下字段:

7CKZTO

這讓 kindling 將事件轉換成指標和 trace 變得事半功倍。

04 正在支持中的 CO-RE

Faclo-libs 截止目前還未支持 CO-RE,不過其已經有獨立的分支開始進行相關內容支持,相信在不久的將來 falco-libs 將支持 CO-RE。這使得筆者認爲的 falco-libs 最大的短板將得到解決。

基於以上理由,筆者認爲 faclo-libs 是當下最適合 Kindling 功能需求的基礎 eBPF 庫。

基於 faclo-libs 的拓展

這些改動都體現在該倉庫 agent-libs(fork on faclo/libs):

https://github.com/Kindling-project/agent-libs

對於未來

隨着國內 3.x 內核版本操作系統的逐漸更新換代,Kindling 有理由選擇社區熱度更火、細節方面更出色的 cilium-ebpf 作爲底層基礎庫,也有理由選擇經過無數環境驗證的 libbcc 作爲底層庫。總之,一切取決於 Kindling 用戶的需要,Kindling 對此呈開放態度並且始終權衡利弊,選擇當下最合適的方案。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/4WNyNwkRW2lZ82nMOP6rMA