基於 CO-RE(Compile Once – Run Everywhe)實現的 Coolbpf 項目,新推出輕量級腳本化編程特性 lwcb(Lightweight Coolbpf)。lwcb 是一款面向 eBPF 的腳本語言和 tracing 開發工具,它可以解析用戶編寫的腳本,生成 eBPF 字節碼,從而實現對 Linux 內核系統的跟蹤診斷、性能分析和監控。此外,lwcb 還提供了大量內置函數,如 tcpstate 可以輕鬆將整數轉換成 tcp 狀態字符串,tcphdr、iphdr 可以讓用戶從 skb 裏獲取 tcphdr 或 iphdr 結構體,有助於快速編寫內核網絡相關的 eBPF 程序。lwcb 也讓用戶方便地添加更多的內置函數,覆蓋更多應用場景。
01 lwcb 特性
輕量級、易部署
lwcb 使用 rust 開發了一個小巧的解析器,不依賴於 Clang。它採用輕量級的編譯器,並且爲編譯器添加了 eBPF 後端,使其不需要依賴於 llvm。lwcb 編譯後只有一個大小約爲 8MB 的獨立二進制程序,部署非常方便快捷。以往部署 BCC 和 bpftrace 等工具,需要在目標執行機器上安裝一堆編譯和運行庫。
腳本化、開發快
lwcb 當前支持類似於 bpftrace 的腳本解釋執行能力,優勢是不需要編譯。同時提供了更多內置函數,方便開發和使用。另外,他天然支持 CO-RE 的能力,在不同內核版本上安全運行。可以說,功能比較強大。
lwcb 功能性強主要體現在以下幾點:
1. 更多的內置函數:如tcphdr、iphdr、tcpstate 等等。
2. 探測點函數參數自動注入功能:
lwcb -t 'kprobe:tcp_rcv_established { ih = iphdr(skb); print("sip: %s dip: %s\n", ntop(bswap(ih->saddr)), ntop(bswap(ih->daddr))); }'
用戶可以直接訪問 tcp_rcv_established 函數的 skb 參數,進而獲取 IP 地址和端口號信息。
3. 支持 BTF,能夠進行類型推導。如 th = tcphdr(skb);,lwcb能夠根據 BTF 信息,知道 skb 的類型是 struct sk_buff*,th 的類型是 struct tcphdr *。用戶可以直接來訪問 struct tcphdr結構體中的成員,如 th->source,而無需再聲明 th 的類型。
4. 支持 python,使得 lwcb 可以充分利用python來進行復雜的數據處理,類似於 bcc 的開發方式。用戶可以通過 import pylwcb 來使用 lwcb 的功能。下面是一個簡單的例子:
import pylwcb
lwcb_program = """
kprobe:tcp_rcv_established {
th = tcphdr(skb);
ih = iphdr(skb);
print(ntop(bswap(ih->saddr)), ntop(bswap(ih->daddr)), bswap(th->source), bswap(th->dest));
}
"""
lwcb = pylwcb.Pylwcb(lwcb_program)
lwcb.attach()
events = lwcb.read_events()
for event in events:
print(event)
5. 支持批量探測點,kprobe:(struct sock *sk) 會跟蹤內核裏所有攜帶有 struct sock *sk 參數的函數。可以利用該功能,實現更細粒度的 function graph。
kprobe:(struct sock *sk) {
sport = sk->__sk_common.skc_num;
if (sport == 22) {
print("%s %s\n", timestr(ns()), ksym(reg("ip")));
}
}
02 lwcb 使用方法
只需要更新 Coolbpf (https://gitee.com/anolis/coolbpf) 到 1.0.0 版本,就可以使用 lwcb 腳本化編程功能。
編譯 lwcb
1. 準備編譯環境(https://coolbpf.readthedocs.io/en/latest/lwcb/build.html#id1)
安裝 rust 編譯工具鏈:curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh克隆 Coolbpf 代碼:git clone https://gitee.com/anolis/coolbpf.git進入到 lwcb 目錄:cd coolbpf/lwcb
2. 編譯:cargo build --release 即可完成編譯,生成的 lwcb 可執行程序在:target/release/lwcb。
3. 此外,lwcb 運行還需要 BTF 文件,可以從該網址(https://mirrors.openanolis.cn/coolbpf/btf/)下載對應內核的 BTF 文件,然後放在 /boot 目錄下。
lwcb 執行單行命令
lwcb -t <TEXT> 可以直接運行單條命令形式的 eBPF 程序,如:
lwcb -t 'kprobe:tcp_rcv_established {print("%s :triggerred by tcp_rcv_established\n", timestr(ns()));}
lwcb 執行腳本
lwcb <*.cb> 可以直接執行腳本。在 coolbpf/tools/lwcb 目錄已經有若干個 lwcb 腳本,我們可以通過命令:lwcb tcpdrop.cb 來執行 tcpdrop 腳本。03pylwcb:lwcb 的 python 模塊pylwcb 是 lwcb 的 python 模塊。通過 pylwcb 我們可以使用 lwcb 提供的腳本化能力,同時可以利用 python 強大的數據處理能力。04pylwcb 使用方法
編譯 pylwcb
1. 編譯環境準備
a. 進入到 pylwcb 項目目錄:cd coolbpf/lwcb/pylwcb。
b. 創建獨立的 python 虛擬環境:python -m venv .env。
c. 激活該開發虛擬環境:source .env/bin/activate。
d. 安裝 pylwcb 編譯環境依賴的 python 庫:pip install tomli && pip install setuptools_rust && pip install maturin。
2. 編譯 pylwcb:我們可以通過命令:maturin develop 來編譯 pylwcb,進而生產相應的 python 模塊。一般生成的 python 模塊所在目錄是:.env/lib64/python3.6/site-packages/。
使用 pylwcb
下面是一個簡單的 pylwcb 腳本示例:
import pylwcb
lwcb_program = """
kprobe:tcp_rcv_established {
th = tcphdr(skb);
ih = iphdr(skb);
print(ntop(bswap(ih->saddr)), ntop(bswap(ih->daddr)), bswap(th->source), bswap(th->dest));
}
"""
lwcb = pylwcb.Pylwcb(lwcb_program)
lwcb.attach()
events = lwcb.read_events()
for event in events:
print(event)
- lwcb_program 存放了 lwcb 腳本代碼,其主要功能是探測內核的 tcp_rcv_established 函數,打印 tcp 接收到報文的四元組,即源地址、目的地址、源端口和目的端口。
- lwcb = pylwcb.Pylwcb(lwcb_program) 創建了 Pylwcb 實例。
- lwcb.attach() 編譯並加載 eBPF 程序。
- lwcb.read_events() 讀取 eBPF 程序的輸出。
相關閱讀
lwcb 文檔:
https://coolbpf.readthedocs.io/en/latest/lwcb/index.html
pylwcb 文檔:
https://coolbpf.readthedocs.io/en/latest/pylwcb/index.html
相關鏈接
eBPF技術探索 SIG 主頁:https://openanolis.cn/sig/ebpfresearch
文/eBPF技術探索 SIG
本文爲阿里雲原創內容,未經允許不得轉載。