eBPF 数据路径介绍

Linux 内核在网络堆栈中支持一组 BPF 钩子(hook),可用于运行 BPF 程序。Cilium 数据路径使用这些钩子来加载 BPF 程序,这些程序一起使用时会创建更高级别的网络结构。

以下是 Cilium 使用的钩子列表和简要说明。有关每个钩子细节的更详尽的文档,请参阅 BPF 和 XDP 参考指南

  • XDP:XDP BPF 钩子位于网络驱动程序中的最早可能点,并在数据包接收时触发 BPF 程序的运行。这实现了可能的最佳数据包处理性能,因为程序在任何其他处理发生之前直接在数据包数据上运行。此钩子非常适合运行丢弃恶意或意外流量的过滤程序以及其他常见的 DDOS 保护机制。

  • 流量控制入口/出口:附加到流量控制(traffic control,简称 TC)入口钩子的 BPF 程序附加到网络接口,与 XDP 相同,但将在网络堆栈完成数据包的初始处理后运行。该钩子在三层网络之前运行,但可以访问与数据包关联的大部分元数据。这非常适合进行本地节点处理,例如应用三层/四层端点策略并将流量重定向到端点。对于面向网络的设备,TC 入口钩子可以与上面的 XDP 钩子耦合。完成此操作后,可以合理地假设此时的大部分流量是合法的并以主机为目的地。

    容器通常使用称为 veth 对的虚拟设备,它充当将容器连接到主机的虚拟路由。通过附加到这个 veth 对的主机端的 TC 入口钩子,Cilium 可以监控和执行所有离开容器的流量的策略。通过将 BPF 程序附加到与每个容器关联的 veth 对,并将所有网络流量路由到主机端虚拟设备,同时将另一个 BPF 程序附加到 TC 入口钩子,Cilium 可以监控所有进入或离开节点的流量并执行策略。

  • 套接字操作:套接字操作钩子附加到特定的 cgroup 并在 TCP 事件上运行。Cilium 将 BPF 套接字操作程序附加到根 cgroup 并使用它来监视 TCP 状态转换,特别是 ESTABLISHED 状态转换。如果 TCP 套接字具有节点本地对等节点(可能是本地代理),则当套接字转换为 ESTABLISHED 状态时,附加套接字发送 / 接收程序。

  • 套接字发送/接收:套接字发送/接收钩子(socket send/recv hook)在 TCP 套接字执行的每个发送操作上运行。此时,钩子可以检查消息并丢弃消息、将消息发送到 TCP 层或将消息重定向到另一个套接字。Cilium 使用它来加速数据路径重定向,如下所述。

将上述钩子与虚拟接口(cilium_hostcilium_net)、可选的 overlay 接口(cilium_vxlan)、Linux 内核加密支持和用户空间代理(Envoy)相结合,Cilium 创建了以下网络对象。

  • 前置过滤器(Prefilter):前置过滤器对象运行一个 XDP 程序并提供一组前置过滤器规则,用于过滤来自网络的流量以获得最佳性能。具体来说,数据包要么被丢弃,例如当目标不是有效的端点时,要么被堆栈处理。这可以根据需要轻松扩展以构建新的前置过滤器标准/功能。

  • 端点策略:端点策略对象实现 Cilium 端点强制。使用映射来查找与身份和策略相关的数据包,该层可以很好地扩展到许多端点。根据策略,该层可能会丢弃数据包、转发到本地端点、转发到服务对象或转发到七层策略对象以获取进一步的七层规则。这是 Cilium 数据路径中的主要对象,负责将数据包映射到身份并执行三层和四层策略。

  • 服务:服务对象对对象接收的每个数据包的目标 IP 和可选的目标端口执行映射查找。如果找到匹配条目,数据包将被转发到配置的三层/四层端点之一。Service 块可用于使用 TC 入口钩子在任何接口上实现独立的负载均衡器,或者可以集成到端点策略对象中。

  • 三层加密:在入口时,三层加密对象标记要解密的数据包,将数据包传递给 Linux xfrm(转换)层进行解密,数据包解密后对象接收数据包,然后将其向上传递到堆栈以供其他人进一步处理对象。根据模式、直接路由或覆盖,这可能是 BPF 尾调用或将数据包传递给下一个对象的 Linux 路由堆栈。解密所需的密钥在 IPsec 标头中编码,因此在入口处我们不需要进行映射查找来查找解密密钥。

    在出口处,首先使用目标 IP 执行映射查找以确定数据包是否应加密,如果加密,则目标节点上可用的密钥。选择两个节点上可用的最新密钥,并将数据包标记为加密。然后将数据包传递到对其进行加密的 Linux xfrm 层。在接收到现在加密的数据包后,通过将其发送到 Linux 堆栈进行路由或在使用覆盖时进行直接尾调用,将其传递到下一层。

  • 套接字层强制:套接字层强制使用两个钩子,套接字操作钩子和套接字发送/接收钩子来监视和附加到与 Cilium 托管端点关联的所有 TCP 套接字,包括任何 七层代理。套接字操作钩子将识别用于加速的候选套接字。这些包括所有本地节点连接(端点到端点)和任何到 Cilium 代理的连接。然后,这些已识别的连接将由套接字发送/接收钩子处理所有消息,并将使用 sockmap 快速重定向加速。快速重定向确保 Cilium 中实现的所有策略对关联的套接字 / 端点映射有效,并假设它们直接将消息发送到对等套接字。这是允许的,因为 sockmap send/recv 钩子确保消息不需要由上述任何对象处理。

  • 七层策略:七层策略对象将代理流量重定向到 Cilium 用户空间代理实例。Cilium 使用 Envoy 实例作为其用户空间代理。然后,Envoy 将根据配置的七层策略转发流量或生成适当的拒绝消息。

这些组件相互连接,以创建 Cilium 使用的灵活高效的数据路径。下面我们展示了连接单个节点上的端点、入口到端点以及端点到出口网络设备的以下可能流程。在每种情况下,都有一个附加图表显示启用套接字层强制时可用的 TCP 加速路径。