将代码注入 Linux 内核的能力开辟了一个全新的可能性世界。您可以轻松改进很多东西——安全性、网络、可观测性等等。BPF(伯克利包过滤器)使您能够编写可以从内部利用 Linux 内核功能的程序。BPF 传统上用于在将原始网络数据包发送到用户空间之前对其进行过滤,以提高系统的整体安全性。
eBPF是 BPF 的扩展版本,具有一系列安全实现,以防止 BPF 程序破坏内核。在本指南中,您将了解如何使用 eBPF 在基于 Kubernetes 的基础架构中实现增强的可观测性。
什么是 eBPF?
eBPF 代表扩展 BPF。顾名思义,它是建立在 Linux 标准 BPF 可观测性系统之上的扩展版本。eBPF 程序通过触发器(或挂钩)附加到 Linux 代码路径。这里的主要目标之一是不对内核源代码进行任何更改以减少对其造成任何损害的机会。
您可以将其视为 Linux 内核中的虚拟机或沙箱,使您能够访问特定的内核资源,同时限制自己对内核本身进行更改。每当跨越用户空间边界时,eBPF 也会特别注意安全性和稳健性。
eBPF 可以通过多种方式强制执行安全构造。这里有一些例子:
- 如果内核内验证程序检测到无效的指针取消引用或达到最大堆栈大小限制,它将不会加载 eBPF 程序。
- 不允许使用循环,除非具有预定义的静态上限
- 在生成的字节码中只允许调用一小部分 eBPF 辅助函数。
有了所有这些限制,人们可能会发现这些程序受到限制。然而,保证不弄乱内核通常胜过这些限制。
eBPF 如何用于帮助监控?
eBPF 程序直接在 Linux 内核中运行。这使他们可以轻松地跟踪操作系统子系统的几乎任何方面,包括 CPU 调度程序、网络、系统调用等。您可以通过 eBPF 程序查看和跟踪操作系统中发生的几乎所有事情。这使其成为在基于 Linux 的部署中设置全局和根深蒂固的监控的可行竞争者。
此外,eBPF 程序不依赖于任何外部模块或依赖项。因此,此类程序添加到 Linux 程序的标准工作负载的性能开销可以忽略不计。在其上运行监控系统几乎不会给您部署的工作负载增加额外的负载。
另一个需要思考的方面是容器优化操作系统的兴起。此类操作系统,包括Google Cloud Platform 的 Container-Optimized OS,为 K8s 应用程序提供了优化的运行环境;但是,它们的设计大多是不可变的,以减少代码占用并增强扩展性。它们也不允许使用内核模块。eBPF 在这种情况下仍然有效,因为它是 Linux 原生的,并且提供了一种完全不依赖内核模块来提取数据的方法。
使用 eBPF 增强监控的 4 个好处
既然您了解了它的工作原理并在 Kubernetes 监控中发挥着不可或缺的作用,那么这里有一些方法可以增强您的监控工作。
优点:低侵入性
在与内核及其资源交互时,它专注于极简主义。它旨在尽可能减少干扰。以下是它这样做的一些方法:
- 它不会改变任何内核源代码,从而减少了 eBPF 程序与内核之间的耦合。
- 当将其用作调试器时,它不需要停止正在运行的程序来观测其状态。
- 只允许一小部分内核辅助函数,进一步减少两者之间的依赖/耦合,并有助于建立一个沙盒环境来运行您的程序。
优点:安全
上述措施还有助于增强内核和程序的安全性。
由于 eBPF 程序根本不允许修改内核,因此可以轻松保留代码级更改的访问管理规则。否则,这将使用内核模块完成,这会带来过多的安全问题。
此外,eBPF 程序在转换为字节码后会经过验证阶段。此步骤检查程序中是否存在资源泄漏,例如无限循环。此验证可防止程序意外过度使用系统上的可用资源。
优点:方便
它为您的监控工作提供了更大的便利。与任何其他 Linux 监控替代方案相比,您可以获得更精细的细节和内核上下文。您还可以自由导出监控数据并将其摄取到第三方可视化工具中。
除此之外,如果你从高层次的角度看一下 BPF 编程的概念,与维护独立的内核模块相比,添加挂钩到内核函数的代码片段更有意义,也更容易。
优点:可编程性
与标准检测技术相比,它为您提供了在转储数据之前对记录的数据运行操作的空间。您可以选择在 eBPF 事件之间存储数据,并根据需要选择性地存储数据。此功能在不添加额外依赖项的情况下提高了监控系统的整体实用性。
4 个使用 eBPF 的特定用例?
以下是四个特定用例,在这些用例中,它是获得深度可见性的最佳选择。
Kubernetes 可观测性
Kubernetes是展示 eBPF 可观测性能力的最佳场所之一。众所周知,Kubernetes 通过增加或减少 pod 的数量来上下扩展工作负载。豆荚本质上是随机的,没有保证的生命周期。因此,在每个 pod 或容器中设置检测代理可能会在工作负载中引入性能问题,并且由于 pod 将随机创建和销毁,因此效果不佳。
使用它,您可以在操作系统级别设置监控阵营并监控Kubernetes 设置中发生的所有事情。
动态网络性能监控
我们已经多次提到 eBPF 如何非常容易地监控和跟踪 Linux 子系统的内部方面,例如 CPU 使用率、网络性能等。您可以利用 eBPF 的这一特性来创建网络性能监控设置。但是,这样的设置将是静态的,因为用于监控网络的规则是预定义的常量。您仍然可以手动更改它们,但这是一个漫长的过程。
为了让这个系统真正动态化,你可以引入Cilium,一个帮助你在 eBPF 中进行规则管理的开源项目。Cilium 可以帮助您逐包分析网络流量使用情况,并自动调整 eBPF 规则以适应传入的工作负载需求。您可以利用它来创建真正动态的网络性能监控设置。
内核跟踪
重申 eBPF 的工作原理——它允许您在 Linux 内核中运行自定义代码。由于系统中发生的所有活动都在内核中完成,因此从一个地方跟踪和跟踪所有内容变得很容易。您还可以设置要根据系统事件执行的 eBPF 程序。这使您能够跟踪围绕此类事件发生的一切。
这也是实现内核跟踪的最安全方法之一,因为所有 eBPF 程序都经过验证阶段,在该阶段检查它们是否存在无限循环和其他错误可能性。因此,您可以安全地依赖它来满足您的内核跟踪要求。
Pod 级网络监控
eBPF 最流行的用途之一是在基于 Kubernetes 的系统中监控 Pod 周围的网络。由于基于 Kubernetes 的设置可以运行各种应用程序,并且每个应用程序都有自己独特的基础映像,因此使用传统方法对其进行检测非常具有挑战性。基本操作系统、云服务器或编码标准的每个变体都可能需要不同的监控代理。
通过 eBPF 实施网络监控可以帮助您解决这些问题。此外,您可以在Linux cgroup级别执行套接字过滤。eBPF 程序将帮助您获得粒度信息,否则这些信息只能在 Linux 的 /sys 目录中访问。由于您可以通过 eBPF 访问内核,因此您可以从内核中接收到更详细的信息以及上下文。
最后的想法
eBPF 是对传统 BPF 机制的一个很好的补充。它为您提供了额外的安全优势,同时实现了传统 BPF 程序的深度可观测性优势。
在本指南中,我们讨论了如何使用 eBPF 来增强 Kubernetes 设置中的可观测性。我们讨论了使用 eBPF 相对于传统 BPF 的一些好处,并提到了一些用例,您可以在其中利用它来获得最佳结果。