eBPF如何简化服务网格

目前有几个服务网格产品和项目,有望简化应用程序微服务之间的连接。同时提供附加功能,如安全连接、可观察性和流量管理。但正如我们在过去几年中反复看到的那样,对服务网格的兴奋已经被对额外的复杂性和开销的实际担忧冲淡了。让我们来看看 EBPF 如何简化,使服务网格数据平面更高效、更易于部署。

Sidecar 问题

如今,Kubernetes 的服务网格解决方案要求您将代理 sidecar 容器(如Envoy或Linkerd-Proxy)添加到每个应用程序 Pod。这是正确的:即使在一个非常小的环境中,比如说,有20个服务,每个服务运行5个 pod,分布在三个节点上,您也有100个代理容器。无论代理实现多么小、多么高效,纯粹的重复都会耗费资源。 每个代理使用的内存随着它需要与之通信的服务数量的增加而增加。Pranay Singhal 写了他配置 Istio 的经验,以减少每个代理大约1GB的消耗(!)到更合理的60-70MB。但是,即使在我们想象的三个节点上有100个代理的小型环境中,这种优化配置仍然需要每个节点大约2GB。

为什么我们需要这些 sidecar?此模型允许代理容器与 Pod 中的应用程序容器共享网络命名空间。网络名称空间是 Linux 内核构造,它允许容器和 pod 拥有自己独立的网络堆栈,将集装箱化应用程序彼此隔离。这使得应用程序互不干扰,这就是为什么,在端口80上运行 Web 应用程序时,您可以拥有任意数量的 pod —网络名称空间意味着它们都有自己的端口80。代理必须共享相同的网络命名空间,以便它可以拦截和处理来自应用程序容器的流量。

eBPF

重要的是,每个节点只有一个内核;在一个节点上运行的所有容器(以及所有pod)共享相同的内核。如果您将EBPF程序添加到内核中的事件,则无论哪个进程导致该事件,无论它是在应用程序容器中运行还是直接在主机上运行,它都将被触发。

这就是为什么 eBPF 对于 Kubernetes 中的任何类型的工具都是如此令人兴奋的技术—您只需要为每个节点添加一次工具,所有的应用程序单元都将被覆盖。无论您是在寻求可观察性、安全性还是联网,基于 EBPF 的解决方案都可以在不需要 Sidecar 的情况下为应用程序提供仪表。

基于 eBPF 的 Cilium 项目(最近在孵化阶段加入了云计算基金会)将这种“无边”模型引入了服务网格世界。与传统的 Sidecar 模型一样,Cilium 支持每个节点使用单个 Envoy 代理实例来运行服务网格数据平面。使用前面的示例,这将代理实例的数量从100个减少到3个。

更少的 YAML

在 Sidecar 模型中,需要修改指定每个应用程序 Pod 的 YAML 以添加 Sidecar 容器。这通常是自动化的——例如,在部署每个应用程序 Pod 时,使用 Mutating webhook 来注入 sidecar。

例如,在 Istio 中,这需要标记 Kubernetes 命名空间和/或pod来定义是否应该注入 sidecar ,当然这需要为集群启用 Mutating webhook。

但如果出了问题怎么办?如果名称空间或 pod 的标签不正确,则不会注入 sidecar,pod 也不会连接到服务网格。更糟糕的是,如果攻击者破坏了集群并能够运行恶意工作负载(例如加密货币矿工),他们将不太可能对其进行标记,使其参与服务网格。通过服务网格提供的流量可观察性,它将不可见。

相反,在支持 eBPF 的 Sidecarless 代理模型中,POD 不需要任何额外的 YAML 来进行插装,而是使用 CRD 在集群的基础上配置服务网格。即使是预先存在的 pod 也可以成为服务网格的一部分,而不需要重新启动。

如果攻击者试图通过直接在主机上运行工作负载来绕过 Kubernetes 编排,eBPF 程序可以看到并控制此活动,因为它在内核中是可见的。

eBPF 的网络效率

消除 Sidecar 并不是 eBPF 优化服务网格的唯一方法。支持 EBPF 的网络允许数据包采用绕过部分内核网络堆栈的捷径,这可以显著提高 Kubernetes 网络的性能。让我们看看这如何应用于服务网格数据平面。在服务网格的情况下,代理作为传统网络中的 Sidecar 运行,数据包到达应用程序的路径相当曲折:入站数据包必须遍历主机 TCP/IP 堆栈才能到达POD通过虚拟以太网连接的网络命名空间。从那里,数据包必须通过 Pod 的网络堆栈才能到达代理,它通过环回接口将数据包转发到应用程序。请记住,流量必须流经连接两端的代理,与非服务网格流量相比,这导致延迟显著增加。

基于 eBPF 的 Kubernetes CNI 实现(如Cilium)可以使用 eBPF 程序,明智地挂接到内核中的特定点,以沿着更直接的路由重定向数据包。Cilium 知道所有的 Kubernetes 端点和服务身份,所以这是可行的。当数据包到达主机时,Cilium 可以将其直接发送到其目的地的代理或 Pod 端点。

网络中的加密

如果网络解决方案能够识别 Kubernetes 服务,并在这些服务的端点之间提供网络连接,那么它能够提供服务网格数据平面的功能也就不足为奇了。但这些功能可以超越基本的连接。一个例子是透明加密。

通常使用服务网格来确保所有应用程序流量都经过身份验证和加密。这是通过双向 TLS(MTLS)实现的。服务网格代理组件充当网络连接的端点,并与其远程对等体协商安全TLS连接。此连接对代理之间的通信进行加密,而无需对应用程序进行任何更改。

但是,在应用层管理的TLS并不是在组件之间实现身份验证和加密通信的唯一方法。另一种选择是使用 IPSec或WireGuard 在网络层加密流量。由于它工作在网络层,这种加密不仅对应用程序而且对代理都是完全透明的,并且它可以在有或没有服务网格的情况下启用。如果使用服务网格的唯一原因是提供加密,则可能需要考虑网络级加密。它不仅更简单,但它也可用于对节点上的任何流量进行身份验证和加密—它不仅限于那些启用了Sidecar的工作负载。

原文出自 https://thenewstack.io/how-ebpf-streamlines-the-service-mesh/

SolarMesh免费体验地址»