第五章:云原生环境中的 eBPF

近年来,云原生应用已呈指数级增长。在本章中,我将讨论为什么 eBPF 如此适合于云原生环境。为了更具象化,我将提到 Kubernetes,但同样适用于任何容器平台。

每台主机一个内核

要理解为什么 eBPF 在云原生世界中如此强大,你需要搞清楚一个概念:每台机器(或虚拟机)只有一个内核,所有运行在该机器上的容器都共享同一个内核 1图 5-1 所示,内核了解主机上运行的所有应用代码。

图 5-1
图 5-1. 同一主机上的所有容器共享一个内核

通过对内核的检测,就像我们在使用 eBPF 时做的那样,我们可以同时检测在该机器上运行的所有应用程序代码。当我们将 eBPF 程序加载到内核并将其附加到事件上时,它就会被触发,而不考虑哪个进程与该事件有关。

eBPF 与 sidecar 模式的比较

在 eBPF 之前,Kubernetes 的可观测性和安全工具大多都采用了 sidecar 模式。这种模式允许你在与应用程序相同的 pod 中,单独部署一个工具容器。这种模式的发明是一个进步,因为这意味着不再需要直接在应用程序中编写工具代码。仅仅通过部署 sidecar,工具就获得了同一 pod 中的其他容器的可视性。注入 sidecar 的过程通常是自动化的,所以这提供了一种机制,以确保你的所有应用程序都被仪器化。

每个 sidecar 容器都会消耗资源,而这要乘以注入了 sidecar 的 pod 的数量。这可能是非常重要的 —— 例如,如果每个 sidecar 需要它自己的路由信息副本,或策略规则,这就是浪费(关于这一点,Thomas Graf 写了一篇 关于服务网格 sidecar 与 eBPF 的比较)。

Sidecar 的另一个问题是,你不能保证机器上的每一个应用程序都被正确检测。设想下有一个攻击者设法破坏了你的一台主机,并启动了一个单独的 pod 来运行,比如,加密货币挖矿程序。他们不可能对你有礼貌,用你的 sidecar 可观测或安全工具来检测他们的挖矿 pod。你需要一个单独的系统来了解这种活动。

但同样的加密货币矿工与运行在该主机上的合法 pod 共享内核。如果你使用基于 eBPF 的工具,如 图 5-2 所示,矿工会自动受到它的影响。

图 5-2
图 5-2. 旁观者只能观测到他们自己 pod 的活动,但 eBPF 程序可以观测到所有活动

eBPF 和进程隔离

我主张将功能整合到一个单一的、基于 eBPF 的代理中,而不是每个 pod 的 sidecar 中。如果该代理可以访问机器上运行的所有 pod,这不是一种安全风险吗?我们不是失去了应用程序之间的隔离,而这种隔离可以防止它们相互干扰吗?

作为一个容器安全领域的过来人,我可以体会到你对此的担忧,但重要的是要挖掘底层机制,以真正理解为什么它不是一开始可能出现的缺陷。

请注意,这些 pod 共享同一个内核,而内核原生不能感知 pod 或容器。相反,内核对进程进行操作,并使用 cgroup 和 namespace 来隔离进程。这些结构由内核监管,以隔离用户空间中的进程,防止它们互相干扰。只要数据在内核中处理(例如,从磁盘中读取或发送到网络中),你就依赖于内核的正确行为。只有内核代码控制文件权限。没有其他层面的东西可以阻止内核忽略文件权限的东西,内核可以从任何文件中读取数据 —— 只是内核本身不会这样做。

存在于 Linux 系统中的安全控制措施假定内核本身是可以信任的。它们的存在是为了防止在用户空间运行的代码产生不良行为。

我们在 第二章 中看到,eBPF 检查器确保 eBPF 程序只能访问它有权限的内存。检查器检查程序时不可能超出其职权范围,包括确保内存为当前进程所拥有或为当前网络包的一部分。这意味着 eBPF 代码比它周围的内核代码受到更严格的控制,内核代码不需要通过任何类型的检查器。

如果攻击者逃脱了容器化的应用程序而到了节点上,而且还能够提升权限,那么该攻击者就可以危害到同一节点上的其他应用程序。由于这些逃逸是未知的,作为一个容器安全专家,我不建议在没有额外安全工具的情况下,在共享机器上与不受信任的应用程序或用户一起运行敏感的应用程序。对于高度敏感的数据,你甚至可能不希望在虚拟机中与不受信任的用户在同一裸机上运行。但是,如果你准备在同一台虚拟机上并行运行应用程序(这在许多不是特别敏感的应用程序中是完全合理的),那么 eBPF 就不会在共享内核已经存在的风险之上增加额外的风险。

当然,恶意的 eBPF 程序可能造成各种破坏,当然也很容易写出劣迹的 eBPF 代码 —— 例如,复制每个网络数据包并将其发送给窃听者。默认情况下,非 root 用户没有加载 eBPF 程序 2 的权限,只有当你真正信任他们时,你才应该授予用户或软件系统这种权限,就像 root 权限一样。因此,必须小心你所运行的代码的出处(有一个倡议正在进行中,以支持 eBPF 程序的签名检查来帮助解决这个问题)。你也可以使用 eBPF 程序来监视其他的 eBPF 程序!现在你已经对为什么 eBPF 是云原生工具的强大基础有了一个概念,下一章给你举一些来自云原生生态系统中的 eBPF 工具的具体例子。

参考


  1. 这基本正确,除非你使用的是虚拟化技术,像 KataContainer、Firecracker 或 unikernels 这样的方法,每个 “容器” 在自己的虚拟机中运行。 ↩︎

  2. Linux CAP_BPF 授予加载 BPF 程序的权限。 ↩︎