原文連結 Learn eBPF Tracing: Tutorial and Examples 譯者 棄餘
在 LPC'18(Linux Plumber's conference) 會議上,至少有24個關于 eBPF 的演講。 eBPF 這一實用技術,将是每個開發者需要掌握的技巧。 也許你的新年目标得再多一個了:學習 eBPF!
eBPF 的名稱源于 extended Berkeley Packet Filter,如果從 eBPF 的功能來說,類似 Virtual Kernel Instruction Set (VKIS) 這樣的名字似乎跟貼切。 eBPF 可以用來做很多事情,比如網絡性能(network performance),防火牆(firewalls),安全(security),程式分析追蹤(tracing) 和 裝置驅動(device drivers) 等。其中,諸如 tracing 等功能在網絡上已經有很多資料。這裡的術語 tracing 特指可以生成 per-event 資訊的性能分析和觀察工具,例如
tcpdump
和
strace
就是兩個常用的 tracer。
這篇文章将着重于 eBPF tracing 的學習,并分為 beginner, intermediate, advanced 三個階段,大綱如下:
Beginner
1. eBPF, bcc, bpftrace, iovisor 是什麼
eBPF 之于 Linux 一定程度上如同 JavaScript 之于 HTML。JavaScript 使得網頁不再是靜态的,它可以讓你編寫程式來監聽滑鼠點選等事件,而且程式運作在浏覽器的安全虛拟環境中;類似的,有了 eBPF,核心也可以不是固定的(fixed),你可以編寫程式來監聽 disk I/O 事件并執行相關動作,而且程式運作在核心的安全虛拟環境中。實際上,eBPF 更像是運作 JavaScript 的 V8 引擎,而不是像 JavaScript 本身。eBPF 是 Linux Kernel 的一部分。
直接 eBPF 編碼難于上青天,就好比直接編寫 V8 位元組碼。但是沒有人直接寫 V8 位元組碼,他們用 JavaScript,或者基于 JavaScript 的架構(jQuery, Angular, React 等)。eBPF 也是一樣,人們通過架構來使用 eBPF。對于 tracing 來說,主要的架構就是
,這兩個架構并不在核心代碼中,他們在名為 iovisor 的 Linux Foundation project 中維護。
2. eBPF tracing 示例
tcplife
是一個基于 eBPF 的工具,可以顯示完整的 TCP session, 以及對應的程序号(PID) ,指令(COMM),收發位元組數(TX_KB, RX_KB),以及時長(MS):
# tcplife
PID COMM LADDR LPORT RADDR RPORT TX_KB RX_KB MS
22597 recordProg 127.0.0.1 46644 127.0.0.1 28527 0 0 0.23
3277 redis-serv 127.0.0.1 28527 127.0.0.1 46644 0 0 0.28
22598 curl 100.66.3.172 61620 52.205.89.26 80 0 1 91.79
22604 curl 100.66.3.172 44400 52.204.43.121 80 0 1 121.38
22624 recordProg 127.0.0.1 46648 127.0.0.1 28527 0 0 0.22
3277 redis-serv 127.0.0.1 28527 127.0.0.1 46648 0 0 0.27
22647 recordProg 127.0.0.1 46650 127.0.0.1 28527 0 0 0.21
3277 redis-serv 127.0.0.1 28527 127.0.0.1 46650 0 0 0.26
[...]
并不是 eBPF 才使得這樣的工具成為可能,完全可以利用其他核心技術特性重寫
tcplife
。但是如果這麼做了,我們将因為性能開銷、安全等因素而無法在生産環境中運作這個工具。eBPF 做的恰恰是讓這個工具變得實用,
tcplife
是高效并且安全的。舉例來說,
tcplife
并不會像其他核心技術特性一樣去追蹤每個網絡包(packet),那樣會帶來太多的性能開銷。相反地,
tcplife
隻追蹤 TCP session 事件,這類事件相對來說頻率較低。這使得
tcplife
的負載極低,以至于我們可以在生産環境中24小時持續運作這個工具。
3. 如何使用 eBPF
對于初學者,嘗試一下 bcc tools。bcc 的安裝很簡單,并有詳細的
說明文檔,例如在 Ubuntu 上,效果如下
# sudo apt-get update
# sudo apt-get install bpfcc-tools
# sudo /usr/share/bcc/tools/opensnoop
PID COMM FD ERR PATH
25548 gnome-shell 33 0 /proc/self/stat
10190 opensnoop -1 2 /usr/lib/python2.7/encodings/ascii.x86_64-linux-gnu.so
10190 opensnoop -1 2 /usr/lib/python2.7/encodings/ascii.so
10190 opensnoop -1 2 /usr/lib/python2.7/encodings/asciimodule.so
10190 opensnoop 18 0 /usr/lib/python2.7/encodings/ascii.py
10190 opensnoop 19 0 /usr/lib/python2.7/encodings/ascii.pyc
25548 gnome-shell 33 0 /proc/self/stat
29588 device poll 4 0 /dev/bus/usb
^C
這裡我通過運作
opensnoop
來驗證 bcc tools 是否工作,如果你順利到這一步,說明你已經在使用 eBPF 了!
Netflix 和 Facebook 等公司已經在伺服器上預設安裝 bcc ,或許你也想這麼做。
4. 初學者入門教程
Brendan Gregg 提供了一個
bcc 入門教程,友善初學者很好地開始 eBPF tracing.
作為初學者,你不必開發 eBPF 代碼。bcc 自帶超過 70 多個工具可以直接使用。bcc 入門教程裡你将接觸 其中 11 個工具:execsnoop, opensnoop, ext4slower (or btrfs, xfs, zfs), biolatency, biosnoop, cachestat, tcpconnect, tcpaccept, tcpretrans, runqlat, and profile.
一旦你開始入門,你需要清楚 bcc tracing 工具還有很多:

這些工具都有很詳細的文檔,包括使用手冊和示例。示例檔案(xxx_example.txt)展示了螢幕截圖和對應的解釋:比如
biolatency_example.txt. Brendan Gregg 撰寫了許多類似的示例文檔、使用手冊、工具,都在
bcc repo中。
生産環境中的 bcc tracing 示例沒有提供,Brendan Gregg 在撰寫這篇文檔時,eBPF 剛發展起來并隻在測試機器上可用,是以大多數使用示例都是構造的測試用例。之後這個教程裡會提供真實世界的用例,這是初學者可以貢獻的方向:如果你通過 bcc 工具解決了一個實際問題,考慮釋出一個部落格文章來共享螢幕截圖,或者添加到 bcc repo 的 examples 檔案中。
Intermediate
到這裡,你應該已經可以運作 bcc 并嘗試了上述工具,然後你肯定會想定制開發自己的 bcc 工具。最佳實踐是切換到 bpftrace,bpftrace 提供進階語言可以使得入門開發更簡單。壞處就是 bpftrace 不如 bcc 那麼拓展友好。是以,你最終還是會遇到瓶頸,繼而切換回 bcc。
參考
bpftrace 安裝說明,bpftrace 是不同于 bcc 的另一個項目。此時 bpftrace 還沒有在各個平台打包釋出。在不久的将來,可以很友善地通過類似
apt-get install bpftrace
的方式來安裝。
1. bpftrace 教程
Brendan Gregg 開發一個了
bpftrace 教程,通過一系列指令來學習 bpftrace,一共有 12 個示例循序漸進。
其中一個示例的截圖如下,這裡使用
open
syscall tracepoint 來跟蹤 PID 和對應的打開檔案路徑。
# bpftrace -e 'tracepoint:syscalls:sys_enter_open { printf("%d %s\n", pid, str(args->filename)); }'
Attaching 1 probe...
181 /proc/cpuinfo
181 /proc/stat
1461 /proc/net/dev
1461 /proc/net/if_inet6
^C
2. bpftrace 參考指南
關于 bpftrace 的更多參考資訊,Brendan Gregg 整理了一個
參考指南,提供了關于 bpftrace 的文法、探針、内建等的示例。
這個參考指南的目的很簡單:Brendan Gregg 盡可能地把主題、摘要、截圖都放在一個螢幕上。如果你查找一些東西,需要滾動浏覽多頁,那就太長了。
3. bpftrace 示例
bpftrace repo 中有 20 多個
,可以通過這些工具來學習開發。例如:
# cat tools/biolatency.bt
[...]
BEGIN
{
printf("Tracing block device I/O... Hit Ctrl-C to end.\n");
}
kprobe:blk_account_io_start
{
@start[arg0] = nsecs;
}
kprobe:blk_account_io_completion
/@start[arg0]/
{
@usecs = hist((nsecs - @start[arg0]) / 1000);
delete(@start[arg0]);
}
和 bcc 工具一樣,bpftrace 工具也有完整的使用手冊和示例文檔,例如
。
Advanced
1. 學習 bcc 開發
Brendan Gregg 提供了兩個幫助文檔:
在
bcc/tools/*.py
中有很多示例。bcc tools 分為兩大部分:1)面向核心的 BPF 代碼,用 C 語言開發;2)使用者态工具,用 Python (lua, C++) 等語言開發。開發 bcc tools 一定程度來說是高階的,可能會深入複雜的核心或應用程式的内部。
2. 貢獻開源
bcc/bpftrace issues 歡迎大家讨論解決:
對于 bpftrace, Brendan Gregg 給了
bpftrace internals development guide. 這裡的開發很有挑戰,因為涉及到 LLVM IR 的知識。
可以貢獻代碼的還有 kernel eBPF (aka BPF) 引擎。如果你浏覽 bcc/bpftrace issues,你會看到一些相關的優化需求,例如
bpftrace kerneltag 标記的 issues。同時,你還可以關注訂閱
netdev郵件清單,進而獲得最新的 kernel BPF 開發進展。這些新開發的代碼會進入 net-next 分支,然後合并入 Linux 主分支。
除了開發代碼,你還可以通過測試、打包、部落格、演講等方式來貢獻。
Summary
eBPF 可以勝任很多事情。這篇文章介紹如何利用 eBPF 來跟蹤問題和性能分析。總的來說:
- Beginner: 運作 bcc tools
- Intermediate: 開發 bpftrace tools
- Advanced: 開發 bcc tools,給 bcc/bpftrace 社群貢獻代碼。
Brendan Gregg 将上述内容整合到一個頁面中,
eBPF Tracing Tools,加油!