在 LPC'18(Linux Plumber's conference) 會議上,至少有24個關於 eBPF 的演講。 eBPF 這一實用技術,將是每一個開發者須要掌握的技巧。 也許你的新年目標得再多一個了:學習 eBPF!html
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。python
這篇文章將着重於 eBPF tracing 的學習,並分爲 beginner, intermediate, advanced 三個階段,大綱以下:linux
eBPF 之於 Linux 必定程度上如同 JavaScript 之於 HTML。JavaScript 使得網頁再也不是靜態的,它可讓你編寫程序來監聽鼠標點擊等事件,並且程序運行在瀏覽器的安全虛擬環境中;相似的,有了 eBPF,內核也能夠不是固定的(fixed),你能夠編寫程序來監聽 disk I/O 事件並執行相關動做,並且程序運行在內核的安全虛擬環境中。實際上,eBPF 更像是運行 JavaScript 的 V8 引擎,而不是像 JavaScript 自己。eBPF 是 Linux Kernel 的一部分。ios
直接 eBPF 編碼難於上青天,就比如直接編寫 V8 字節碼。可是沒有人直接寫 V8 字節碼,他們用 JavaScript,或者基於 JavaScript 的框架(jQuery, Angular, React 等)。eBPF 也是同樣,人們經過框架來使用 eBPF。對於 tracing 來講,主要的框架就是 bcc 和 bpftrace,這兩個框架並不在內核代碼中,他們在名爲 iovisor 的 Linux Foundation project 中維護。git
tcplife
是一個基於 eBPF 的工具,能夠顯示完整的 TCP session, 以及對應的進程號(PID) ,命令(COMM),收發字節數(TX_KB, RX_KB),以及時長(MS):github
# 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小時持續運行這個工具。redis
對於初學者,嘗試一下 bcc tools。bcc 的安裝很簡單,並有詳細的說明文檔,例如在 Ubuntu 上,效果以下shell
# 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 ,或許你也想這麼作。安全
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 文件中。
到這裏,你應該已經能夠運行 bcc 並嘗試了上述工具,而後你確定會想定製開發本身的 bcc 工具。最佳實踐是切換到 bpftrace,bpftrace 提供高級語言可使得入門開發更簡單。壞處就是 bpftrace 不如 bcc 那麼拓展友好。所以,你最終仍是會遇到瓶頸,繼而切換回 bcc。
參考 bpftrace 安裝說明,bpftrace 是不一樣於 bcc 的另外一個項目。此時 bpftrace 尚未在各個平臺打包發佈。在不久的未來,能夠很方便地經過相似 apt-get install 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
關於 bpftrace 的更多參考信息,Brendan Gregg 整理了一個 參考指南,提供了關於 bpftrace 的語法、探針、內建等的示例。
這個參考指南的目的很簡單:Brendan Gregg 儘量地把主題、摘要、截圖都放在一個屏幕上。若是你查找一些東西,須要滾動瀏覽多頁,那就太長了。
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 工具也有完整的使用手冊和示例文檔,例如 biolatency_example.txt。
Brendan Gregg 提供了兩個幫助文檔:
在 bcc/tools/*.py
中有不少示例。bcc tools 分爲兩大部分:1)面向內核的 BPF 代碼,用 C 語言開發;2)用戶態工具,用 Python (lua, C++) 等語言開發。開發 bcc tools 必定程度來講是高階的,可能會深刻複雜的內核或應用程序的內部。
bcc/bpftrace issues 歡迎你們討論解決:
對於 bpftrace, Brendan Gregg 給了 bpftrace internals development guide. 這裏的開發頗有挑戰,由於涉及到 LLVM IR 的知識。
能夠貢獻代碼的還有 kernel eBPF (aka BPF) 引擎。若是你瀏覽 bcc/bpftrace issues,你會看到一些相關的優化需求,例如 bpftrace kernel tag 標記的 issues。同時,你還能夠關注訂閱 netdev 郵件列表,從而得到最新的 kernel BPF 開發進展。這些新開發的代碼會進入 net-next 分支,而後合併入 Linux 主分支。
除了開發代碼,你還能夠經過測試、打包、博客、演講等方式來貢獻。
eBPF 能夠勝任不少事情。這篇文章介紹如何利用 eBPF 來跟蹤問題和性能分析。總的來講:
Brendan Gregg 將上述內容整合到一個頁面中,eBPF Tracing Tools,加油!
原文連接 本文爲雲棲社區原創內容,未經容許不得轉載。