BPF二进制文件:BTF、CO-RE和BPF性能工具的未来

2020-11-05 20:03:34

两项新技术,BTF和CO-RE,正在为BPF成为一个价值数十亿美元的产业铺平道路。目前,有许多BPF初创公司正在构建网络、安全和性能产品(以及更多隐蔽的产品),但要求客户安装LLVM、Clang和内核头部依赖项--这可能会消耗超过100兆字节的存储--会拖累客户的采用。BTF和CO-RE在运行时消除了这些依赖,不仅使BPF在嵌入式Linux环境中更加实用,而且在任何地方都可以采用。

Btf:bpf类型格式,提供结构信息以避免需要Clang和内核头。

CO-RE:BPF一次编译到处运行,它允许编译后的BPF字节码可重定位,避免了LLVM重新编译的需要。

Clang和LLVM仍然是编译所必需的,但是结果是一个轻量级的ELF二进制文件,它包含预编译的BPF字节码,可以在任何地方运行。BCC项目有一组这样的工具,称为libbpf工具。作为一个例子,我移植到了我的opensnoop(8)工具上:

#./opensnoopPID comm FD err PATH27974 opensnoop 28 0/etc/localtime1482 redis-server 7 0/proc/1482/stat1657 atlas-system-ag 3 0/proc/stat[…]。

#file opensnoopensnoop:ELF 64位LSB共享对象,x86-64,版本1(SYSV),动态链接,解释器/lib64/l,适用于GNU/Linux3.2.0,带DEBUG_INFO的BuildID[sha1]=b4b5320c39e5ad2313e8a371baf5e8241bb4e4ed,,未剥离#LDD opensnoop linux-vdso.so.1(0x00007fff3f1000)libelf.so.1=>;/usr/lib/x86_64-linux-gnu/libel.so.1(0x00007fff3f1000)libelf.so.1=>;/usr/lib/x86_64-linux-gnu/libel.。/lib/x86_64-linux-gnu/libz.so.1(0x00007f9fb7619000)libc.so.6=>;/lib/x86_64-linux-gnu/libc.so.6(0x00007f9fb7228000)/lib64/ld-linux-x86-64.so.2(0x00007f9fb7c76000)#ls-lh opensnoop。

现在设想一个BPF产品:不需要客户安装各种重量级(和脆弱的)依赖项,BPF代理现在可以是在任何具有BTF的内核上工作的单个微型二进制文件。

这不仅仅是将BPF字节码保存在ELF中,然后将其发送到任何其他内核的问题。许多BPF程序遍历内核结构,这些结构可以从一个内核版本更改到另一个内核版本。您的BPF字节码可能仍然在不同的内核上执行,但它可能读取错误的结构偏移量并打印垃圾输出!Opensnoop(8)不遍历内核结构,因为它检测稳定的跟踪点及其参数,但很多其他工具都是这样做的。

这是一个重新定位的问题,BTF和CO-RE都为BPF二进制文件解决了这个问题。BTF提供类型信息,以便可以根据需要查询结构偏移量和其他细节,CO-RE记录BPF程序的哪些部分需要重写,以及如何重写。Co-RE开发人员Andrii Nakryi ko写了一篇长篇文章,更深入地解释了这一点:BPF便携性和CO-RE和BTF类型信息。

只有在设置了此内核配置选项的情况下,这些新的BPF二进制文件才有可能。它给内核镜像增加了大约1.5兆字节(与矮小的调试信息相比,这是微不足道的,后者可能是几百兆字节)。Ubuntu20.10已经将此配置选项设为默认选项,所有其他发行版也应该效仿。请发行版维护人员注意:它需要pahole>;=1.16。

对于BPF性能工具,您应该从运行bcc和bpftrace工具开始,然后在bpftrace中编码。密件抄送工具最终应该在幕后从Python切换到libbpf C,但工作原理是一样的。在我们使用BTF和CO-RE迁移到libbpf C时,BCC Python中的编码性能工具现在被认为是不推荐使用的(尽管我们还有库工作要做,比如支持USDT,所以在一段时间内还需要使用Python版本)。请注意,BCC还有其他可能继续使用Python接口的用例;BPF的共同维护者Alexei Starovoitov和我在iovisor-dev上简要讨论了这一点。

我的《BPF性能工具》一书专注于运行Bcc工具和在bpftrace中编码,这一点没有改变。然而,附录中的Python编程示例现在被认为是不推荐使用的。很抱歉给您带来不便。幸运的是,在这本880页的书中,附录材料只有15页。

那么bpftrace呢?它确实支持BTF,未来我们也在考虑减少它的安装空间(目前它可以达到29MB,我们认为它可以小得多)。假设libbpf程序的平均大小为229K字节(基于当前的libbpf工具,已剥离),而bpftrace程序的平均大小为1K字节(我的书中的工具),那么大量的bpftrace工具加上bpftrace二进制文件可能会比libbpf中的同等工具占用更少的安装空间。另外,bpftrace版本可以动态修改。Libbpf更适合需要自定义参数和库的更复杂、更成熟的工具。

#ls/usr/share/bcc/Tools/usr/sbin/*.btargdist drsnoop mdflush pythongc tclobjnewbashreadline execsnoop memleake pythonstat tclstat[...]/usr/sbin/bashreadline.bt/usr/sbin/mdflush.bt/usr/sbin/tcpcept.bt/usr/sbin/biolatency.bt。

#!/usr/bin/pythonfrom bcc导入bPFfrom bcc.utils导入printbprog=";";";int Hello(void*ctx){bpf_trace_printk(";Hello,World!\\n";);返回0;}";";";[...]。

感谢宋永红(Facebook)领导BTF的开发,感谢Andrii Nakryi ko(Facebook)领导CO-RE的开发,以及其他所有参与实现这一目标的人。

你可以在这里发表评论,但我不能保证你的评论会永远留在这里:我可能会在某个时候更换评论系统(例如,如果Disqus添加了广告)。

由Disqus提供支持的评论