一文读懂内核可编程技术eBPF

内核,在现代计算架构中扮演着至关重要的角色,它直接管理着系统资源并执行底层操作。出于系统安全性的考虑,对内核的访问权限被严格限制。这种机制有效地防止了潜在的系统破坏,但也带来了一项挑战:由于用户应用程序无法直接访问内核空间,它们难以检测到那些仅在内核级别才能观察到的低级网络和安全事件。

为了应对这一挑战,eBPF技术应运而生。它允许用户在内核空间内运行经过安全验证的代码,而无需修改内核源代码或加载额外的内核模块。这一创新性的技术为内核功能扩展提供了极大的灵活性。

eBPF解决了什么问题?

为了更好地回答这个问题,了解 eBPF 的起源以及它是如何从最初的 Berkeley Packet Filter(BPF)发展而来会有所帮助。

BPF 于 1993 年推出,旨在实现对网络流量的有效控制与筛选。在 BPF 出现之前,数据包过滤工具大多局限于用户空间运行,这不仅导致这些应用占用了大量的CPU资源,还限制了其性能表现。BPF 提供了一种独特的替代方案,因为它作为内核虚拟机 (VM) 运行,支持在原本独立的内核空间中进行包过滤。

然而,尽管有创新,BPF 最初并未得到广泛应用。随着计算机技术的进步,尤其是64位处理器的普及,BPF项目迎来了全新的发展机遇。在此期间,BPF经历了重大升级,原有的功能性限制被逐步突破。

这样,eBPF便应运而生,进一步拓宽了其在操作系统内核中执行安全、高效程序的能力。eBPF 在多个方面拓展了 BPF 的概念:

1.与其前身不同,eBPF 并不局限于 Linux 内核的网络子系统。它几乎可以访问 Linux 内核所能“关联”的任何资源。
2.BPF 仅支持相对简单的、面向网络的操作,而 eBPF 配备了多种工具,可以扩展已开发程序的功能。
3.社区围绕 eBPF 做出了巨大的努力,产生了许多软件开发套件 (SDK) 和工具,极大地方便了eBPF程序的开发过程。

eBPF :内核的 JavaScript 可编程接口

对于浏览器来说,JavaScript 的引入带来了可编程性,并引发了一场巨大的革命,将浏览器转变为几乎独立的操作系统。eBPF正逐渐扮演着类似JavaScript在浏览器中的角色,只不过这次是在操作系统内核层面。

Linux内核的主要目的是抽象化硬件或虚拟硬件,并提供一致的API(系统调用),使应用程序能够运行和共享资源。为了实现这一目标,内核由多个子系统组成,每个子系统负责不同的任务。子系统通常允许一定程度的配置以满足不同的用户需求。当所需的行为无法通过配置达成时,传统上有两种选择:一是修改内核源代码,此路径不仅耗时费力,还需历经社区审核;二是编写一个内核模块,虽相对灵活,但模块随内核迭代需定期修复。二者均非理想之选,前者成本高昂,后者牺牲了可移植性。

eBPF提供了一个新的选项,可以在不修改内核源代码或加载内核模块的情况下,重新编程Linux内核的行为,同时确保在不同内核版本间保持一定程度的行为一致性、兼容性和安全性。为此,eBPF程序也需要一个相应的API,允许用户定义的应用程序执行和共享资源。

换言之,从某种意义上说,eBPF虚拟机也提供了一个类似于系统调用的机制。借助eBPF与用户空间之间的通信机制,无论是WebAssembly虚拟机还是用户空间应用程序都能够全面利用这套“系统调用”。一方面,它可以通过编程方式扩展传统系统调用的能力;另一方面,它能够在网络、文件系统等多个层级实现更高效的可编程I/O处理,从而解锁内核级编程的全新潜能,推动操作系统内核进入一个更为灵活和动态的时代。

如上图所示,当今的Linux内核正在向新的内核模型演进:用户定义的应用程序既可在内核空间也可在用户空间运行,用户空间通过传统的系统调用来访问系统资源,而内核空间则通过BPF Helper Call与系统的各个部分交互。

截至2023年初,内核中的eBPF虚拟机已包含超过220个Helper系统接口,广泛覆盖了多种应用场景。值得注意的是,BPF Helper Call与系统调用并不具有竞争性。它们的编程模型和性能优势截然不同,无法完全互相替代。对于Wasm及WASI生态系统而言,情况类似。专门设计的wasi接口需经历漫长的标准化过程,然而,它可为特定场景下的用户模式应用程序提供更好的性能和可移植性保障。另一方面,eBPF则能提供一个快速灵活的系统接口扩展方案,同时确保沙箱特性和可移植性。

目前,eBPF仍处于发展的初级阶段,但已经展现出强大的潜力。凭借eBPF提供的内核接口及其与用户空间交互的能力,运行在Wasm虚拟机中的应用程序几乎能够访问任何内核或用户模式函数调用(如kprobe、uprobe等)的数据和返回值。它能以较低的成本收集并理解所有的系统调用,获取所有网络操作(如tracepoint、socket...)的包级数据和套接字级数据。此外,eBPF还能在不脱离Linux内核包处理环境的前提下,添加额外的协议分析器,并轻松地对网络包处理解决方案(如XDP、TC等)中的任何转发逻辑进行编程。

此外,eBPF还具有向用户空间进程的任意地址写入数据(bpf_probe_write_user)、部分修改内核函数返回值(bpf_override_return)以及甚至在内核模式下直接执行特定系统调用的能力。不过,eBPF在将字节码加载到内核之前会对它进行严格的安保检查,以确保不存在越界内存访问等操作。而且,许多可能扩大攻击面并带来安全风险的功能特性,在内核编译时需要被显式启用。在将字节码载入内核之前,Wasm虚拟机也可以选择性地启用或禁用某些eBPF特性,以确保沙盒的安全性。

除了作为内核模式下的运行时,eBPF还能扩展到用户空间中,例如通过bpftime实现更高性能的用户空间追踪、性能分析、插件等功能。

eBPF 是如何工作的?

eBPF 允许开发人员按照以下流程在内核空间中执行自定义代码:

1.编写一个 eBPF 程序。
2.将程序加载到内核中。通常,使用用户空间工具(例如bpftool )来执行此操作,该工具允许与 eBPF 框架交互。
3.程序会经历一个验证过程,这一阶段会检查程序是否存在尝试访问指定内存区域之外的内存等问题。eBPF程序的验证机制是为了确保程序执行时不会导致系统不稳定,防止例如无限循环或者非法内存访问等可能破坏系统安全和稳定性的行为。
4.如果程序通过了验证,内核就会根据程序中指定的代码路径来执行它。之后,开发者可以在程序设计的输出位置查看执行结果。

EBPF 的采用

多年来,eBPF 已在全球数百万台设备和服务器上运行。

众多美国超大规模企业,如Meta、Google、Netflix等,已在生产环境中使用 eBPF。每一部Android手机都利用eBPF来监控网络流量。进出Facebook数据中心的每一个数据包都会受到eBPF的影响。包括软件、云服务、金融服务、电信、媒体娱乐、电子商务、咨询以及安全在内的众多行业企业,正日益增多地采用eBPF技术来提升效率,实现更快速度的作业,节省时间和成本,同时提高性能。

当然,超大规模企业和大型公司拥有大多数公司不具备的优势:成队的软件工程师。为了将eBPF技术推广至更多企业,开源软件项目应运而生,旨在让这项技术即插即用,易于消费。

用例

以下是eBPF在生产环境中三个主要的用例:

可观察性

eBPF首先在可观测性领域崭露头角,并产生了巨大影响。在涉及数十、数百乃至数千台服务器的分布式系统中,增强的可观测性使得企业能够更容易且全面地了解系统时间的分配情况。

例如,它们可以发现瓶颈所在、评估CPU的工作速度,以及更快地定位到可能出错的代码片段。通过将eBPF程序附加到文件打开等事件上,用户可以获得提供系统内部运行状况惊人洞察力的指标。

网络

Linux网络堆栈的许多部分是在几十年前编写的,那时IP地址和端口范围还可以在电子表格上跟踪,而不是像现在每个容器都会变化。eBPF使得程序员能够重写网络堆栈,仅使用所需的部件,或者完全跳过某些环节以节省时间和处理能力。通过绕过不需要的部分或根据构建软件的新方法重写功能,网络性能得到了显著提升。

安全性

eBPF 增强了可观察性,使其更容易发现和防止安全攻击,包括内核内部以及整个 Kubernetes 和云原生环境中的安全攻击。 eBPF 还将安全执行策略推送到分布式环境中,以便实时实施。例如,如果内核中出现漏洞,可以通过 eBPF 进行快速修复,而无需更改内核代码,从而实现动态地安全更新。

虽然 eBPF 已被广泛部署,但它仍处于即将开启的创新大潮的初期阶段。

eBPF 的缺点

eBPF虽然功能强大,但并非万能,它仍受到一些固有限制,且这些限制可能永远不会完全消失。

首先,编写能够通过内核验证器审核的eBPF代码颇具挑战性,尤其是对于新手来说。而且,程序如果未通过验证,验证器也不总会明确告知原因。虽然有一些独立于验证器的工具可以帮助检查程序,以此应对这一挑战,但它们并不能消除程序被拒绝的风险。并且,因为验证是在运行时发生的,就会面临着一种风险:一个内核可能接受程序,而另一个版本的内核却可能拒绝它。

其次,eBPF程序在堆栈空间上存在限制,这使得开发难度增加。(它们过去在指令大小上也有限制,但在内核5.3版中这一限制已被移除)。需要学会高效编写eBPF代码,以实现规模化应用。

第三,尽管eBPF被集成在Linux内核中,但不同内核版本之间的差异以及各Linux发行版的定制化意味着eBPF程序并不总是像期望的那样具备良好的可移植性。如果某些节点运行的是Alpine Linux,而其他节点运行Ubuntu,程序可能并不能在所有节点上顺利运行。虽然提高eBPF可移植性的工作正在进行中,但目前仍未达到人们期待的无缝程度。

链接
https://www.devopsdigest.com/state-of-ebpf
https://www.datadoghq.com/knowledge-center/ebpf/
https://www.groundcover.com/ebpf#what-is-ebpf
https://eunomia.dev/tutorials/0-introduce/
https://www.solo.io/topics/cilium/cilium-ebpf/
https://cloudnativenow.com/features/whats-new-with-cilium-and-whats-next/


  • 本站原创文章仅代表作者观点,不代表SDNLAB立场。所有原创内容版权均属SDNLAB,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用,转载须注明来自 SDNLAB并附上本文链接。 本站中所有编译类文章仅用于学习和交流目的,编译工作遵照 CC 协议,如果有侵犯到您权益的地方,请及时联系我们。
  • 本文链接https://www.sdnlab.com/26501.html
分享到:
相关文章
条评论

登录后才可以评论

SDNLAB君 发表于24-05-15
0