在 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,加油!
原文连接 本文为云栖社区原创内容,未经容许不得转载。