使用 Go 语言管理和分发 ebpf 程序
1. Go 语言管理 eBPF 程序库
1.1 cilium/ebpf
cilium/ebpf
库是 Cilium
项目的一个子项目。仅使用 Go 语言编写的库,提供了加载、编译和调试 eBPF 程序的功能。它具有最小的外部依赖性,适合在长期运行的进程中使用。库主要有由 Cloudflare 和 Cilium 两家公司维护,由于 Cilium
产品的火爆程度,该库的活跃度在社区层面还是会持续演进和发展。
cilium/ebpf
已经满足生产可用,但 API 现在显然是不稳定的,编写的程序升级时可能需要进行部分调整。cilium/ebpf
使用样例参考这里。该库提供的 cmd/bpf2go
工具允许在 Go 代码中编译和嵌入 eBPF 程序。
通过 go 语言注解来自动进行 eBPF 代码的编译。
1.2 iovisor/gobpf
iovisor/gobpf
项目为著名 eBPF 项目 BCC 的一个子项目。该库提供了 bcc 框架的 Go 语言绑定,可以在底层使用 .elf
格式文件加载和调试 eBPF 程序,底层依赖于 libbcc
库,使用前需要提前安装。iovisor/gobpf
使用样例参考这里。
可以在 weaveworks/tcptracer-bpf
项目中查看到使用方式。
1.3 dropbox/goebpf
dropbox/goebpf
一个使用方便操作 eBPF 程序和读取 Perf 事件的 Go 语言库。dropbox/goebpf
使用样例参考这里。
1.4 aquasecurity/libbpfgo
libbpfgo 是 Linux 的 eBPF 项目的 Go 库,目前主要在 Tracee 项目中使用,用于创建开源运行时安全性和 eBPF 跟踪工具。
1.5 仓库对比(截止到 2021-08-10)
update: 2021-11-29
仓库名 | 描述 | 贡献者/核心贡献者 | 创建时间 | 更新时间 | stars | forks | open issues | size(Byte) | 备注 |
---|---|---|---|---|---|---|---|---|---|
cilium/ebpf | eBPF Library for Go | 43/7 | 2019-09-05 | 2021-08-10 | 1523 | 149 | 21 | 9655K | 纯 Go 语言实现 |
dropbox/goebpf | Library to work with eBPF programs from Go | 8/1 | 2019-01-24 | 2021-08-08 | 723 | 51 | 6 | 1786K | 底层依赖libbpf( cgo) |
iovisor/gobpf | Go bindings for creating BPF programs. | 49/3 | 2016-11-18 | 2021-08-10 | 1409 | 250 | 58 | 520K | 底层依赖 libbcc/libbpf(cgo) |
aquasecurity/libbpfgo | eBPF library for Go, wrapping libbpf | 8/2 | 2020-11-8 | 2012-08-10 | 150 | 28 | 23 | 475K | 底层依赖 libpf(cgo) |
核心贡献者,按照提交 commits 超过 10 个以上计算
库贡献者的活跃度
总结: cilium/ebpf
> iovisor/gobpf
> dropbox/goebpf
> aquasecurity/libbpfgo
aquasecurity/libbpfgo (update 2021-11-29)
2. 样例代码测试
2.1 库选择
这里,我们使用 cilium/ebpf
来进行测试,主要是因为项目活跃度高并且为纯 Go 程序编写,从而实现了程序最小依赖;于此同时其还提供了 bpf2go
工具,可用来将 eBPF 程序编译成 Go 语言中的一部分,使得交付更加方便,后续如果配合 CO-RE 功能则威力大增。
2.2 样例代码结构
eBPF 程序一般有两部分组成:
- 基于 C 语言的 eBPF 程序,最终使用
clang/llvm
编译成elf
格式的文件,为内核中需要加载的程序; - Go 语言程序用于加载、调试 eBPF 程序,为用户空间的程序,用于配置或者读取 eBPF 程序生成的数据。
样例测试环境如下:
|
|
前置条件需要安装 clang/llvm
编译器:
|
|
example 目录中,kprobe
代码结构如下:
|
|
主要为两个目录, headers
和 kprobe
,其中:
headers
保存了 bpf 程序的头部依赖,为生成 CO-RE 方式下生成vmlinux.h
文件的精简版;kprobe
中分为 bpf 程序bpf/kprobe_example
和用户态程序main.go
;
在 main.go 文件中,有行注解:
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc clang-11 KProbeExample ./bpf/kprobe_example.c -- -I../headers
该注解使用
bpf2go
程序将kprobe_example.c
文件编译成kprobeexample_bpfeb.go
和kprobeexample_bpfel.go
两个文件,分别为bigendian
和littleendian
两种平台的程序。其中参数中的
KProbeExample
参数为main.go
文件中函数调用的名称,例如objs := KProbeExampleObjects{}
和LoadKProbeExampleObjects(&objs, nil);
2.3 kprobe 样例代码测试
在 examples
目录执行 go run -exec sudo ./kprobe
即可运行 eBPF 程序:
|
|
我们也可以到 examples/kprobe
目录下执行 go build -o main
命令,生成可交付文件 main
,后续只需要拷贝该文件即可实现二进制程序的分发 ,但是请注意的是我们没有使用 CO-RE 特性,因此还是需要内核环境一致情况下才能正常运行。
2.4 错误解决
|
|
在当前终端执行:
|
|
再次执行,就可以正常工作。
3. 总结
cilium/ebpf 通过生成中间代码的思路与 libbpf-bootstrap 的思路基本一致,简化了部分中间过程,让开发者更加聚焦。
libbpf-bootstrap 主要是还是聚焦在 C 代码层面,需要用户自己编写 C 语言生成 elf
文件的 Makefile 文件,从这点看 cilium/ebpf
中的 cmd/bpf2go
工具通过注解的方式解决了这个问题,屏蔽了细节,利于快速上手,但是从某种程度上对于高级用户也屏蔽了一定的灵活性。
libbpf-bootstrap
脚手架的使用可以阅读这篇博客。
- 原文作者:DavidDi
- 原文链接:https://www.ebpf.top/post/ebpf_go/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议. 进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。
- 最后更新时间:2022-11-05 21:36:51.98358585 +0800 CST