唯品会网站建设,零售网站开发,找做网站页的在哪找,网站建设 网络科技公司学习ebpf相关知识 参考资料: awesome-ebpf 文章目录 初识准备ebpf.io介绍cilium的介绍内核文档Brendan Greggs Blog 的介绍书籍Learning eBPFWhat is eBPF? 交互式环境视频 基础知识学习学习环境搭建书籍阅读 项目落地流程整理环境搭建内核编译bcc环境变量zliblibelflibbpflib…学习ebpf相关知识 参考资料: awesome-ebpf 文章目录 初识准备ebpf.io介绍cilium的介绍内核文档Brendan Greggs Blog 的介绍书籍Learning eBPFWhat is eBPF? 交互式环境视频 基础知识学习学习环境搭建书籍阅读 项目落地流程整理环境搭建内核编译bcc环境变量zliblibelflibbpflibbpf-bootstrapbpftool 初识
最开始接触到的是经典bpf即cbpf可以通过生成的字节码给raw socket设定过滤器这过程中了解到了ebpf被他的强大所吸引过去我就对内核观测方面缺少了解而现有的一些手段显的有点麻烦不是那么易用我当时就感觉ebpf可能可以符合我的要求。看gpt的回答:
灵活性方面eBPF是目前最灵活的观测内核行为的工具之一。它允许用户编写自定义的观测逻辑并且可以在不需要重新编译内核的情况下动态加载和卸载观测程序。当时尝试去搞ebpf但是由于改了内核选项之后内核跑不起来了加之工作太忙因此就搁置了这段时间又捡起来
准备
本来想找linux内核之旅的入门教程的但是去看了gitee和github资料都不知道去哪了无奈只能重新找了awesome ebpf来看了。这个项目中有很多的资料链接非常多可以先挑几个看。
ebpf.io介绍
先看ebpf.io的介绍可以设置中文。 这里摘录一些我觉得有必要记录的:
如何编写 eBPF 程序 在很多情况下eBPF 不是直接使用而是通过像 Cilium、bcc 或 bpftrace 这样的项目间接使用这些项目提供了 eBPF 之上的抽象不需要直接编写程序而是提供了指定基于意图的来定义实现的能力然后用 eBPF 实现。 如果不存在更高层次的抽象则需要直接编写程序。Linux 内核期望 eBPF 程序以字节码的形式加载。虽然直接编写字节码当然是可能的但更常见的开发实践是利用像 LLVM 这样的编译器套件将伪 c 代码编译成 eBPF 字节码如果不存在更高层次的抽象则需要直接编写程序。 开发工具链 bcc BCC 是一个框架它允许用户编写 python 程序并将 eBPF 程序嵌入其中。该框架主要用于应用程序和系统的分析/跟踪等场景其中 eBPF 程序用于收集统计数据或生成事件而用户空间中的对应程序收集数据并以易理解的形式展示。运行 python 程序将生成 eBPF 字节码并将其加载到内核中。 bpftrace bpftrace 是一种用于 Linux eBPF 的高级跟踪语言可在较新的 Linux 内核4.x中使用。bpftrace 使用 LLVM 作为后端将脚本编译为 eBPF 字节码并利用 BCC 与 Linux eBPF 子系统以及现有的 Linux 跟踪功能内核动态跟踪kprobes、用户级动态跟踪uprobes和跟踪点进行交互。bpftrace 语言的灵感来自于 awk、C 和之前的跟踪程序如 DTrace 和 SystemTap。 eBPF Go 语言库 eBPF Go 语言库提供了一个通用的 eBPF 库它将获取 eBPF 字节码的过程与 eBPF 程序的加载和管理进行了解耦。eBPF程序通常是通过编写高级语言然后使用 clang/LLVM 编译器编译成 eBPF 字节码来创建的。 libbpf C/C 库 libbpf 库是一个基于 C/ c 的通用 eBPF 库它可以帮助解耦将 clang/LLVM 编译器生成的 eBPF对象文件的加载到内核中的这个过程并通过为应用程序提供易于使用的库 API 来抽象与 BPF 系统调用的交互。 cilium的介绍
链接BPF and XDP Reference Guide 在开发工具章节的安装比如bpftool,llvm等在内核编译章节提供了一些编译内核相关的内容。
内核文档
BPF Documentation
Brendan Gregg’s Blog 的介绍
Learn eBPF Tracing: Tutorial and Examples
书籍
Learning eBPF
这里ebpf.io还推荐了几本书我准备先看下Learning eBPF电子版在这看起来像是一本入门书籍。而且还有配套的示例代码。我在我的Mac-mini上装了一个lima用来跑这个代码。我看这里面用了quem感觉如果不是为了后续实际落地我可以不用折腾环境了。。。
What is eBPF?
另外还有一本同一个作者在更早写的《what-is-ebpf》这里有中文翻译版。
交互式环境
都在这个页面 Getting started with eBPF Learning eBPF Tutorial
视频
Tutorial: Getting Started with eBPF - Liz Rice, Isovalent
基础知识学习
学习环境搭建
我发现资料太多了打算先从《Learning eBPF》开始刚好作者提供了环境。我打算以树莓派真实环境为主毕竟是后面打算落地应用的以虚拟环境为辅。 在Brendan Gregg的博客中提到初级是运行 bcc tools中级开发bpftrace tools高级直接参与到这两个工具的开发因此我打算先从bcc开始。而《Learning eBPF》作者提供的环境里各种环境都准备好了像bcc,bpftool,libbpf等等全部都ok而且内核的各种选项也都开了而且使用了quem可以模拟arm64设备十分方便用来前期学习。
书籍阅读
详见《Learning eBPF》读书笔记
项目落地流程整理
如果想把ebpf在项目落地需要考虑的有以下方面问题 1.嵌入式设备的交叉编译 2.主机设备网络受限无法使用apt等工具 3.编写程序以及排查定位编写程序的难度问题
目前大概有两条路: 1.使用bpftool加载ebpf程序到内核但是这样就没法写用户态程序交互了 2.使用libbpf完成全套工作优点是可扩展性高缺点是环境搭建可能更麻烦。
环境搭建
内核编译
毫无疑问内核需要进行配置以运行ebpf 我这里5.10.110的默认配置如下:
$ cat .config|grep BPF
CONFIG_CGROUP_BPFy
CONFIG_BPFy
CONFIG_BPF_SYSCALLy
CONFIG_ARCH_WANT_DEFAULT_BPF_JITy
# CONFIG_BPF_UNPRIV_DEFAULT_OFF is not set
# CONFIG_BPF_PRELOAD is not set
CONFIG_NETFILTER_XT_MATCH_BPFm
# CONFIG_BPFILTER is not set
# CONFIG_NET_CLS_BPF is not set
# CONFIG_NET_ACT_BPF is not set
# CONFIG_BPF_JIT is not set
# CONFIG_BPF_STREAM_PARSER is not set
CONFIG_LWTUNNEL_BPFy
CONFIG_HAVE_EBPF_JITy
CONFIG_BPF_LIRC_MODE2y
CONFIG_BPF_EVENTSy
# CONFIG_BPF_KPROBE_OVERRIDE is not set
# CONFIG_TEST_BPF is not set上面需要开启JIT以获取更高的运行效率另外还需要再开启BTF支持CO-RE。
CONFIG_BPF_JIT
CONFIG_DEBUG_INFO_BTFok不出意外的话会出现意外编译失败:
FAILED: load BTF from vmlinux: Unknown error -22make: *** [Makefile:1179: vmlinux] Error 255看了下是tools/bpf/resolve_btfids直接失败了。。。。 后面用6.1内核一次成功我怀疑是交叉编译的支持不太好我选择放弃选6.1了
bcc
本来我打算在树莓派自行从源码搭建bcc的但是看了下安装文档感觉有点麻烦所以直接用Learning eBPF中提供的虚拟环境了。 感受下22.04依赖库:
# For Jammy (22.04)
sudo apt install -y zip bison build-essential cmake flex git libedit-dev \libllvm14 llvm-14-dev libclang-14-dev python3 zlib1g-dev libelf-dev libfl-dev python3-setuptools \liblzma-dev libdebuginfod-dev arping netperf iperf环境变量
shell:
#!/bin/bash
ROOT_PATH/home/wsl/project/raspberry_pi/
export ZLIB_ROOT_PATH${ROOT_PATH}/ebpf/zlib-1.3/
export LIBELF_ROOT_PATH${ROOT_PATH}/ebpf/elfutils-0.190/
ZLIB_INC${ZLIB_ROOT_PATH}/output/usr/local/include
ZLIB_LIB${ZLIB_ROOT_PATH}/output/usr/local/lib
LIBELF_INC${LIBELF_ROOT_PATH}/libelf/output/usr/local/include
LIBELF_LIB${LIBELF_ROOT_PATH}/libelf/output/usr/local/lib
export ZLIB_INC ZLIB_LIB LIBELF_INC LIBELF_LIBzlib
github仓库 编译脚本:
#!/bin/bash
make clean
CHOSTaarch64-linux-gnu ./configure \
--static #最好编译成静态的因为后面feature检查不加-lz
make -j4
make DESTDIRoutput installlibelf
libelf隶属于elfutils。 直接编译然后报了这个错误_FORTIFY_SOURCE redefined然后参照github的解答修改了configure参数编译脚本如下可以编译通过了。 后面发现可以直接编译通过了神奇
#!/bin/bash
source ../../env.sh
echo zlib inc is $ZLIB_INC
echo zlib lib is $ZLIB_LIB
./configure --hostaarch64-linux-gnu \
CFLAGS-I${ZLIB_INC} \
LDFLAGS-L${ZLIB_LIB} LIBS-lz
make -j4
make DESTDIRoutput installlibbpf
知识了解:【译】 Libbpf初学者指南 libbpf的起始代码示例: libbpf-bootstrap 包含libbpf相关基础知识和例子的博客 libbpf依赖libelf和zlib不过这个库应该是还好应该是用gcc可以编出来 然后libbpf本身应该也是可以用gcc编出来但是我看用libbpf写的程序却是用clang编的主要我用的时候要交叉编译 其实libbpf在linux源码中也有要不是看makefile我都不知道位于tools/lib/bpf/ 官方编译指南
编译脚本
#!/bin/bash
BUILD_STATIC_ONLYy CROSS_COMPILEaarch64-linux-gnu- NO_PKG_CONFIG1 DESTDIRoutput make installlibbpf-bootstrap
libbpf-bootstrap在树莓派安装失败了但在虚拟机环境上却一次成功不知道是不是内核支持的问题。不过最终在树莓派上我也是要交叉编译的不折腾了。
bpftool
在内核源码中就有位于/tools/bpf/bpftool/。而且看makefile是可以连libbpf一起编的。依赖libelf和zlib。 最开始时特性检查是这样的:
Auto-detecting system features:
... libbfd: [ OFF ]
... disassembler-four-args: [ OFF ]
... zlib: [ on ]
... libcap: [ OFF ]
... clang-bpf-co-re: [ OFF ]我就在想co-re为啥不支持呢后来把feature检查的打印放开发现是主机没装llvm和clang。。。。装好后再编就ok了。 还有一个就是我编译找不到库发现是用了CFLAGS实际应该用EXTRA_CFLAGS以及EXTRA_LDFLAGS。 OK,继续编译应该是去编libbpf了问题又来了提示找不到libelf我明明都编了只好加打印分析了。 在tools/bpf/bpftools当中CFLAGS在Makefile中有额外赋值LDFLAGS无额外赋值两者都会EXTAR_XXFLAGS但是在子目标libbpf中未传递任何变量也就是说只有最开始命令行指定的参数才会通过MAKEFLAGS传递到子makefile中去。在tools/lib/bpf/Makfile中CFLAGS与bpftool中类似因此CFLAGS无误但是LDFLAGS无额外赋值。 实际libbpf在编译时include的了Makefile.feature,在build/Makefile.feature中实际make的命令行参数中CFLAGS赋值为EXTRA_CFLAGSLDFLAGS无赋值如下:
feature_check $(eval $(feature_check_code))
define feature_check_codefeature-$(1) : $(shell $(MAKE) OUTPUT$(OUTPUT_FEATURES) CC$(CC) CXX$(CXX) CFLAGS$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1)) CXXFLAGS$(EXTRA_CXXFLAGS) $(FEATURE_CHECK_CXXFLAGS-$(1)) LDFLAGS$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1)) -C $(feature_dir) $(OUTPUT_FEATURES)test-$1.bin /dev/null 2/dev/null echo 1 || echo 0)
endef在在build/feature/Makefile中直接使用CFLAGSLDFLAGS无任何额外赋值。因此决定调整编译参数。编译ok但是又报错了
/bpftool-bootstrap btf dump file /home/wsl/project/raspberry_pi/linux/vmlinux format c vmlinux.h
/bin/sh: 1: ./bpftool-bootstrap: Exec format error
make[1]: *** [Makefile:139: vmlinux.h] Error 126
make: *** [Makefile:71: bpf/bpftool] Error 2看下这两个文件:
wslMy-win:~/project/raspberry_pi/linux/tools$ file bpf/bpftool/bpftool-bootstrap
bpf/bpftool/bpftool-bootstrap: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]6de9b18d3cb85a30d39cd8eebb37836397a08dd8, for GNU/Linux 3.7.0, not stripped
wslMy-win:~/project/raspberry_pi/linux/tools$ file /home/wsl/project/raspberry_pi/linux/vmlinux
/home/wsl/project/raspberry_pi/linux/vmlinux: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), statically linked, BuildID[sha1]1b1c20a248667d9a82dbfb87488660e92ca992f4, not stripped好吧都是ARM64的所以这个脚本交叉编译真的能行吗。。。 我直接把bpftool-bootstrap拷贝到已经换好内核的树莓派然后准备按照makefile中的提示执行这个工具依赖libelf所以需要在树莓派安装依赖库 按照libbpf-的编译指南ubuntu应该装这些:
$ apt install clang libelf1 libelf-dev zlib1g-dev我没装clang后面再说吧。讲道理本来应该我把我自己交叉编译的库拷过去的直接install也行吧。。。 bpftool-bootstrap btf dump file /sys/kernel/btf/vmlinux format c vmlinux.h这个命令和之前看learnning ebpf中提到的生成vmlinux.h的命令几乎一模一样除了执行的进程变成了bpftool-bootstrap。 好吧这个vmlinux ok之后又有新的错误
./bpftool-bootstrap gen skeleton profiler.bpf.o profiler.skel.h
/bin/sh: 1: ./bpftool-bootstrap: Exec format error感觉很生气去看了别人的文章都是能编译过的然后换了6.1的内核bpftool,libbpf包括带btf选项的内核全部一次编译通过了。。。。 分别对比Makefile有如下发现 1.编译bpftool不再检查zlib 2.编译libbpf不再检查libelf zlib,且编译已经完全不依赖这两个库 3.bpftool-bootstrap变成了bpftool而且是直接host编译的不是交叉编译的:
$ file /home/wsl/project/raspberry_pi/linux_6.1.y/tools/bpf/bpftool/bootstrap/bpftool
/home/wsl/project/raspberry_pi/linux_6.1.y/tools/bpf/bpftool/bootstrap/bpftool: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]e9f7b79931f1f08a97a24ae93a014750bce6c04e, for GNU/Linux 3.2.0, with debug_info, not stripped更绝望的是5.11就支持交叉编译了我用的是5.10生产环境也是5.10啊啊啊啊啊阿啊啊啊啊 编译脚本:
#!/bin/bash
source ../../env.sh
echo zlib inc is $ZLIB_INC
echo zlib lib is $ZLIB_LIB
echo libelf inc is $LIBELF_INC
echo libelf lib is $LIBELF_LIB
echo vmlinux path is $VMLINUX_PATH
make bpf/bpftool V1 ARCHarm64 CROSS_COMPILEaarch64-linux-gnu- EXTRA_CFLAGS-I${ZLIB_INC} -I${LIBELF_INC} LDFLAGS-L${ZLIB_LIB} -L${LIBELF_LIB} VMLINUX_H${VMLINUX_PATH} -j4