近日,在‖2022云栖大会龙蜥峰会eBPF&LinuxStabilitySession上,来自eBPF技术探索SIGMaintainer的毛文安分享了技术演讲《Coolbpf 的应用实践》。以下为本次演讲内容:1、为什么支持便携性?随着BPF技术的发展,开发BPF程序变得更加容易。虽然BPF提高了便利性,但BPF也一直在追求另一个方面:便携性。BPF可移植性定义为成功编写并经内核验证的BPF程序可以在不同的内核版本上运行。移植BPF有两个挑战:数据在不同内核版本中的内存布局不同。内核类型和数据结构在不断变化,结构字段可能会被删除或重命名。BPFCO-RE(CompileOnce-RunEverywhere)是一种实现可移植性的手段。为了支持CORE,提供了以下组件:BTF:描述内核镜像,获取内核关键信息和BPF程序类型和代码Clang将bpf程序重定位信息发布到libbpfCO-RE需要的.btf段根据.btf段重定位bpf程序重定位的信息主要有以下三种:结构相关的重定位,与BTF密切相关。Clang通过__builtin_preserve_access_index()记录成员偏移量。mapfd、全局变量(data、bss、rodata)、extern的变量重定位主要是依赖ELF的重定位机制来更新eBPF指令的imm字段。Subfunctionrelocation就是把eBPF程序调用的子函数和main函数放在一起,这样就可以一起加载到内核中。使用libbpf开发BPFCORE的步骤如下:1.生成包含所有core类型的头文件vmlinux.h,由bpftool生成。使用Clang(10或更新版本)将BPF程序的源代码编译成.o目标文件;从bpftoolgen命令生成的已编译BPF目标文件生成BPF骨架头文件;在用户空间代码头文件中包含生成的BPF框架;编译用户空间代码,然后嵌入BPF目标代码而不发布单独的文件。大致有以下函数调用:__open():创建并打开一个BPF应用,然后设置skel->rodata变量。__load():初始化、加载和验证BPF应用程序部分。__attach():附加所有可以自动附加的BPF程序。当有事件和网络操作包到达时,会触发bpf程序运行。__destroy():分离所有BPF程序并使用它们使用的所有资源。eBPF程序的开发方式主要有3种,各有优缺点,具体如下:1.内核自带样例代码:基于kernelsamples/bpf样例代码,无CORE。该方法没有任何第三方开源项目,资源占用低。但缺点是需要自己完全重建工程,效率低,版本兼容性差。2.BPFCORE:开发机基于libbpf自己编写的bpf_core_read代码,生成目标机对应的二进制程序。该方法不依赖于环境中部署Clang/LLVM,消耗资源少。但是需要构建一个编译工程,有些代码比较固定,不能动态配置。3.BCC:基于目前使用最广泛的开源项目,开发效率高。但Clang/LLVM编译每次运行都要执行,存在内存、CPU等资源竞争;目标环境取决于相应的内核头文件。二、Coolbpf的功能结构Coolbpf提供远程编译(云编译)。其中,远程编译是指运行程序的目标机器与编译后的程序不在同一台机器上,可以解决资源占用问题;提供本地编译和基础库打包,方便用户调用基础库进行编写;它提供对低版本内核的支持;BTF自动生成和发布,用户无需手动适配,直接下载使用;提供自动化测试,支持Python/Go/Rust等高级语言进行应用开发。Coolbpf天然支持BPF的CORE能力,解决了编译和资源消耗的问题。同时,完全简化了上面介绍的复杂的libbpf开发步骤。用户只需专注于自己的功能开发,无需关注环境搭建和冗余代码开发。Coolbpf提供标准化的bpf编译服务。当先向远程编译服务器提交bpf.c时,服务器会针对不同的语言返回点bpf.so或bpf.o,根据内核版本为高级应用提供服务。因此,在你的高级语言代码中,只需要加载bpf.so即可运行程序,无需手动触发libbpf的open()、load()、attach()等函数,而是通过init()的高级语言程序自动完成,使用户可以快速构建和部署项目,而只需要专注于数据输出后的处理。Coolbpf也支持没有eBPF特性的低版本内核,通过我们提供的eBPF驱动帮助它在低版本上安全运行。我们在一个驱动中实现了高版本eBPF验证器的验证部分,它会进行各种安全验证,以保证eBPF相对于内核模块的安全性。此外,我们将原来基于libbpf的调用转换为IOCTL系统调用。之前支持的helperfunctions、mapcreation、programloading,在低版本上将转换为kprobe或tracepoint的实现,同时支持perfevent和jit。这样,同一个用户程序就可以安全地运行在低版本内核上,而无需通过加载这样的驱动来修改eBPF程序代码。3、Coolbpf的网络应用实践Raptor是基于Coolbpf的系统可观测性工具,可以运行在alios、CentOS3.10等低版本内核上。可作为SDK提供给第三方进行数据采集。在本次网络应用观察中,通过监听系统调用中的数据交互、请求和回复信息,确定交互数据内容和五元组信息,通过map的交互方式发送给用户态,从而实现非-IntrusiveObservations通过这种方式进行,最后呈现流量统计、请求时延等观察结果。下面我们来看一个具体的问题,了解一下Coolbpf是如何在收包阶段发现网络抖动问题的。我们知道网络收包分为两个阶段:Stage1:OS通过软中断将数据包发送到应用程序收包队列,并通知进程完成协议栈的收包工作。阶段2:应用程序接到通知后,从接收队列中取数据。我们在Coolbpf中写了一个BPF程序,只需要监控两个tracepoint:tcp_probe和tcp_rcv_space_adjust来查询阶段2的延迟问题。此时业务应用收包慢,发现内核端收到了tcp数据包,但是应用端在将近1秒后才收到。观察方法:部署eBPF代理,发现第2阶段的“接收包延迟时间”接近1秒。判断原因:每次延迟时间都出现在某个时间42秒左右,怀疑与业务的某个定时任务有关,导致应用本身延迟。最后发现业务的某个任务会定时采集jvm参数,这对业务停止运行有重要意义。解决方法:停止任务后,抖动问题消除。相关链接:eBPF技术探索SIG地址:https://openanolis.cn/sig/ebp...关于龙蜥峰会eBPF&LinuxStability专题课件获取方式:【PPT课件获取】:关注微信公众号(OpenAnolis),回复“龙蜥课件”获取。如有任何问题,欢迎随时咨询龙蜥小助手——小龙(微信:openanolis_assis)。【视频播放】:可到龙蜥官网观看视频播放。-超过-