作者:Lavanya Chockalingam,New Relic 高级产品营销经理。最初发表在 New Relic 的博客[1]。
在 Linux 内核中工作是实现安全性、网络和可观察性特性的理想选择。然而,这并不是没有挑战。无论是修改内核源代码,还是添加模块,开发人员传统上发现他们要与难以调试的复杂基础设施和抽象层作斗争。Extended BPF[2](eBPF)解决了这两个问题。
Extended Berkeley Packet Filter(eBPF)是一种内核技术(从 Linux 4.x 开始),它允许程序在无需更改内核源代码,或添加额外模块的情况下运行。你可以将其视为 Linux 内核中的轻量级沙箱虚拟机(VM),程序员可以在其中运行 BPF 字节码,从而利用特定的内核资源。
使用 eBPF 消除了更改内核源代码的需要,并简化了软件利用现有层的能力。因此,它是一项强大的技术,有可能从根本上改变网络、可观察性和安全性等服务的交付方式。
下面详细介绍一下它是什么,它是如何工作的,以及何时考虑实施它。
eBPF 是如何工作
eBPF 程序是事件驱动的,并附加到代码路径上。代码路径包含特定的触发器(称为钩子),这些触发器在传递附加的 eBPF 程序时执行它们。钩子的一些例子包括网络事件、系统调用、函数项和内核追踪点。
当触发时,代码首先被编译为 BPF 字节码。然后,字节码在运行之前会被验证,以确保它不会创建循环。这个步骤可以防止程序无意或故意损害 Linux 内核。
在钩子上触发程序之后,它就会进行助手调用。这些助手调用是为 eBPF 配备许多用于访问内存的特性的函数。助手调用需要由内核预先定义,但是存在的函数列表在不断增长[3]。
eBPF 最初被用作过滤网络数据包时,提高可观察性和安全性的一种方法。然而,随着时间的推移,它成为了一种使用户提供的代码实现更安全、更方便和性能更好的方法。
eBPF 的优点
eBPF 通常用于追踪[4]用户空间进程,它的优点在这里很明显。这是一个安全和有用的方法来确保:
- 速度和性能。eBPF 可以将包处理从内核空间转移到用户空间。同样,eBPF 是即时(JIT)编译器。编译字节码后,将调用 eBPF,而不是为每个方法调用字节码的新解释。
- 低侵入性。当作为调试器使用时,eBPF 不需要停止程序来观察其状态。
- 安全。程序实际上是沙箱化的,这意味着内核源代码仍然受到保护并且没有改变。验证步骤确保资源不会被运行无限循环的程序堵塞。
- 方便。创建钩子内核函数的代码比构建和维护内核模块的工作要少。
- 统一的追踪。eBPF 为你提供了一个用于追踪流程的单一、强大且可访问的框架。这增加了可见性和安全性。
- 可编程性。使用 eBPF 有助于增加环境的特性丰富度,而无需添加额外的层。同样,由于代码直接在内核中运行,因此可以在 eBPF 事件之间存储数据,而不像其他追踪程序那样转储数据。
- 表达能力。eBPF 具有表达性,能够执行通常只能在高级语言中找到的功能。
eBPF 的最佳实践
由于 eBPF 是一项如此新的技术,许多东西仍未被探索。随着技术的发展,围绕 eBPF 的最佳实践仍在不断发展。虽然没有明确的最佳实践集存在,但你可以做一些事情来确保有效、高效的程序。
如果你正在为你的生态系统使用 eBPF,我们建议你:
- 使用LLVM Clang[5]将 C 编译成字节码。当 eBPF 首次出现时,需要手工编写和组装程序。然后,开发人员使用内核的汇编程序生成字节码。幸运的是,现在不再需要这样做了。Clang 提供了 C 语言的前端基础设施和工具。
- 编写 BPF 程序时请使用 BCC 工具包。BPF Compiler Collection[6](BCC)是一个工具包,可以帮助你创建高效的内核追踪和操作程序。它特别适合于性能分析和网络流量控制相关的任务。
eBPF 的缺点
尽管 eBPF 功能强大,但它并不是适合每个项目或生态系统的灵丹妙药。eBPF 确实有一些明显的缺点,这可能会使它在某些实例中工作起来令人沮丧。一些开发人员可能会发现 eBPF 不适合使用,原因如下:
- 它仅限于 Linux 和一个最新的内核。eBPF 是在 Linux 内核中开发的,并且是完全面向 Linux 内核的。这使得它比其他追踪器更难携带。此外,你需要一个相当新的内核。如果你运行的是比 v4.13 更老的版本,你将无法使用它。
- 沙箱程序是有限的。eBPF 通过限制程序可以访问的资源来提高安全性。然而,通过限制程序可以访问的操作系统部分,功能也可能受到限制。
eBPF 的常用情况
eBPF 在云原生应用[7]中正迅速获得关注。因此,eBPF 最常用于两种情况:
- 需要使用内核追踪实现可观察性。在这种情况下,eBPF 更快、更准确。这里不涉及上下文切换[8],而且 eBPF 程序是基于事件的,因此没有特定的触发器就不会运行任何程序——你不会错过任何事件。
- 传统的安全监控不起作用。eBPF 在分布式和基于容器的环境中得到了广泛的应用,包括Kubernetes[9]。在这些环境中,eBPF 可以缩小可见性差距,因为它可以提供对 HTTP 通信的可见性。
你可能还会发现 eBPF 被部署用于其他安全措施,包括:
- 防火墙
- 设备驱动程序
- 网络性能监控
New Relic 和 eBPF
Pixie[10](早前被 New Relic 收购了)是一个开源的 kubernetes-native-in-cluster 可观察平台,它提供了 Kubernetes 工作负载的即时可见性,无需手动检测。eBPF 提供了 Pixie 平台背后的大部分魔力。如前所述,eBPF 允许在触发事件时运行受限制的代码。这个事件可以是内核空间(kprobes)或用户空间(uprobes)中的函数调用。Pixie 同时使用 uprobes 和 kprobes 来支持跨服务和应用程序的可观察性。
Pixie 利用 eBPF 自动获取遥测数据,其边缘机智能将这些数据与 Kubernetes 元数据连接起来,在保持数据局部性的同时提供可见性。这种可见性补充了 New Relic 强大的 Kubernetes 可观测性解决方案。从 5 月底开始,你将能够将 Pixie 生成的遥测数据发送到 New Relic One,获得可扩展的留存率、强大的可视化、高级关联和智能警报功能。
eBPF 是有效的可观察性
eBPF 是一种新技术,它改进了 Linux 内核中的可观察性、联网和安全性。它消除了更改内核源代码或添加模块的需要,因此你可以创建更丰富的基础设施来支持你的系统,而不会使其过于复杂。
总结
我们了解了 eBPF 是什么,它是如何工作的,以及为什么它在分布式环境中如此有用。通过从内核层进行监控,许多与云中的可观测性相关的挑战都得到了解决。你可以在数据中享受更深入的可见性、更多的上下文和更准确的信息。
参考资料
- New Relic 的博客: https://newrelic.com/blog/best-practices/what-is-ebpf
- Extended BPF: https://www.kernel.org/doc/html/latest/bpf/index.html
- 不断增长: https://man7.org/linux/man-pages/man7/bpf-helpers.7.html
- 追踪: https://blog.pixielabs.ai/ebpf-function-tracing/post/
- LLVM Clang: https://clang.llvm.org/
- BPF Compiler Collection: https://github.com/iovisor/bcc
- 云原生应用: https://newrelic.com/solutions/cloud-native
- 上下文切换: https://www.quora.com/What-is-context-switching-in-Linux
- Kubernetes: https://kubernetes.io/blog/2017/12/using-ebpf-in-kubernetes/
- Pixie: http://pixielabs.ai/
本文转载自:「 CNCF 」,原文:https://tinyurl.com/ymz2kh4j ,版权归原作者所有。欢迎投稿,投稿邮箱: editor@hi-linux.com。