在上篇文章eBPF初见(入门篇)我们介绍了eBPF的发展历程和强大的能力,同时也介绍了在内核中的运行时组件,以及为用户空间提供的系统调用bpfAPI,这些细节能够帮助更好的理解eBPF程序的运行机制,但在实际使用时有一定难度,本篇将介绍eBPF的生态,了解有哪些可以帮助我们以更简单的方式使用eBPF,以及有哪些热门开源项目。 下面我们将从开发、工具、应用等多个方面介绍相关生态:开发 编译器 由于eBPF程序被设计为在用C编写的Linux内核中运行,因此eBPF定义了与两种最常用的架构x64和arm64兼容的指令集(并考虑了其他架构的重要怪癖),并定义了与这些架构上Linux内核的C调用约定兼容的调用约定。 LLVM和GCC支持将CC代码编译为eBPF字节码,目前LLVM的支持最好。 原生Linux系统调用接口和内核函数 用户态 根据上一篇的介绍已经了解到eBPF程序的开发是分为用户空间和内核空间两部分,不同空间中需要实现的功能和能够使用的能力是不一样的。 在用户态,linux提供了有且只有一个系统调用bpfAPI,根据参数不同主要提供加载编译好的eBPF字节码以及访问eBPFmaps。includelinuxbpf。hintbpf(intcmd,unionbpfattrattr,unsignedintsize); cmd(目前有37种) 功能描述 BPFMAP mapsCRUD遍历等操作 BPFPROGATTACHDETACH 附加或接触某个数据源 BPFLINK LINK相关操作 BPFBTF BTF相关操作 BPFOBJ 对象相关操作 BPFPROGLOAD 验证并加载BPF程序 每个调用的返回都是一个文件描述符(可以代表maps或者某个eBPF程序),可以基于这个文件描述符修改一些属性(比如附加eBPF程序到特定事件源)。 以上eBPFmaps的CRUD和遍历,操作都比较简单,不过需要注意应该区分不同的maps类型,这里不展开讲,具体参考上一篇的eBPFmaps部分。 最重要的就是验证并加载eBPF程序BPFPROGLOAD这个操作,不同的eBPF程序是分类型的,类型信息需要在第二个参数attr中明确给出。 通过以上系统调用和不同参数,可以在用户态与内核交互,实现eBPF程序加载和maps操作。 内核态 不同类型的eBPF决定内核中可用的辅助函数集和被调用时的输入信息。通常eBPF分为跟踪类和网络类,跟踪类的eBPF程序能用的辅助函数集与网络类eBPF的函数集差异很大,跟踪类eBPF程序的输入信息通常是内核中已有的注册值,而网络类的输入信息是网络包数据。 在内核中,eBPF程序可以使用受限的C语言(不支持循环、全局变量、浮点数、函数参数等),配合内核提供的辅助函数和映射(maps)来实现较复杂的执行逻辑,而且使用JIT编译(kernel4。15开始默认开启),在内核中执行效率很高。 不同类型的eBPF的内核辅助函数还是很多的,具体开发时需要查阅具体的清单(https:www。man7。orglinuxmanpagesman7bpfhelpers。7。html)。bpftoolfeautre可以列出所有eBPFmaps和程序的类型,以及每个不同类型的辅助函数列表 libbpf 直接基于系统调用和内核函数开发是可行的,但现实总会遇到一些与逻辑无关的细节问题,如需要考虑不同内核版本细微变化的兼容性、总是编写类似的代码、缓存、错误处理等,同时需要兼顾内核的变化和追求代码的通用性、可移植性,为了克服这些问题通常会抽象出一层常用的函数库,于是libbpf就诞生了,类似libc库的作用,目前libbpf已经是内核的一部分。 libbpf提了以下更好的能力:封装并简化使用bpf系统调用的能力和数据结构提供一致的错误处理提供额外的扩展的辅助函数联合多个系统调用实现更高的服务能力内核版本兼容支持编译一次到处运行能力 具体API参考:https:libbpf。readthedocs。ioenlatestapi。html BCC BCC(eBPFcompilercollection)是最早用于开发eBFP跟踪程序的高级框架,不仅提供了基于C语言开发eBPF程序的开发环境,还同时提供了Python、Lua、C来实现用户态接口,是libbcc和libbpf的前身,最开始添加到Linux3。15中,目前大部分内容都需要Linux4。1及更高版本。 BCC还自带了70多种已经写好的可以直接使用的eBPF工具,可以用来支持性能分析和排障工作。 bpftrace bpftrace是由AlastairRobertson创建的一个新的开发工具,提供了专门用于创建eBPF工具的高级语言支持,在最近的Linux内核(4。x)中可用。bpftrace使用LLVM作为后端将脚本编译为eBPF字节码,并利用BCC与LinuxBPF系统以及现有的Linux跟踪功能进行交互:内核动态跟踪(kprobes)、用户级动态跟踪(uprobes)和跟踪点。bpftrace语言的灵感来自awk和C以及DTrace和SystemTap等前身跟踪器。 BCC、bpftrace和libbpf的关系如下,libbpf作为ebpf的函数库,BCC和bpftrace基于libbpf实现了自己的一些工具和高级自定义语法,简化eBPF的使用难度。 bcc、bpftrace与libbpf的关系 从目前的趋势看,BCC这个项目实现了大量好用的工具,但其实现方式比较臃肿,且兼容性不太好,会逐步被bpftracelibbpf取代,目前已经有大量的BCC工具用bpftrace重构。 在5。15kernel中被bpftrace重构的bcc工具 还有一些其他语言的eBPF开发库:golang:ebpfgo(cilium项目维护)、goebpf、libbpfgorust:libbpfrs、redbpf、ayaeBPF衍生引擎 ply一个简化版的bpftrace ply是一个用于嵌入式Linux的轻量化eBPF前端工具,适用于Linux的轻量级动态跟踪器。它利用内核的eBPFVM与kprobes和跟踪点配合使用,将探测器附加到内核中的任意点。大多数生成BPF字节码的跟踪器都基于基于LLVM的BCC工具链。另一方面,除了libc之外,Ply没有必需的外部依赖项。 ubpf ubpf项目旨在创建一个Apache许可的库来执行eBPF程序。eBPF的主要实现存在于Linux内核中,但由于其GPL许可证,它不能在许多项目中使用。 该项目包括eBPF汇编器、反汇编器、解释器(适用于所有平台)和JIT编译器(适用于x8664和Arm64目标)。 eBPFforWindows eBPFforWindows项目是一个正在进行的工作,它允许使用eBPF生态系统中熟悉的现有eBPF工具链和API在Windows之上使用。也就是说,该项目将现有的eBPF项目作为子模块,并在两者之间添加层以使它们在Windows上运行。 hBPFeBPFinhardware hBPF设计为在FPGA硬件中实现的扩展BerkleyPacketFilterCPU。与Verilog或VHDL等经典HDL语言相比,MigenLiteX(均基于Python)使用。支持调用操作码的自定义扩展,并为包含的仿真器和模拟器以及包含的硬件目标的每个操作码提供完整的测试套件。 XDP eXpress数据路径(XDP)是一个框架,可以在BPF应用程序中执行高速数据包处理。为了更快地响应网络操作,XDP会尽快运行BPF程序,通常在网络接口收到数据包后立即运行。应用 kubectltrace kubectltrace是一个kubectl插件,它允许您在Kubernetes集群中调度bpftrace程序的执行,可以用于在kubernetes中临时运行eBPF排查问题。 kubectltrace支持node、pod、container三种维度的观测,可以自动识别k8s集群中对应node或者pod所在node,然后自动部署bpftrace程序进行trace。 tracenode tracepod Cilium Cilium是一个开源项目,提供eBPF驱动的网络、安全性和可观察性。它是从头开始专门设计的,旨在将eBPF的优势带到Kubernetes领域,并满足容器工作负载的新可扩展性、安全性和可见性要求。 Cilium为Kubernetes网络提供了极致的性能优化体验,后续有机会会重点解析一下。 Hubble Hubble是一个完全分布式的网络和安全可观测性平台,适用于云原生工作负载。它建立在Cilium和eBPF之上,能够以完全透明的方式深入了解服务的通信和行为以及网络基础设施。 Tetragon Cilium的新Tetragon组件支持强大的实时、基于eBPF的安全可观测性和运行时实施。 Tetragon检测并能够对安全重大事件做出反应,例如流程执行事件系统调用活动IO活动,包括网络和文件访问 当在Kubernetes环境中使用时,它能理解Kubernetes身份,如命名空间、pod等因此可以根据单个工作负载配置安全事件检测。 Falco Falco是一种行为活动监测器,旨在检测应用程序中的异常活动。Falco在eBPF的帮助下在Linux内核层审计系统。它使用其他输入流(如容器运行时指标和Kubernetes指标)丰富收集的数据,并允许持续监控和检测容器、应用程序、主机和网络活动。 Katran Katran是一个C库和eBPF程序,用于构建高性能的第4层负载平衡转发平面。Katran利用Linux内核中的XDP基础架构为快速数据包处理提供内核内设施。其性能与NIC的接收队列数量呈线性关系,并使用RSS友好封装转发到L7负载均衡器。 KubeArmor KubeArmor是一个容器感知运行时安全强制系统,它使用LSM和eBPF在系统级别限制容器的行为(例如进程执行、文件访问、网络操作和资源利用率)。 Pixie Pixie是一个用于Kubernetes应用程序的开源可观测性工具。Pixie使用eBPF自动捕获遥测数据,无需手动检测。开发人员可以使用Pixie查看其集群的高级状态(服务映射、集群资源、应用程序流量),还可以向下钻取到更详细的视图(pod状态、火焰图、单个全身应用程序请求)。 Tracee Tracee使用eBPF技术来检测和筛选操作系统事件,帮助您公开安全见解、检测可疑行为并捕获取证指标。 DeepFlow DeepFlow是云杉网络(opensnewwindow)开源的一款高度自动化的可观测性平台,是为云原生应用开发者建设可观测性能力而量身打造的全栈、全链路、高性能数据引擎。DeepFlow使用eBPF、WASM、OpenTelemetry等新技术,创新的实现了AutoTracing、AutoMetrics、AutoTagging、SmartEncoding等核心机制,帮助开发者提升埋点插码的自动化水平,降低可观测性平台的运维复杂度。利用DeepFlow的可编程能力和开放接口,开发者可以快速将其融入到自己的可观测性技术栈中。 Githubstart统计 这里简单统计今天各个项目在githubstart的数量以反应各个项目的活跃度: 项目 startcount kubectltrace 1。7k Katran 3。9k Cilium 13。6k Hubble 2。3k Tetragon 1。9k KubeArmor 526hrFalco 5。4k Pixie 4k Tracee 2。3k DeepFlow 458hr其中Cilium、Hubble、Tetragon都隶属于cilium项目,一起提供在云环境下的基于eBPF的网络、可观测性和安全性,覆盖了其他各个项目的能力,是一个非常值得关注的组合。 参考 https:github。comiovisorbpfdocsblobmastereBPF。md https:www。man7。orglinuxmanpagesman2bpf。2。html https:www。man7。orglinuxmanpagesman7bpfhelpers。7。html https:elixir。bootlin。comlinuxlatestsourceincludeuapilinuxbpf。hL840 https:libbpf。readthedocs。ioenlatestapi。html https:github。comlibbpflibbpf https:ebpf。foundationprojects https:deepflow。yunshan。netdocsaboutarchitecture https:github。comcilium