当前位置:网站首页>eBPF系列学习(4)了解libbpf、CO-RE (Compile Once – Run Everywhe) | 使用go开发ebpf程序(云原生利器cilium ebpf )
eBPF系列学习(4)了解libbpf、CO-RE (Compile Once – Run Everywhe) | 使用go开发ebpf程序(云原生利器cilium ebpf )
2022-06-12 04:12:00 【西京刀客】
文章目录
一、了解libbpf
在使用libbpf前,先使用bcc对eBPF相关知识进行学习运行,学习曲线将更平滑。相对于bcc,libbpf与BPF CO-RE的实际编译部署的难度增大了。
1. BPF的可移植性CO-RE (Compile Once – Run Everywhere)
官方:BPF CO-RE (Compile Once – Run Everywhere)
参考URL: https://github.com/libbpf/libbpf#bpf-co-re-compile-once–run-everywhere
BPF的可移植性和CO-RE (Compile Once – Run Everywhere)
参考URL: https://www.cnblogs.com/charlieroro/p/14206214.html
eBPF 的内核无关是有限的,需要 eBPF 机制和开发者共同努力实现。除了 BCC 这种即时编译的方案,还有另外一种名为 CO-RE (Compile Once – Run Everywhere) 的编译方式,其核心依赖于 BTF(更加先进的 DWARF 替代方案)。
文章BPF Portability and CO-R 指出,为了提高BPF程序的便携性,即在不同内核版本上正常工作,而无需为每个特定内核重新编译的能力,社区提出了一个称为BPF CO-RE(Compile Once – Run Everywhere)的解决方案。
Libbpf+BPF CO-RE的理念是,BPF程序与任何"正常"用户空间程序没有太大区别:它们应该汇编成小型二进制文件,然后以紧凑的形式进行部署,以瞄准主机。Libbpf 扮演 BPF 程序装载机的角色,执行平凡的设置工作(重定位、加载和验证 BPF 程序、创建 BPF map、连接到 BPF 挂钩等),让开发人员只担心 BPF 程序的正确性和性能。这种方法将开销保持在最低水平,消除沉重的依赖关系,使整体开发人员体验更加愉快。
BPF CO-RE的目标是帮助BPF开发者使用一个简单的方式解决简单的可移植性问题(如读取结构体字段),并使用它来定位复杂的可移植性问题(如不兼容的数据结构,复杂的用户空间控制条件等)。使得开发者的BPF程序能够"一次编译–随处运行"
Libbpf supports building BPF CO-RE-enabled applications, which, in contrast to BCC, do not require Clang/LLVM runtime being deployed to target servers and doesn’t rely on kernel-devel headers being available.
Libbpf 支持构建 BPF CO-RE-enabled 的应用程序,与BCC相比,它不需要部署的Clang/LLVM运行时,并且不依赖 kernel-devel 内核头文件。
It does rely on kernel to be built with BTF type information, though. Some major Linux distributions come with kernel BTF already built in:
不过,它确实依靠内核来使用BTF类型信息构建。一些主要的Linux发行版本已内置的内核BTF:
Fedora 31+
RHEL 8.2+
OpenSUSE Tumbleweed (in the next release, as of 2020-06-04)
Arch Linux (from kernel 5.7.1.arch1-1)
Manjaro (from kernel 5.4 if compiled after 2021-06-18)
Ubuntu 20.10
Debian 11 (amd64/arm64)
如果您的内核不支持内置的BTF附带,则需要构建自定义内核。你需要:
- pahole 1.16+ tool (part of dwarves package), which performs DWARF to BTF conversion;
- kernel built with CONFIG_DEBUG_INFO_BTF=y option;
- you can check if your kernel has BTF built-in by looking for /sys/kernel/btf/vmlinux file:
$ ls -la /sys/kernel/btf/vmlinux
-r--r--r--. 1 root root 3541561 Jun 2 18:16 /sys/kernel/btf/vmlinux
要开发和构建BPF程序,您将需要Clang/LLVM 10+。默认情况下,以下发行版具有clang/llvm 10+打包:
- Fedora 32+
- Ubuntu 20.04+
- Arch Linux
- Ubuntu 20.10 (LLVM 11)
- Debian 11 (LLVM 11)
- Alpine 3.13+
2. libbpf和bcc性能对比
性能优化大师 Brendan Gregg 在用 libbpf + BPF CO-RE 转换一个 BCC 工具后给出了性能对比数据:
As my colleague Jason pointed out, the memory footprint of opensnoopas CO-RE is much lower than opensnoop.py. 9 Mbytes for CO-RE vs 80 Mbytes for Python.
这句话原文暂未找到,TODO!
我们可以看到在运行时相比 BCC 版本,libbpf + BPF CO-RE 版本节约了近 9 倍的内存开销。
3. 了解libbpf
摆脱对内核头文件的依赖
除了使用内核的BTF信息进行字段的重定位意外,还可以将BTF信息生成一个大(基于5.10.1版本生成的长度有106382行)的头文件(“vmlinux.h”),其中包含了所有的内核内部类型,可以避免对系统范围的内核头文件的依赖。可以使用如下方式生成vmlinux.h:
$ bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h
上述命令可以获得到一个可兼容的C头文件(即"vmlinux.h"),包含所有的内核类型("所有"意味着包含那些不会通过kernel-devel包暴露的头文件)。
当使用了vmlinux.h,此时就不需要依赖像#include <linux/sched.h>, #include <linux/fs.h>这样的头文件,仅需要#include "vmlinux.h"即可。该头文件包含了所有的内核类型:暴露了UAPI,通过kernel-devel提供的内部类型,以及其他一些更加内部的内核类型。
不幸的是,BTF(即DWARF)不会记录#define宏,因此在vmlinux.h中丢失一些常用的宏。但大多数通常不存在的宏可以通过libbpf的bpf_helpers.h(即libbpf提供的内核侧的库)头文件提供。
libbpf知道如何将BPF程序代码匹配到特定的内核。它会查看程序记录的BTF类型和重定位信息,然后将这些信息与内核提供的BTF信息进行匹配。 libbpf解析并匹配所有的类型和字段,更新必要的偏移以及重定位数据,确保BPF程序能够正确地运行在特定的内核上。如果一切顺利,则BPF应用开发人员会获得一个BPF程序,这种方式可以针对目标主机上的内核进行“量身定制”,就好像程序是专门针对这个内核编译的,但无需在应用程序中分发Clang以及在目标主机上的运行时中执行编译,就可以实现所有这些目标。
libbpf 是一个比BCC更新的 BPF 开发库,也是最新的 BPF 开发推荐方式!
4. libbpf 库
libbpf/bpftool 项目地址:https://github.com/libbpf/libbpf
libbpf库是基于C / C ++的通用eBPF库,提供了一些加载bpf程序的方法,封装了内核提供的bpf()系统调用。
eBPF 程序加载的本质是 BPF 系统调用,Linux 内核通过 BPF 系统调用提供 eBPF 相关的一切操作,比如:程序加载、map 创建删除等。常见的 loader 都是对这个系统调用的封装,部分 loader 提供更加原生接近系统调用的操作,部分 loader 则是进行了更多封装使得编程更便捷。
内核实现的 libbpf 库,封装了 BPF 系统调用,使得加载 BPF 程序更便捷。libbpf 不像 iproute2,它能够使 BPF 相关操作更为便捷,没有做过多封装。如果要将程序加载到内核,则需要自己实现一个用户态程序,调用 libbpf 的 API 去加载到内核。如果要复用 pinned 在 BPF 文件系统的 MAP,也需要用户态程序调用 libbpf 的 API,在加载程序时进行相关处理。
典型案例:Facebook 开源的 katran 项目使用 libbpf 加载 eBPF 程序。
构建基于libbpf的BPF应用需要使用BPF CO-RE的步骤
构建基于libbpf的BPF应用需要使用BPF CO-RE包含的几个步骤:
- 生成带所有内核类型的头文件vmlinux.h;
- 使用Clang(版本10或更新版本)将BPF程序的源代码编译为.o对象文件;
- 使用 libbpfgo 将其编译为二进制文件,加载到内核中并监听输出。
5. libbpf-bootstrap
原文链接:Building BPF applications with libbpf-bootstrap
开始使用 BPF 在很大程度上仍然令人生畏,因为即使为简单的"Hello World"般的 BPF 应用程序设置构建工作流,也需要一系列步骤,对于新的 BPF 开发人员来说,这些步骤可能会令人沮丧和令人生畏。这并不复杂,但知道必要的步骤是一个(不必要的)困难的部分。
libbpf-bootstrap 就是这样一个 BPF 游乐场,它已经尽可能地为初学者配置好了环境,帮助他们可以直接步入到 BPF 程序的书写。它综合了 BPF 社区多年来的最佳实践,并且提供了一个现代化的、便捷的工作流。libbpf-bootstrap 依赖于 libbpf 并且使用了一个很简单的 Makefile。对于需要更高级设置的用户,它也是一个好的起点。即使这个 Makefile不会被直接使用到,也可以很轻易地迁移到别的构建系统上。
二、使用go开发ebpf程序
ebpf的核心程序是通过c编写,clang进行编译的。在编译好ebpf程序后,我们需要将其加载到内核中。目前有很多个项目对ebpf的编写调试运行的流程进行了优化,比较有名的是bcc和libbpf。很多时候我们希望能够更加方便的进行程序编写和部署,也希望程序能够在不同的linux发行版和内核上使用(即BPF CO-RE),bcc的运行依赖内核的头文件,也引入了繁重的整个clang llvm工具链,libbpf只能使用C/C++进行外部程序的开发。
BCC、libbpf都主要使用 C 语言开发 eBPF 程序,而实际的应用程序可能会以多种多样的编程语言进行开发。所以,开源社区也开发和维护了很多不同语言的接口,方便这些高级语言跟 eBPF 系统进行交互。
BCC 就提供了 Python、C++ 等多种语言的接口,而使用 BCC 的 Python 接口去加载 eBPF 程序,要比 libbpf 的方法简单得多。
随着ebpf的发展,开源社区中也诞生了各种编程语言的开发库,特别是 Go 和 Rust 这两种语言,其开发库尤为丰富。
1. Go 语言开发库以及选择
使用 Go 语言管理和分发 ebpf 程序
参考URL: https://www.ebpf.top/post/ebpf_go/
目前使用 Go 开发 eBPF 程序可以使用的框架有 IO Visor-gobpf、Dropbox-goebpf和 Cilium-ebpf等,考虑到 Cilium 的社区活跃度和未来的发展,使用 Cilium 的 ebpf 是一个比较不错的选择。

每个库都有各自的范围和限制:
- Calico 在用 bpftool 和 iproute2 实现的 CLI 命令基础上实现了一个 Go 包装器。
- Aqua 实现了对 libbpf C 库的 Go 包装器。
- Dropbox 支持一小部分程序,但有一个非常干净和方便的用户API。
- IO Visor 的 gobpf 是 BCC 框架的 Go 语言绑定,它更注重于跟踪和性能分析。
- Cilium 和 Cloudflare 维护一个 纯 Go 语言编写的库 (以下简称 “libbpf-go”),它将所有 eBPF 系统调用抽象在一个本地 Go 接口后面。
在使用这些 Go 语言开发库时需要注意,Go 开发库只适用于用户态程序中,可以完成 eBPF 程序编译、加载、事件挂载,以及 BPF 映射交互等用户态的功能,而内核态的 eBPF 程序还是需要使用 C 语言来开发的。
当涉及到选择库和工具来与 eBPF 进行交互时,会让人有所困惑。在选择时,你必须在基于 Python 的 BCC 框架、基于 C 的 libbpf 和一系列基于 Go 的 Dropbox、Cilium、Aqua 和 Calico 等库中选择。
库贡献者的活跃度
总结: cilium/ebpf > iovisor/gobpf > dropbox/goebpf > aquasecurity/libbpfgo
关于Cilium?
cilium
n. 纤毛;睫毛;
[例句]Cilium is the major power source of pallium to transport materials.
纤毛是外套膜进行物质运输的主要动力来源。
[其他] 复数:cilia
eBPF是一项革命性的技术,可以在Linux内核中运行沙盒程序,而无需重新编译内核或加载内核模块。在过去的几年中,eBPF已成为解决以前依赖于内核更改或内核模块的问题的标准方法。
eBPF 在动态跟踪、网络、安全以及云原生等领域的广泛应用。
Cilium是一个开源项目,它的基础是基于eBPF的Linux内核技术,用于透明地提供和保护使用Linux容器管理平台部署的应用程序服务之间的网络和API连接。以解决容器工作负载的新可伸缩性,安全性和可见性要求。Cilium超越了传统的容器网络接口(CNI),可提供服务解析,策略执行等功能。

Cilium已迅速成为Kubernetes生态系统中的领先技术,为Google Kubernetes Engine(GKE)提供了网络数据平面,并在其他领先的云原生最终用户(包括Adobe,DataDog,GitLab和DigitalOcean)中得到采用。
Cilium 母公司 Isovalent
Liz Rice,是Isovalent的首席开源官,这家公司是Cilium网络项目的幕后推手。也是CNCF技术监督委员会主席
Cilium 是一个用于容器网络领域的开源项目,主要是面向容器而使用,用于提供并透明地保护应用程序工作负载(如应用程序容器或进程)之间的网络连接和负载均衡。
2. cilium/ebpf库实践
cilium/ebpf 纯 Go 程序编写,从而实现了程序最小依赖;与此同时其还提供了 bpf2go 工具,可用来将 eBPF 程序编译成 Go 语言中的一部分,使得交付更加方便。
因此,本文也选择基于 cilium/ebpf 库来开发和实践。
cilium/ebpf 库
cilium/ebpf库
github: https://github.com/cilium/ebpf
ebpf的核心程序是通过c编写,clang进行编译的。在编译好ebpf程序后,我们需要将其加载到内核中。目前有很多个项目对ebpf的编写调试运行的流程进行了优化,比较有名的是bcc和libbpf。很多时候我们希望能够更加方便的进行程序编写和部署,也希望程序能够在不同的linux发行版和内核上使用(即BPF CO-RE),bcc的运行依赖内核的头文件,也引入了繁重的整个clang llvm工具链,libbpf只能使用C/C++进行外部程序的开发。
如果想使用go编写,有两个选择:cilium的ebpf项目和libbpf-go,考虑的社区活跃度和未来的发展,也许使用cilium的ebpf工具比较合适。
eBPF 程序加载的本质是 BPF 系统调用,Linux 内核通过 BPF 系统调用提供 eBPF 相关的一切操作,比如:程序加载、map 创建删除等。常见的 loader 都是对这个系统调用的封装,部分 loader 提供更加原生接近系统调用的操作,部分 loader 则是进行了更多封装使得编程更便捷。
cilium/ebpf 库是一个 GO 语言版本的 libbpf 库,它封装了 BPF 系统调用,与内核提供的 libbpf 类似。使用 cilium/ebpf 库实现用户态程序加载 eBPF 到内核,在很多方面都类似 libbpf,区别在于这个库是 GO 语言的,更加方便使用 GO 语言构建一套 eBPF 程序的控制面方案。
纯go库用于读取,修改和加载EBPF程序,并将其连接到Linux内核中的各种钩子上。
使用go开发ebpf程序思路
官方github: https://github.com/cilium/ebpf
使用 Go 语言开发 ebpf 程序
https://houmin.cc/posts/adca5ae5/
开发者只需要实现内核态C文件,用户态go文件,用户态event消息结构体三个文件即可,框架会自动加载执行。
- 运行在内核态用C写eBPF代码,llvm编译为eBPF字节码。
- 用户态使用golang编写,cilium/ebpf纯go类库,做eBPF字节码的内核加载,kprobe/uprobe HOOK对应函数。
- 用户态使用golang做事件读取、解码、处理。
cilium/ebpf是一个纯GO库,可提供用于加载,编译和调试EBPF程序的实用程序。它具有最小的外部依赖性,旨在用于长期运行的过程中。
官方demo: tracepoint_in_go
官方demo参考路径:
examples/tracepoint_in_go/main.go
//此程序演示如何将eBPF程序附加到跟踪点。
//程序附加到syscall/sys_enter_openat跟踪点,并且
//每次 syscall 时,打印出整数123。
//基于预先存在的内核hook(tracepoint)打开跟踪事件。
//每次用户空间程序使用’openat()’ 系统调用时,eBPF
//将执行上面指定的程序,并显示“123”值 在 perf ring 中
纯go库用于读取,修改和加载EBPF程序,并将其连接到Linux内核中的各种钩子上。
这是官方完全go写的demo,演示了 syscall/sys_enter_openat跟踪点。
边栏推荐
- R language uses the coxph function of survival package to build Cox regression model, uses the ggrisk function of ggrisk package to visualize the risk score map (risk score map) of Cox regression, and
- SqEL简单上手
- Smart Panel wifi Linkage Technology, esp32 wireless chip module, Internet of Things WiFi Communication Application
- Summary of sequential, modulelist, and moduledict usage in pytorch
- R语言plotly可视化:可视化回归模型实际值和回归预测值的散点图分析回归模型的预测效能、区分训练集和测试集、一个好的模型大部分的散点在对角线附近、添加边缘直方图以快速诊断模型可能存在的任何预测偏差
- MySQL创建用户并授权
- What does hard work mean to you?
- What does kotlin collaboration scope and coroutinescope mainscope globalscope viewmodelscope lifecyclescope represent respectively
- 1. Mx6ull learning notes (II) - uboot migration
- Create a new table in the database. There was no problem before. Today
猜你喜欢

Smart Panel wifi Linkage Technology, esp32 wireless chip module, Internet of Things WiFi Communication Application

Notes on relevant knowledge points such as original code / inverse code / complement code, size end, etc

E-commerce middle office system architecture

Enterprise Architect v16
![[official testerhome] MTSC 2021 Shanghai and Shenzhen PPT download addresses](/img/a0/d1170b20d01a7a586d8ff68279f1d4.jpg)
[official testerhome] MTSC 2021 Shanghai and Shenzhen PPT download addresses

1. Mx6ull learning notes (II) - uboot migration

Mosaïque d'images basée sur la matrice de transformation

SQL safe backup display and zoom font support

Smart panel WiFi linkage technology, esp32 wireless chip module, Internet of things WiFi communication application

1. Mx6ull learning notes (III) - busybox creates root file system
随机推荐
[data recovery in North Asia] data recovery in which the logical volume of the server is changed and the file system is damaged due to system reinstallation
Will subsequent versions support code block search highlighting
智能面板WiFi联动技术,ESP32无线芯片模组,物联网WiFi通信应用
动规(15)-最低通行费
Kill session? This cross domain authentication solution is really elegant!
【C语言】封装接口(加减乘除)
MySQL create user and authorize
电商中台系统架构
[C language] analysis of variable essence
Successfully solved: warning: there was an error checking the latest version of pip
【FPGA+FFT】基于FPGA的FFT频率计设计与实现
EN in Spacey_ core_ web_ SM installation problems
PostMessage implements window communication
[C language] encapsulation interface (addition, subtraction, multiplication and division)
R语言plotly可视化:使用plotly可视化简单线性回归模型的回归线(simple regression model linear regression plots)
Dynamic gauge (15) - Minimum toll
Call reminder
Mongodb essence summary
分布式锁介绍
Batch automated e-mail: Vika Vige table x Tencent Qianfan scene connector has made new moves, and business communication and event marketing only need 3 steps