天天看點

輕量易部署!Coolbpf 釋出不依賴 Clang 的腳本化程式設計特性 lwcb

輕量易部署!Coolbpf 釋出不依賴 Clang 的腳本化程式設計特性 lwcb

文/eBPF技術探索 SIG

基于 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 也讓使用者友善地添加更多的内置函數,覆寫更多應用場景。

01lwcb 特性

輕量級、易部署

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")));
  }
}           

02lwcb 使用方法

隻需要更新 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 檔案,可以從該網址下載下傳對應核心的 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

—— 完 ——