Linux未來監控tracing框架——eBPF
eBPF源於早年間的成型於 BSD 之上的傳統技術 BPF(Berkeley Packet Filter)。BPF 的全稱是 Berkeley Packet Filter,顧名思義,這是一個用於過濾(filter)網絡報文(packet)的架構。
BPF 是在 1997 年首次被引入 Linux 的,Linux 內核中的報文過濾機制其實是有自己的名字的:Linux Socket Filter,簡稱 LSF。
從 3.15 開始,一個套源於 BPF 的全新設計開始,在3.17被添置到了 kernel/bpf 下。全新設計最終被命名為了 extended BPF(eBPF);為了后向兼容,傳統的 BPF 仍被保留了下來,並被重命名為 classical BPF(cBPF)。相對於 cBPF,eBPF 帶來的改變可謂是革命性的:一方面,它已經為內核追蹤(Kernel Tracing)、應用性能調優/監控、流控(Traffic Control)等領域帶來了激動人心的變革;另一方面,在接口的設計以及易用性上,eBPF 也有了較大的改進。
cBPF 所覆蓋的功能范圍很簡單,就是網絡監控和 seccomp 兩塊,數據接口設計的粗放;而 eBPF 的利用范圍要廣的多,性能調優、內核監控、流量控制什么的,數據接口的多樣性設計。
由一個文件(net/core/filter.c)進化到一個目錄(kernel/bpf)
目前,支持生成 BPF 偽代碼的編譯器只有 llvm 一家,即使是通篇使用 gcc 編譯的 Linux 內核,samples 目錄下的 bpf 范例也要借用 llvm 來編譯完成。
1. 運行監測
eBPF 其實是內核模塊,比內核模塊更短小精干,實現的功能也更新穎, eBPF注入的代碼是要在內核中運行的,會有安全隱患。
為了最大限度控制安全隱患,cBPF 時代就開始加入了代碼檢查機制以防止不規范的注入代碼;到了 eBPF則在載入程序(bpf_load_program())時加入了更復雜的verifier 機制,會進行一系列的安全檢查。
2. 架構
架構如下:
3. bcc
現在可以用 C 來實現 BPF,但編譯出來的卻仍然是 ELF 文件,開發者需要手動析出真正可以注入內核的代碼。這工作有些麻煩,於是就有人設計了 BPF Compiler Collection(BCC),BCC 是一個 python 庫,但是其中有很大一部分的實現是基於 C 和 C++的,python實現了對 BCC 應用層接口的封裝。
使用 BCC 進行 BPF 的開發仍然需要開發者自行利用 C 來設計 BPF 程序——但也僅此而已,余下的工作,包括編譯、解析 ELF、加載 BPF 代碼塊以及創建 map 等等基本可以由 BCC 一力承擔,無需多勞開發者費心。
3.1 bcc安裝
github的地址鏈接如下:
https://github.com/iovisor/bcc
執行:git clone https://github.com/iovisor/bcc.git
在Ubuntu中直接安裝二進制文件,命令如下:
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys D4284CDD
echo "deb https://repo.iovisor.org/apt/xenial xenial main" | sudo tee /etc/apt/sources.list.d/iovisor.list
sudo apt-get update
sudo apt-get install bcc-tools libbcc-examples linux-headers-$(uname -r)
這樣就可以 使用bcc/example/tracing中的python用例。