一、概要
eBPF程序当前的开发和分发过程中存几个痛点:
第一,对于新手而言,搭建和开发 eBPF程序的门槛较高,必须同时关注内核态和用户态两方面的交互和信息处理,还需要编写用户态加载代码。
第二,在不同架构的不同内核版本上无法方便快捷地打包、分发、发布各种eBPF程序。eBPF很多小工具由不同的语言开发,存在不同的接口,无法轻易集成到大型的可观测系统。
第三,当前没有很好的插件方案,很多时候必须重新编译整个可观测的框架,再重新部署上线,才能更新 ebpf 探针或数据处理模块。另外,如果引入第三方的用户态数据处理代码,代码崩溃会导致整个程序崩溃。
因此,我们提出了两种解决思路。
第一,针对初学者,只需要编写内核态代码即可自动获取内核态导出的数据,编译后即可进行加载和运行,降低了eBPF的学习成本,提高了开发效率。
第二,基于 libbpf一次编译处处运行的特性,将用户态和内核态的编译和运行的完全分离,通过标准 JSON 或WASM模块的方式进行分发,无需进行重新编译,应用启动占用资源少,时间短,甚至容器启动更短。
另外,我们希望能够提供标准化的分发方式,比如可以使用 JSON/ WASM 分发。WebAssembly是一种基于堆栈虚拟机的二进制格式,为了可移植的目标而设计。一开始的目的在于希望能够让C、C++、rust 编写的代码在浏览器里运行,到现在已经发展成为轻量级、高性能、跨平台和多语种的沙盒环境,可以运用于云原生的软件或组件。其设计思路与eBPF相似,区别在于运行在内核态或用户态。
我们尝试将两者做了结合,比如只编写内核态代码时,可直接将整个 eBPF程序打包成 JSON,其中包含各种配置信息,比如从内核态上报到用户态的数据内存布局信息,比如需要配置的全局变量等,使得仅通过 JSON 即可完成大部分内核态 eBPF程序的配置信息,并且可以正确地加载。
与WASM结合后,用户态通过 WASM对 eBPF程序进行打包,其中包含用户态的数据处理、配置信息、完整的命令、函数解析等,与eBPF一起分发。
二、示例
Eunomia并不是一个完整的系统,而是类似于开发库和开发框架,可以很轻松地嵌入coolbpf 工具链里,也可以作为开发库或开发框架嵌入其他程序。
可以通过一行命令从网页端直接下载预编译好的eBPF程序运行。使用 WebAssembly 或JSON模块的方式进行分发,部署时无需重新编译,启动速度很快。
图中为放入 URL 里的形式,也可以换成 OCI 镜像或 Docker 镜像,可以存储在 Docker 仓库或 github package ,使用方式与Docker基本一致,只需简单地执行pull、run即可运行,也可以将编译好的程序包 push 下去直接使用。
而相比于传统的 Docker 镜像,它的启动速度更快,同时也保留了 eBPF很重要的特性,可以轻松嵌入到其他程序作为子模块或插件使用。
通过Eunomia,只需编写内核态代码即可正确运行,能够最大程度减少新手的上手障碍,省略了用户态的加载框架编写,能够自动导出内核态 perf event 或 ring buffer 事件。另外,它与和原生 libbpf 完全兼容,可以获取libbpf tools的内核态代码,无需修改任何代码,可直接运行。
可以额外添加 tracepoint ,也可以通过注释的形式添加其他内容。使用容器打包编译工具链,无需担心环境配置问题,一行命令生成项目模板、一行命令编译。
完整的 eBPF工具通常会分为用户空间和内核空间两个部分。用户空间负责加载、读取内核态回传的统计信息以及配置信息,可以在WASM中编写用户态辅助程序。WASM本身是安全高效的用户态数据处理和控制逻辑,处于用户态时也无需担心会对其他应用程序造成干扰,且速度非常快。
用户可以用多种语言编写,比如C、C++、Go、Rust,最终均可被编译成WASM的形式。我们将内核态代码和用户态代码一起打包生成WASM模块,借助 WebAssembly 的相关生态帮助分发、管理 eBPF 程序,可嵌入大型应用中作为可编程模块或插件使用。
目前我们已经实现了将libbpf tools 里用libbpf 写的工具直接编译成WASM模块进行分发。
过程中最主要的困难在于 WebAssembly 的内存布局比如结构体的内存布局与eBPF完全不一样,因此 API 中可能会存在数据序列化或转译的开销。同时因为 WebAssembly本身在虚拟机的沙箱环境运行,可以访问的系统占用也受限,因此也必须经过额外的转换。
三、系统架构
架构底层依赖的是内核态和用户态的基础设施,比如libbpf 库和 kernel ,会提供相关的编译工具链,帮助生成 JSON 或打包成 WASM的模块,工具链本身使用了比如 Clang/LLVM、bpftool等工具。动态加载库可以独立使用,与WASM无关,可以根据 JSON 信息动态地加载 eBPF程序,在外面套一个HTTP 即可变为web 服务的形式,实现 kernel function as your service ,变为内核函数及服务的形态。
我们还实现了WASM抽象层,包含 API 规范,比如用于扩展 WASM的虚拟机WSAI 系统占用的访问形式或与eBPF交互的访问形式。还有基于 WASM定制的 libbpf 库、移植的辅助态程序以及序列化库等,用于在 WASM模块加载基于 libbpf 的 eBPF程序。
运行时库可以轻松进行替换,比如替换成WSI的 WASM运行时。除此之外,上层还实现了LMP、命令行工具、可观测性工具等。
关于龙蜥峰会 eBPF & Linux 稳定性专场课件获取方式:
【PPT 课件获取】:关注微信公众号(OpenAnolis),回复“龙蜥课件” 即可获取。有任何疑问请随时咨询龙蜥助手—小龙(微信:openanolis_assis)。
【视频回放】:视频回放可前往龙蜥官网https://openanolis.cn/video 查看。