eBPF对应用开发者而言,可能些许陌生,但是对于从事云、网络、操作系统等相关的开发者而言,近年来或多或少听说过或使用过。那么eBPF到底是什么?它有何作用?如何使用?今天这篇文章就来一一解答。
eBPF(extended Berkeley Packet Filter),意为“可扩展数据包过滤器”,是一种网络数据包的过滤技术。 在eBPF出现前,BPF (也称为cBPF , classic BPF ) 得到了广泛的应用,BPF 最初的名字 BSD Packet Filter ,源于BSD操作系统上的一种包过滤机制,后经发展,被作者的工作单位名所替代,变成了 Berkeley Packet Filter。 BPF支持数据包筛选,允许用户态程序提供要接收的数据包条件。最常用的tcpdump就 是基于BPF 实现 的 过滤出tcp包或u dp 包等功能。由于BPF实现了在内核直接过滤处理的能力,因此避免了不符合条件的数据包被“多余地”复制到用户态,从而大大提高了性能。
eBPF,作为扩展版本的BPF,支持JIT机制,动态地将用户态自定义指令解释为机器代码,并在内核中执行,从而大大提高了灵活性。在eBPF之前,内核模块是注入内核的最主要机制。由于缺乏对内核模块的安全控制,内核的基本功能很容易被一个有缺陷的内核模块破坏。而eBPF则借助即时编译器(JIT),并在kernel预先控制好开放的植入范围及校验程序,保证只有被验证安全的eBPF指令才会被内核执行。
eBPF伴随着kernel的发展,逐步完善和成熟,其发展历程大致如下:
• 内核可编程性 eBPF带来的最大的好处即是可以对内核进行编程性处理,实现对内核中不灵活的部分,实现自定义的处理,这大大提高了灵活性。
• 广泛应用场景 正是由于这种灵活性,使得对于不可见的kernel具有了可观测性的基础,在进行内核监控、网络故障分析、文件系统分析等方面具有广泛的使用前景。
正是由于这些突出的特性,eBPF程序可以附加到各种内核子系统,包括网络,跟踪和Linux安全模块(LSM)。比如,Facebook开源的高性能网络负载均衡器Katran、Isovalent开源的容器网络方案 Cilium ,以及著名的内核跟踪排错工具 BCC 和 bpftrace 等,都是基于eBPF技术实现的。更有意思的是,盘古实验室发现了NSA也使用BPF技术在Linux布置后门。
下图为内核跟踪排错工具BCC所支持的追踪点示意图,可见当前内核中除了驱动部分外的几乎所有子系统、高级语言、应用均已支持细粒度的跟踪分析:
那么,eBPF程序又是如何工作的呢?
在了解eBPF之前,需要先了解钩子(hook)机制,钩子机制顾名思义即可以挂载一种未确定的逻辑处理过程以实现对特定位置的处理,这种未确定性即灵活性,可以实现定制化或配置化管理,实现不同的需求。在linux内核中有一套hook函数机制(khook),可以在不同的hook点监控或处理如:文件打开、关闭等操作;网络包过滤、转换。最常见的netfilter就是借助于一整套的hook函数机制,实现了数据包在三层以上的过滤、NAT转换、基于协议的跟踪等等,具体参考: linux netfilter hook
eBPF程序是事件驱动的,当内核或应用程序通过某个钩子点(hook point)时触发执行。预定义的钩子包括:系统调用、函数进入/退出、内核跟踪点、网络事件等。
虽然现在我们依然不清楚如何写一个钩子处理函数,即eBPF程序的具体逻辑,不用担心,我们假设已经有了这样一个程序,那它会如何被处理,并执行起来呢?
上图展示了一个程序是如何被加载、验证并执行的,具体来看,经历了如下步骤:
但是我们要知道的是eBPF不是万能的,受限于本身内核版本支持能力、eBPF指令的种类、eBPF虚拟机结构等,eBPF程序并不能发挥 其 无限的能力,仅仅是“山顶跳舞”。
不过,基于这广泛的应用,无论是linux kernel社区,还是工具社区,都在试图突破这些限制,例如将高版本kernel才具备的能力以低成本的方式移植到低版本上,或者是实现一次编译,到处运行(CO-RE)等。
libbpf C/C++ Library
下一篇我们将会针对eBPF中的相关概念、eBPF虚拟机、BTF、eBPF原理做详细的介绍,敬请期待。
如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!
赞3
添加新评论0 条评论