当Docker 于 2013 年突然出现时,Linux 容器似乎一夜成名。但容器(以及微服务和Kubernetes)的演变实际上是基于 Linux 操作系统中的内核原语而进行的,历时数十年。
Docker 使用这些原语(即 cgroups 和命名空间)作为构建块来创建一种轻量级、易于使用的软件打包格式。
Google 和其他公司已经使用 Linux 容器多年,但 Docker 让主流开发人员可以轻松访问它们。
这就是我们今天看到的 eBPF,另一种诞生于 Linux 内核原语的技术。
如今,每个主要的网络、可观察性和安全供应商都在声称提供“eBPF 驱动”的产品。
Cilium、Tetragon 和 Falco 等 eBPF 工具正在企业架构和云服务提供商产品中根深蒂固。
据其一位创建者称,这只是基于 eBPF 的突破的开始。
InfoWorld 采访了 eBPF 的联合创始人兼 Linux 内核的当前 eBPF 联合维护者 Daniel Borkmann,以了解有关该技术的起源、eBPF 为何成为编程和定制 Linux 内核的标准方法以及这对 Linux 和平台工程的未来意味着什么的更多信息。
从 Solaris 学生到 Linux 内核维护者
Daniel Borkmann 的 eBPF 之路始于对 Solaris 内部结构的探索,当时他所在大学的计算机科学课程仍在教授 Solaris。然而,一个主要障碍是缺乏源代码,无法看到“魔法发生的地方”。
Borkmann 发现操作系统课程中的理论非常有趣,但真正让他恍然大悟的是他深夜研究 Linux 内核源代码、Git 日志和邮件列表。他开始编写与内核交互的低级用户应用程序。
很快,Borkmann 就开始研究数据包过滤器、tcpdump 和 libpcap,以及数据包来来回回穿越不同层时网络堆栈的工作原理。他在业余时间编写了一个更高效的 tcpdump 克隆,并开始向 Linux 网络堆栈发送小代码改进。
在开始攻读硕士学位时,他最终获得了第一份有偿工作,为德国莱比锡的一家本地初创公司开发 Linux 内核代码。
2010 年,Borkmann 以“完全菜鸟”(他的话)的身份向 Linux 内核提交了他的第一个补丁,以扩展 netpoll,允许每个接口执行多个 rx_hooks,并意外引入了一个可能导致内核死锁的错误,该错误很快被另一位贡献者发现并修复。
但他迷上了 Linux 内核开发。他知道,Linux 内核开发是一个令人着迷的环境,这是他的使命。
Borkmann 搬到苏黎世,完成他的硕士论文,论文主题是为内核开发可组合网络堆栈。从 FreeBSD 的 netgraph 中汲取灵感,他的实验是尝试将网络块卸载到 FPGA 上,并构建可组合的数据包处理图。但在此过程中,他有时发现学术论文太枯燥,对现实世界的长期影响太小,他意识到全职为 Linux 内核做出贡献会更有回报。
他发现了一位名叫 Thomas Graf 的 Linux 贡献者(最终两人都成为 Cilium 的共同创建者),他的电子邮件带有瑞士域名 (.ch),于是自发地联系了他——并被邀请加入 Red Hat 的 Linux 内核网络团队。
如今,Borkmann 是全球 1% 的 Linux 内核贡献者之一。
重新思考 Linux 操作系统中的网络
eBPF 的起源故事实际上始于 2011 年,当时软件定义网络 (SDN) 正在蓬勃发展,Linux 的采用率也在激增。Linux 子系统需要跟上微服务架构和分布式应用程序的新范式,这些应用程序跨 Linux 机器集群运行,而不是在单个服务器和主机操作系统上运行。
Borkmann 在网络堆栈中从事内核开发的工作使他处于满足 SDN 和云原生网络要求的最前线。
Linux 需要更新的抽象,因为它的许多构建块都是 10 多年前设计的 — cgroups(CPU、内存处理)、命名空间(net、mount、pid)、SELinux、seccomp、Netfilter、Netlink、AppArmor、Auditd、Perf 等。
Borkmann 看到 netfilter 的 nftables 等技术被推为“下一代”Linux 网络,以及当时最先进的 SDN 项目 Open vSwitch (OVS)。他相信有更好的方法。
Linux 内核已经为跟上更高的网络速度而付出了巨大的努力,但并没有为编写新的自定义功能提供足够的灵活性。另一个限制是“绝不破坏用户空间”的规定。也就是说,Linux 内核必须继续支持在云原生应用程序出现之前开发的所有软件。不幸的是,这种“遗留包袱”将一些网络创新从内核转移到了用户空间。
简而言之,新的云操作模式带来了更多的自动化、流失和规模,以及更苛刻的网络性能要求。但 Linux 内核中的独立子系统没有在内核中推送、聚合和处理所有这些新云上下文的惯例。
在 Linux 编程中,数据包处理(解析、操作、过滤和转发)是“什么是可能的”的零基础关注点。这是内核开发人员在网络数据包通过堆栈时路由、控制和检查网络数据包的机制。数据包处理之于内核的网络堆栈,就如同化油器之于发动机,通量电容器之于 Doc 的 DeLorean。
应用程序开发人员大多在用户空间中编写应用程序,使用抽象来保护应用程序免受需要对内核进行的系统调用的影响。因此,当应用程序需要与硬件交互时(写入屏幕、写入文件、发送网络数据包),它必须向内核寻求帮助。用户空间无法直接执行此操作(出于各种原因,例如系统安全性)。内核提供用户空间应用程序与硬件之间的通用接口,并协调同时运行的多个用户空间进程。
在从虚拟化到容器的演进过程中,许多不同的数据包过滤方法争夺 Linux 内核的一席之地:iptables、nftables、OVS、Linux 流量控制 (TC) 等等。eBPF 凭借其表现力和验证程序的安全性(同时以原生性能执行程序)而成为首选方法。换句话说,eBPF 允许用户以这些替代方案无法实现的方式对内核进行编程,并且不会冒内核崩溃的风险。
更“可编程”的 Linux 内核
虽然 Borkmann 最初被 eBPF 为网络带来的灵活性和性能所吸引,但很明显,这项新技术的好处远远超出了网络范围。
一旦 eBPF 引入了这种可以立即构建和部署的基础功能,它就解决了一个巨大的问题。
您可以编写嵌入 eBPF 的编排程序,并部署它,无论底层内核版本是什么。而且,您不必向大型供应商支付大量资金来获得核心内核 ABI 稳定性,现在您只需使用 eBPF,而不需要模块来扩展内核以适应许多不同的用例。
eBPF 变成了一种通用汇编语言,允许用户在 Linux 内核中 加载并安全运行自定义程序,这是一种在运行时向操作系统添加各种功能的方法。它具有严格的类型,具有稳定的指令集,并且其扩展是向后兼容的。
将 eBPF 视为一种新型软件,它弥补了典型的单片内核和微内核之间的差距。它是来自可信用户空间的内核的安全扩展。eBPF 的优点在于它与常规内核代码一样快,因为 eBPF 不是沙盒,但验证程序可以完全理解该程序,以确定它在可信环境中运行是否安全,然后将其 JIT [即时编译] 为本机代码。
eBPF 不仅安全、快速,而且运行速度与本机速度相同。它还非常灵活,允许不同的用户以不同的方式使用它。“eBPF 的强大之处在于,只有当您作为用户有该用例或需要以某种方式处理某些事情时,您才可以从用户的角度启用代码。
它不会惩罚其他人。它不像内核中硬编码的东西,会让关键路径越来越慢——性能会受到千刀万剐的惩罚。
Cilium 的 Graf 表示:“在 eBPF 之前,大多数用户使用的是企业 Linux 发行版,或者只是运行设备上安装的任何内核版本。eBPF 从根本上改变了这种情况,因为有了运行时,任何想法都可以在几天内(而不是几年内)变成 eBPF 程序并在运行时加载。这意味着我们可以更好地重建一切。我们必须决定先重建什么。”
内核工程成为主流
和 Google Borg 以及其他诞生于超大规模企业的技术一样,eBPF 最初仅被少数拥有内核开发技能的软件工程公司采用。很少有开发人员具备进行内核工程和编写 eBPF 程序所需的低级 C 编程技能。
但如今,这少数专家编写的程序影响着数百万用户。eBPF 驱动的程序是负责网络、安全和可观察性的平台工程团队最令人兴奋的领域,许多使用这些程序的人不需要了解实现这些程序的底层 eBPF 抽象。
正如 Borkmann 在最近的 eBPF 研讨会主题演讲中指出的那样,“可以将其视为一场来自云原生的无声平台革命”。
以下是 eBPF 领域中众多应用程序的概览:
Cilium最初是基于 eBPF 的容器网络接口(CNI) 实现,用于在容器工作负载之间提供第 3 层和第 4 层连接,但后来逐渐发展成为大多数云服务提供商 Kubernetes 产品的实际网络层。
除其他功能外,Cilium 还为 Kubernetes pod 和外部服务之间的流量实现分布式负载平衡,并且能够完全取代 kube-proxy,使用 eBPF 中的高效哈希表实现几乎无限的扩展。
它还支持高级功能,如第 3 层到第 7 层策略实施、集成入口和出口网关、带宽管理、与 Envoy 结合的服务网格以及深度网络可见性。
Tetragon是另一个提供安全可观察性和运行时强制执行的 eBPF 程序。通过利用 eBPF 的低开销,Tetragon 允许平台团队将网络流和其他内核事件与 Kubernetes 对象(标签、pod、命名空间)绑定到非常具体的进程及其相关进程树。
在XZ Utils等软件供应链安全漏洞出现之后,Tetragon 是一个开源项目,旨在为平台团队提供更深入的方法来查找特定软件在其环境中的运行位置,并在内核级别采取特定的策略操作。
Pixie是一种可观察性工具,它使用 eBPF“自动捕获遥测数据,无需手动操作”。它已成为下一代应用程序性能管理和监控供应商的热门构建模块。
只需在 Google 上搜索“可观察性和 eBPF”,即可看到该技术正在多大程度上改变遥测数据的丰富性,而 eBPF 的性能正是实现这一改变的条件。
推断云原生系统的实时状态历来需要堆积监控数据,而这些数据必须在未来进行关联。将这种遥测数据收集更接近内核,可以实现更高的一致性和更低的资源使用率。
Katran是一个 C++ 库,它可以通过一种基于内核数据包处理的新方法挑战专有第 3 层和第 4 层负载均衡器的现状。并非每个人都可以创建 eBPF 程序,但正在创建的程序针对的是企业基础设施中相对停滞不前的领域,并且迫切需要对云原生用例进行现代化改造。
未来十年的基础设施软件将由能够使用 eBPF 的平台工程师和利用 eBPF 为更高级别平台创建正确抽象的项目来定义。
将云原生上下文推入内核是缺失的,而 eBPF 解决了这个问题。
本月,我们迎来了Kubernetes 十周年纪念日,但我们仍处于分布式应用程序、容器编排和平台工程的早期阶段。
很少有人可能直接在内核级别设计 eBPF,但数百万人将使用基于 eBPF 的程序。
如果您在大型公共云提供商平台上的 Kubernetes 上运行工作负载,那么您可能已经这样做了。