mirror of
https://github.com/eunomia-bpf/bpf-developer-tutorial.git
synced 2026-05-06 05:11:40 +08:00
Deploying to gh-pages from @ eunomia-bpf/bpf-developer-tutorial@bbd7b1638d 🚀
This commit is contained in:
99
print.html
99
print.html
@@ -219,12 +219,11 @@
|
||||
<h3 id="了解如何开发-ebpf-程序10-15h"><a class="header" href="#了解如何开发-ebpf-程序10-15h">了解如何开发 eBPF 程序(10-15h)</a></h3>
|
||||
<p>了解并尝试一下 eBPF 开发框架:</p>
|
||||
<ul>
|
||||
<li>bpftrace 教程,对于最简单的应用来说,bpftrace 可能是最方便的:https://eunomia.dev/zh/tutorials/bpftrace-tutorial/ (试试,1h)</li>
|
||||
<li>bpftrace 教程,对于最简单的应用来说,bpftrace 可能是最方便的:<a href="https://eunomia.dev/zh/tutorials/bpftrace-tutorial/">https://eunomia.dev/zh/tutorials/bpftrace-tutorial/</a> (试试,1h)</li>
|
||||
<li>BCC 开发各类小工具的例子:<a href="https://github.com/iovisor/bcc/blob/master/docs/tutorial_bcc_python_developer.md">https://github.com/iovisor/bcc/blob/master/docs/tutorial_bcc_python_developer.md</a> (跑一遍,3-4h)</li>
|
||||
<li>libbpf 的一些例子:<a href="https://github.com/libbpf/libbpf-bootstrap">https://github.com/libbpf/libbpf-bootstrap</a> (选感兴趣的运行一下,并阅读一下源代码,2h)</li>
|
||||
<li>基于 libbpf 和 eunomia-bpf 的教程:<a href="https://github.com/eunomia-bpf/bpf-developer-tutorial">https://github.com/eunomia-bpf/bpf-developer-tutorial</a> (阅读 1-10 的部分,3-4h)</li>
|
||||
<li>基于 C 语言 libbpf, Go 语言或者 Rust 语言和 eunomia-bpf 的教程:<a href="https://github.com/eunomia-bpf/bpf-developer-tutorial">https://github.com/eunomia-bpf/bpf-developer-tutorial</a> (阅读 1-20 的部分,3-8h)</li>
|
||||
</ul>
|
||||
<p>其他开发框架:Go 语言或者 Rust 语言,请自行搜索并且尝试(0-2h)</p>
|
||||
<p>有任何问题或者想了解的东西,不管是不是和本项目相关,都可以在本项目的 discussions 里面开始讨论。</p>
|
||||
<p>回答一些问题,并且进行一些尝试(2-5h):</p>
|
||||
<ol>
|
||||
@@ -285,15 +284,13 @@ eBPF 程序每次执行时候都需要进行编译,编译则需要用户配置
|
||||
字节码装载到内核中。同样的,<code>libbpf-bootstrap</code> 也有非常完备的入门教程,用户可以在<a href="https://nakryiko.com/posts/libbpf-bootstrap/">该处</a>
|
||||
得到详细的入门操作介绍。</p>
|
||||
<h3 id="eunomia-bpf"><a class="header" href="#eunomia-bpf">eunomia-bpf</a></h3>
|
||||
<p>开发、构建和分发 eBPF 一直以来都是一个高门槛的工作,使用 BCC、bpftrace 等工具开发效率高、可移植性好,但是分发部署时需要安装 LLVM、Clang 等编译环境,每次运行的时候执行本地或远程编译过程,资源消耗较大;使用原生的 CO-RE libbpf 时又需要编写不少用户态加载代码来帮助 eBPF 程序正确加载和从内核中获取上报的信息,同时对于 eBPF 程序的分发、管理也没有很好地解决方案。</p>
|
||||
<p><a href="https://github.com/eunomia-bpf/eunomia-bpf">eunomia-bpf</a> 是一个开源的 eBPF 动态加载运行时和开发工具链,是为了简化 eBPF 程序的开发、构建、分发、运行而设计的,基于 libbpf 的 CO-RE 轻量级开发框架。</p>
|
||||
<p>使用 eunomia-bpf ,可以:</p>
|
||||
<ul>
|
||||
<li>在编写 eBPF 程序或工具时只编写内核态代码,自动获取内核态导出信息,并作为模块动态加载;</li>
|
||||
<li>使用 WASM 进行用户态交互程序的开发,在 WASM 虚拟机内部控制整个 eBPF 程序的加载和执行,以及处理相关数据;</li>
|
||||
<li>eunomia-bpf 可以将预编译的 eBPF 程序打包为通用的 JSON 或 WASM 模块,跨架构和内核版本进行分发,无需重新编译即可动态加载运行。</li>
|
||||
</ul>
|
||||
<p>eunomia-bpf 由一个编译工具链和一个运行时库组成, 对比传统的 BCC、原生 libbpf 等框架,大幅简化了 eBPF 程序的开发流程,在大多数时候只需编写内核态代码,即可轻松构建、打包、发布完整的 eBPF 应用,同时内核态 eBPF 代码保证和主流的 libbpf,libbpfgo,libbpf-rs 等开发框架的 100% 兼容性。需要编写用户态代码的时候,也可以借助 Webassembly 实现通过多种语言进行用户态开发。和 bpftrace 等脚本工具相比, eunomia-bpf 保留了类似的便捷性, 同时不仅局限于 trace 方面, 可以用于更多的场景, 如网络、安全等等。</p>
|
||||
<p>eunomia-bpf 由一个编译工具链和一个运行时库组成, 对比传统的 BCC、原生 libbpf 等框架,简化了 eBPF 程序的开发流程,在大多数时候只需编写内核态代码,即可轻松构建、打包、发布完整的 eBPF 应用。</p>
|
||||
<blockquote>
|
||||
<ul>
|
||||
<li>eunomia-bpf 项目 Github 地址: <a href="https://github.com/eunomia-bpf/eunomia-bpf">https://github.com/eunomia-bpf/eunomia-bpf</a></li>
|
||||
@@ -404,7 +401,7 @@ Packing ebpf object and config into package.json...
|
||||
</code></pre>
|
||||
<p>然后使用 ecli 运行编译后的程序:</p>
|
||||
<pre><code class="language-console">$ sudo ./ecli run package.json
|
||||
Runing eBPF program...
|
||||
Running eBPF program...
|
||||
</code></pre>
|
||||
<p>运行这段程序后,可以通过查看 /sys/kernel/debug/tracing/trace_pipe 文件来查看 eBPF 程序的输出:</p>
|
||||
<pre><code class="language-console">$ sudo cat /sys/kernel/debug/tracing/trace_pipe | grep "BPF triggered sys_enter_write"
|
||||
@@ -4702,19 +4699,81 @@ Packing ebpf object and config into package.json...
|
||||
<li><a href="http://just4coding.com/2022/08/05/tc/">http://just4coding.com/2022/08/05/tc/</a></li>
|
||||
<li><a href="https://arthurchiao.art/blog/understanding-tc-da-mode-zh/">https://arthurchiao.art/blog/understanding-tc-da-mode-zh/</a></li>
|
||||
</ul>
|
||||
<div style="break-before: page; page-break-before: always;"></div><h1 id="ebpf-入门实践教程二十一使用-xdp-实现可编程包处理"><a class="header" href="#ebpf-入门实践教程二十一使用-xdp-实现可编程包处理">eBPF 入门实践教程二十一:使用 xdp 实现可编程包处理</a></h1>
|
||||
<h2 id="背景-3"><a class="header" href="#背景-3">背景</a></h2>
|
||||
<p>xdp(eXpress Data Path)是 Linux 内核中新兴的一种绕过内核的、可编程的包处理方案。相较于 cBPF,xdp 的挂载点非常底层,位于网络设备驱动的软中断处理过程,甚至早于 skb_buff 结构的分配。因此,在 xdp 上挂载 eBPF 程序适用于很多简单但次数极多的包处理操作(如防御 Dos 攻击),可以达到很高的性能(24Mpps/core)。</p>
|
||||
<h2 id="xdp-概述"><a class="header" href="#xdp-概述">XDP 概述</a></h2>
|
||||
<p>xdp 不是第一个支持可编程包处理的系统,在此之前,以 DPDK(Data Plane Development Kit)为代表的内核旁路方案甚至能够取得更高的性能,其思路为完全绕过内核,由用户态的网络应用接管网络设备,从而避免了用户态和内核态的切换开销。然而,这样的方式具有很多天然的缺陷:</p>
|
||||
<div style="break-before: page; page-break-before: always;"></div><h1 id="ebpf-入门实践教程二十一-使用-xdp-进行可编程数据包处理"><a class="header" href="#ebpf-入门实践教程二十一-使用-xdp-进行可编程数据包处理">eBPF 入门实践教程二十一: 使用 XDP 进行可编程数据包处理</a></h1>
|
||||
<p>在本教程中,我们将介绍 XDP(eXpress Data Path),并通过一个简单的例子帮助你入门。之后,我们将探讨更高级的 XDP 应用,例如负载均衡器、防火墙及其他实际应用。如果你对 eBPF 或 XDP 感兴趣,请在 <a href="https://github.com/eunomia-bpf/bpf-developer-tutorial">Github</a> 上为我们点赞!</p>
|
||||
<h2 id="什么是-xdp"><a class="header" href="#什么是-xdp">什么是 XDP?</a></h2>
|
||||
<p>XDP 是 Linux 内核中的一种高性能可编程数据路径,专为网络接口级的数据包处理而设计。通过将 eBPF 程序直接附加到网络设备驱动程序上,XDP 能够在数据包到达内核网络栈之前拦截并处理它们。这使得 XDP 能够进行极低延迟和高效的数据包处理,非常适合如 DDoS 防护、负载均衡和流量过滤等任务。实际上,XDP 每核心的吞吐量可以高达 <strong>每秒 2400 万包(Mpps)</strong>。</p>
|
||||
<h3 id="为什么选择-xdp"><a class="header" href="#为什么选择-xdp">为什么选择 XDP?</a></h3>
|
||||
<p>XDP 运行在比传统 Linux 网络组件(如 cBPF)更低的层级,在网络设备驱动程序的软中断上下文中执行。它能够在数据包被内核标准网络栈处理之前对其进行处理,避免了创建 Linux 中表示网络数据包的 <code>skb_buff</code> 结构。这种早期处理为简单但频繁的操作(如丢弃恶意数据包或负载均衡服务器)带来了显著的性能提升。</p>
|
||||
<p>与其他数据包处理机制相比,XDP 在性能和可用性之间取得了平衡,它利用了 Linux 内核的安全性和可靠性,同时通过可编程的 eBPF 提供了灵活性。</p>
|
||||
<h2 id="xdp-与其他方法的比较"><a class="header" href="#xdp-与其他方法的比较">XDP 与其他方法的比较</a></h2>
|
||||
<p>在 XDP 出现之前,一些解决方案通过完全绕过内核来加速数据包处理。其中一个显著的例子是 <strong>DPDK</strong>(数据平面开发工具包)。DPDK 允许用户空间应用程序直接控制网络设备,从而实现非常高的性能。然而,这种方法也存在一些权衡:</p>
|
||||
<ol>
|
||||
<li>
|
||||
<p><strong>缺乏内核集成</strong>:DPDK 及其他内核绕过解决方案无法利用现有的内核网络功能,开发者必须在用户空间重新实现许多协议和功能。</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>安全边界</strong>:这些绕过技术破坏了内核的安全模型,使得难以利用内核提供的安全工具。</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>用户空间与内核的转换开销</strong>:当用户空间数据包处理需要与传统内核网络交互时(例如基于套接字的应用程序),数据包必须重新注入到内核中,增加了开销和复杂性。</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>专用 CPU 使用</strong>:为了处理高流量,DPDK 和类似解决方案通常需要专用的 CPU 核心来处理数据包,这限制了通用系统的可扩展性和效率。</p>
|
||||
</li>
|
||||
</ol>
|
||||
<p>另一个替代 XDP 的方法是使用 Linux 网络栈中的 <strong>内核模块</strong> 或 <strong>挂钩</strong>。虽然这种方法可以很好地集成现有的内核功能,但它需要大量的内核修改,且由于在数据包处理管道的后期运行,无法提供与 XDP 相同的性能优势。</p>
|
||||
<h3 id="xdp--ebpf-的优势"><a class="header" href="#xdp--ebpf-的优势">XDP + eBPF 的优势</a></h3>
|
||||
<p>XDP 与 eBPF 结合提供了介于内核绕过方案(如 DPDK)和内核集成方案之间的中间地带。以下是 XDP + eBPF 脱颖而出的原因:</p>
|
||||
<ul>
|
||||
<li>无法与内核中成熟的网络模块集成,而不得不在用户态将其重新实现;</li>
|
||||
<li>破坏了内核的安全边界,使得内核提供的很多网络工具变得不可用;</li>
|
||||
<li>在与常规的 socket 交互时,需要从用户态重新将包注入到内核;</li>
|
||||
<li>需要占用一个或多个单独的 CPU 来进行包处理;</li>
|
||||
<li>
|
||||
<p><strong>高性能</strong>:通过在网络接口卡(NIC)驱动程序级别拦截数据包,XDP 可以实现接近线速的性能,用于丢弃、重定向或负载均衡数据包,同时保持低资源消耗。</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>内核集成</strong>:与 DPDK 不同,XDP 在 Linux 内核中工作,允许与现有的内核网络栈和工具(如 <code>iptables</code>、<code>nftables</code> 或套接字)无缝交互。无需在用户空间重新实现网络协议。</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>安全性</strong>:eBPF 虚拟机确保用户定义的 XDP 程序是被隔离的,不会对内核造成不稳定影响。eBPF 的安全模型防止恶意或有缺陷的代码损害系统,提供了一个安全的可编程数据包处理环境。</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>不需要专用 CPU</strong>:XDP 允许数据包处理而无需将整个 CPU 核心专用于网络任务。这提高了系统的整体效率,允许更灵活的资源分配。</p>
|
||||
</li>
|
||||
</ul>
|
||||
<p>总的来说,XDP + eBPF 提供了一种强大的可编程数据包处理解决方案,结合了高性能与内核集成的灵活性和安全性。它消除了完全绕过内核方案的缺点,同时保留了内核安全性和功能的优势。</p>
|
||||
<h2 id="xdp-的项目和应用案例"><a class="header" href="#xdp-的项目和应用案例">XDP 的项目和应用案例</a></h2>
|
||||
<p>XDP 已经在许多高调的项目中得到应用,这些项目展示了它在实际网络场景中的强大功能和灵活性:</p>
|
||||
<h3 id="1-cilium"><a class="header" href="#1-cilium">1. <strong>Cilium</strong></a></h3>
|
||||
<ul>
|
||||
<li><strong>描述</strong>:Cilium 是一个为云原生环境(尤其是 Kubernetes)设计的开源网络、安全和可观测性工具。它利用 XDP 实现高性能的数据包过滤和负载均衡。</li>
|
||||
<li><strong>应用案例</strong>:Cilium 将数据包过滤和安全策略卸载到 XDP,实现高吞吐量和低延迟的容器化环境流量管理,同时不牺牲可扩展性。</li>
|
||||
<li><strong>链接</strong>:<a href="https://cilium.io/">Cilium</a></li>
|
||||
</ul>
|
||||
<h3 id="2-katran"><a class="header" href="#2-katran">2. <strong>Katran</strong></a></h3>
|
||||
<ul>
|
||||
<li><strong>描述</strong>:Katran 是由 Facebook 开发的第 4 层负载均衡器,优化了高可扩展性和性能。它使用 XDP 处理数据包转发,开销极小。</li>
|
||||
<li><strong>应用案例</strong>:Katran 每秒处理数百万个数据包,高效地将流量分配到后端服务器上,利用 XDP 在大规模数据中心中实现低延迟和高性能的负载均衡。</li>
|
||||
<li><strong>链接</strong>:<a href="https://github.com/facebookincubator/katran">Katran GitHub</a></li>
|
||||
</ul>
|
||||
<h3 id="3-cloudflare-的-xdp-ddos-保护"><a class="header" href="#3-cloudflare-的-xdp-ddos-保护">3. <strong>Cloudflare 的 XDP DDoS 保护</strong></a></h3>
|
||||
<ul>
|
||||
<li><strong>描述</strong>:Cloudflare 已经实现了基于 XDP 的实时 DDoS 缓解。通过在 NIC 级别处理数据包,Cloudflare 能够在恶意流量进入网络栈之前过滤掉攻击流量,最小化 DDoS 攻击对其系统的影响。</li>
|
||||
<li><strong>应用案例</strong>:Cloudflare 利用 XDP 在管道早期丢弃恶意数据包,保护其基础设施免受大规模 DDoS 攻击,同时保持对合法流量的高可用性。</li>
|
||||
<li><strong>链接</strong>:<a href="https://blog.cloudflare.com/l4drop-xdp-ebpf-based-ddos-mitigations/">Cloudflare 博客关于 XDP</a></li>
|
||||
</ul>
|
||||
<p>这些项目展示了 XDP 在不同领域的可扩展和高效的数据包处理能力,从安全和负载均衡到云原生网络。</p>
|
||||
<h3 id="为什么选择-xdp-而不是其他方法"><a class="header" href="#为什么选择-xdp-而不是其他方法">为什么选择 XDP 而不是其他方法?</a></h3>
|
||||
<p>与传统方法(如 <code>iptables</code>、<code>nftables</code> 或 <code>tc</code>)相比,XDP 提供了几个明显的优势:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p><strong>速度与低开销</strong>:XDP 直接在 NIC 驱动程序中运行,绕过了内核的大部分开销,使数据包处理更快。</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>可定制性</strong>:XDP 允许开发人员通过 eBPF 创建自定义的数据包处理程序,提供比传统工具(如 <code>iptables</code>)更大的灵活性和细粒度控制。</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>资源效率</strong>:XDP 不需要像 DPDK 等用户空间解决方案那样将整个 CPU 核心专用于数据包处理,因此它是高性能网络的更高效选择。</p>
|
||||
</li>
|
||||
</ul>
|
||||
<p>除此之外,利用内核模块和内核网络协议栈中的 hook 点也是一种思路,然而前者对内核的改动大,出错的代价高昂;后者在整套包处理流程中位置偏后,其效率不够理想。</p>
|
||||
<p>总而言之,xdp + eBPF 为可编程包处理系统提出了一种更为稳健的思路,在某种程度上权衡了上述方案的种种优点和不足,获取较高性能的同时又不会对内核的包处理流程进行过多的改变,同时借助 eBPF 虚拟机的优势将用户定义的包处理过程进行隔离和限制,提高了安全性。</p>
|
||||
<h2 id="编写-ebpf-程序-3"><a class="header" href="#编写-ebpf-程序-3">编写 eBPF 程序</a></h2>
|
||||
<pre><code class="language-C">#include "vmlinux.h"
|
||||
#include <bpf/bpf_helpers.h>
|
||||
@@ -4772,12 +4831,12 @@ Packing ebpf object and config into package.json...
|
||||
<li><a href="http://arthurchiao.art/blog/linux-net-stack-implementation-rx-zh/">http://arthurchiao.art/blog/linux-net-stack-implementation-rx-zh/</a></li>
|
||||
<li><a href="https://github.com/xdp-project/xdp-tutorial/tree/master/basic01-xdp-pass">https://github.com/xdp-project/xdp-tutorial/tree/master/basic01-xdp-pass</a></li>
|
||||
</ul>
|
||||
<div style="break-before: page; page-break-before: always;"></div><h1 id="在-andorid-上使用-ebpf-程序"><a class="header" href="#在-andorid-上使用-ebpf-程序">在 Andorid 上使用 eBPF 程序</a></h1>
|
||||
<div style="break-before: page; page-break-before: always;"></div><h1 id="在-android-上使用-ebpf-程序"><a class="header" href="#在-android-上使用-ebpf-程序">在 Android 上使用 eBPF 程序</a></h1>
|
||||
<blockquote>
|
||||
<p>本文主要记录了笔者在 Android Studio Emulator 中测试高版本 Android Kernel 对基于 libbpf 的 CO-RE 技术支持程度的探索过程、结果和遇到的问题。
|
||||
测试采用的方式是在 Android Shell 环境下构建 Debian 环境,并基于此尝试构建 eunomia-bpf 工具链、运行其测试用例。</p>
|
||||
</blockquote>
|
||||
<h2 id="背景-4"><a class="header" href="#背景-4">背景</a></h2>
|
||||
<h2 id="背景-3"><a class="header" href="#背景-3">背景</a></h2>
|
||||
<p>截至目前(2023-04),Android 还未对 eBPF 程序的动态加载做出较好的支持,无论是以 bcc 为代表的带编译器分发方案,还是基于 btf 和 libbpf 的 CO-RE 方案,都在较大程度上离不开 Linux 环境的支持,无法在 Android 系统上很好地运行<sup class="footnote-reference"><a href="#WeiShu">1</a></sup>。</p>
|
||||
<p>虽然如此,在 Android 平台上尝试 eBPF 也已经有了一些成功案例,除谷歌官方提供的修改 <code>Android.bp</code> 以将 eBPF 程序随整个系统一同构建并挂载的方案<sup class="footnote-reference"><a href="#Google">2</a></sup>,也有人提出基于 Android 内核构建 Linux 环境进而运行 eBPF 工具链的思路,并开发了相关工具。</p>
|
||||
<p>目前已有的资料,大多基于 adeb/eadb 在 Android 内核基础上构建 Linux 沙箱,并对 bcc 和 bpftrace 相关工具链进行测试,而对 CO-RE 方案的测试工作较少。在 Android 上使用 bcc 工具目前有较多参考资料,如:</p>
|
||||
|
||||
Reference in New Issue
Block a user