分布式集群可能会遇到性能问题或不可预测的故障,尤其是当它们在云中运行时。在所有类型的故障中,内核故障可能是最难分析和模拟的。
实用的解决方案是Berkeley数据包筛选器(BPF),它是一种高度灵活,高效的虚拟机,可在Linux内核中运行。它允许字节码在各种钩子中安全执行,这些钩子存在于各种Linux内核子系统中。 BPF主要用于网络,跟踪和安全性。
BPF编译器集合(BCC)工具包提供了许多有用的资源和示例,以构建有效的内核跟踪和操作程序。但是,它有缺点。
libbpf + BPF CO-RE(一次编译–随处运行)是与BCC框架不同的开发和部署模式。它大大减少了存储空间和运行时开销,这使BPF支持更多的硬件环境,并且优化了程序员。开发经验。
在这篇文章中,我将介绍为什么libbpf-tools(一个基于libbpf + BPF CO-RE模式的应用程序集合)比bcc-tools更好的解决方案,以及我们如何在以下位置使用libbpf-tools PingCAP。
BCC嵌入LLVM或Clang来重写,编译和加载BPF程序。尽管它尽最大努力简化BPF开发人员。工作,它具有以下缺点:
它使用Clang前端来修改用户编写的BPF程序。出现问题时,很难找到问题并找出解决方案。
因为libbcc库包含一个庞大的LLVM或Clang库,所以在使用它时,可能会遇到一些问题:
工具启动时,需要很多CPU和内存资源来编译BPF程序。如果它在缺少系统资源的服务器上运行,则可能会引发问题。
BCC取决于内核标头程序包,您必须在每个目标主机上安装该程序包。如果内核中需要未导出的内容,则必须手动将类型定义复制并粘贴到BPF代码中。
由于BPF程序是在运行时编译的,因此许多简单的编译错误只能在运行时检测到。这会影响您的开发经验。
实现BPF CO-RE时,可以直接使用内核开发人员提供的libbpf库来开发BPF程序。开发方法与编写普通的C用户模式程序相同:一个编译会生成一个小的二进制文件。
Libbpf的行为类似于BPF程序加载器,并重新定位,加载和检查BPF程序。 BPF开发人员只需要关注BPF程序。正确性和性能。
这种方法最大程度地减少了开销并消除了巨大的依赖关系,从而使整个开发过程更加顺畅。
性能优化大师Brendan Gregg使用libbpf + BPF CO-RE转换了BCC工具并比较了它们的性能数据。他说:"正如我的同事Jason指出的那样,由于CO-RE,opensnoop的内存占用量远远低于opensnoop.py。 CO-RE为9 MB,而Python为80 MB。"
根据他的研究,与运行时的BCC相比,libbpf + BPF CO-RE将内存开销减少了近9倍,这为物理内存不足的服务器带来了极大的好处。
在PingCAP,我们一直关注BPF及其社区的发展。过去,每次添加新计算机时,都必须在该计算机上安装一组BCC依赖项,这很麻烦。在Andrii Nakryiko(libbpf + BPF CO-RE项目的负责人)将第一个libbpf-tools添加到BCC项目之后,我们进行了研究,并从bcc-tools切换到libbpf-tools。幸运的是,在转换期间,我们得到了他,Brendan和Song Yonghong(BTF项目负责人)的指导。我们已经将18个BCC或bpftrace工具转换为libbpf + BPF CO-RE,并且在我们公司中正在使用它们。
例如,当我们分析特定工作负载的I / O性能时,我们在块层使用了多个性能分析工具:
分析结果帮助我们优化了I / O性能。我们还在探索与调度程序相关的libbpf工具是否对调整TiDB数据库有用。
这些工具具有通用性:请随时尝试。将来,我们将基于libbpf-tools实施更多工具。如果您想详细了解我们在这些工具上的经验,可以加入Slack上的TiDB社区。