这是本节的多页打印视图。 点击此处打印.

返回本页常规视图.

文档

帮助您了解如何使用 Merbridge

Merbridge 旨在使用 eBPF 代替 iptables 技术,加速服务网格的数据平面。

1 - 概览

本文概述了 Merbridge 的含义、特性、适用场景等内容。

Merbridge 是什么

Merbridge 专为服务网格设计,使用 eBPF 代替传统的 iptables 劫持流量,能够让服务网格的流量拦截和转发能力更加高效。

eBPF (extended Berkeley Packet Filter) 技术可以在 Linux 内核中运行用户编写的程序,而且不需要修改内核代码或加载内核模块,目前广泛应用于网络、安全、监控等领域。相比传统的 iptables 流量劫持技术,基于 eBPF 的 Merbridge 可以绕过很多内核模块,缩短边车和服务间的数据路径,从而加速网络。Merbridge 没有对现有的 Istio 作出任何修改,原有的逻辑依然畅通。这意味着,如果您不想继续使用 eBPF,直接删除相关的 DaemonSet 就能恢复为传统的 iptables 方式,不会出现任何问题。

Merbridge 有哪些特性

Merbridge 的核心特性包括:

  • 出口流量处理

    Merbridge 使用 eBPF 的 connect 程序,修改 user_ipuser_port 以改变连接发起时的目的地址,从而让流量能够发送到新的接口。为了让 Envoy 识别出原始目的地址,应用程序(包括 Envoy)会在收到连接之后调用 get_sockopts 函数,获取 ORIGINAL_DST。

  • 入口流量处理

    入口流量处理与出口流量处理基本类似。需要注意的是,eBPF 是全局性的,不能在指定的命名空间生效。因此,如果对原本不是由 Istio 管理的 Pod 或者对外部的 IP 地址执行此操作,就会导致请求无法建立连接。为了解决此问题,Merbridge 设计了一个小的控制平面(以 DaemonSet 方式部署),通过 Watch 所有的 Pod,用类似于 kubelet 的方式获取当前节点的 Pod 列表,然后将已经注入 Sidecar 的 Pod IP 地址写入 local_pod_ips map。如果流量的目的地址不在该列表中,Merbridge 就不做处理,转而使用原来的逻辑。这样就可以灵活且便捷地处理入口流量。

  • 同节点加速

    在 Istio 中,Envoy 使用当前 PodIP 加服务端口来访问应用程序。由于 PodIP 肯定也存在于 local_pod_ips ,所以请求就会被转发到 PodIP + 15006 端口。这样会造成无限递归,不能在 eBPF 获取当前命名空间的 IP 地址信息。因此,需要一套反馈机制:在 Envoy 尝试建立连接时仍然重定向到 15006 端口,在 sockops 阶段判断源 IP 和目的 IP 是否一致。如果一致,说明发送了错误的请求,需要在 sockops 丢弃该连接,并将当前的 ProcessID 和 IP 地址信息写入 process_ip map,让 eBPF 支持进程和 IP 的对应关系。下次发送请求时直接从 process_ip 表检查目的地址是否与当前 IP 地址一致。Envoy 会在请求失败时重试,且这个错误只会发生一次,后续的连接会非常快。

为什么需要 Merbridge

在服务网格场景中,为了能在应用程序完全无感知的情况下利用边车进行流量治理,需要把 Pod 的出入口流量都转发到边车。在这种情况下,最常见的解决方案就是使用 iptables (netfilter) 的重定向能力。这种方案的缺点是增加了网络延迟,因为 iptables 对出口流量和入口流量都进行拦截。以入口流量为例,原本直接流向应用的流量,需要先由 iptables 转发到边车,再由边车将流量转发到实际的应用。原本只需要在内核态处理两次的链路如今变成四次,损失了不少性能。

幸运的是,eBPF 技术提供了一个 bpf_msg_redirect_hash 函数,可以将应用发出的数据包直接转发到对端的 socket,从而极大地加速数据包在内核中的处理流程。我们希望用 eBPF 技术代替 iptables 提高服务网格的效率,于是 诞生了 Merbridge。

Merbridge 适用哪些场景

如果您遇到下列任一问题,建议使用 Merbridge:

  1. 在需要高性能连接的场景下,使用 iptables 会增加延迟。
    • 由于集群中容器数量增加,iptables 控制面和数据面的性能会急剧下降。在 iptables 控制面的接口设计中,每添加一条规则都需要遍历并修改所有的规则。
    • 由于 Pod 生命周期越来越短,有时甚至只有几秒钟,这就需要快速更新 iptables 规则,使用 IP 地址进行安全过滤的系统将承受越来越大的压力。
    • 由于使用 iptables 实现透明劫持需要借助 conntrack 模块跟踪连接,连接较多时会造成大量消耗。
  2. 系统因某些原因不能使用 iptables。
    • 有时需同时处理大量活动连接,但使用 iptables 容易出现 conntrack 表满的情况。
    • 有时又需每秒处理极大数量的连接,但超出了 conntrack 表的限制。例如,在超时设置为 120 秒且表容量是 128k 的情况下,如果尝试每秒处理 1100 个连接,就会超出 conntrack 表的限制(128k/120秒 = 1092 连接/秒)。
  3. 出于安全考虑不能为普通的 Pod 授予太多权限,但使用 Istio(若无 CNI)必须允许 Pod 获得更多权限。
    • 运行 init 容器,可能需要 NET_ADMIN 等权限。
    • 运行 iptables 命令,对应的进程可能需要 CAP_NET_ADMIN 权限。
    • 挂载文件系统,对应的进程可能需要 CAP_SYS_ADMIN 权限。

Merbridge 如何改变连接关系

使用 eBPF 在主机上处理连接,可以显著简化内核处理流量的流程,提升服务之间的通讯质量。

Merbridge 是完全独立的开源项目,目前仍处于早期阶段。希望有更多的用户或开发者参与其中,不断完善 Merbridge,共同优化服务网格。如果您发现了 Merbridge 的漏洞而且有兴趣帮助修复,非常欢迎您提交 Pull Request,附上您的修复代码,我们会及时处理您的 PR。

2 - 快速入门

本文将帮助您快速使用 Merbridge

先决条件

  1. 系统的内核版本应大于等于 5.7,可以使用 uname -r 查看。
  2. 系统应开启 cgroup2,可以通过 mount | grep cgroup2 进行验证。

安装

目前支持在 Istio 和 Linkerd2 环境下安装 Merbridge。

Istio 环境

只需要在环境中执行以下命令即可安装 Merbridge:

kubectl apply -f https://raw.githubusercontent.com/merbridge/merbridge/main/deploy/all-in-one.yaml

Linkerd2 环境

只需要在环境中执行以下命令即可安装 Merbridge:

kubectl apply -f https://raw.githubusercontent.com/merbridge/merbridge/main/deploy/all-in-one-linkerd.yaml

Kuma 环境

只需要在环境中执行以下命令即可安装 Merbridge:

kubectl apply -f https://raw.githubusercontent.com/merbridge/merbridge/main/deploy/all-in-one-kuma.yaml

验证

验证安装

在验证 Merbridge 是否能正常工作之前,需要先确保 Merbridge 的 Pod 都运行正常。以 Istio 为例,可以使用以下命令查看 Merbridge 的 Pod 状态:

kubectl -n istio-system get pods

当 Merbridge 相关的所有 Pod 都处于 Running 状态时,表明 Merbridge 已经安装成功。

连接测试

可以按照如下方案验证 Merbridge 的连接是否正常:

安装 sleep 和 helloworld 应用并等待其完全启动

kubectl label ns default istio-injection=enabled
kubectl apply -f https://raw.githubusercontent.com/istio/istio/master/samples/sleep/sleep.yaml
kubectl apply -f https://raw.githubusercontent.com/istio/istio/master/samples/helloworld/helloworld.yaml

执行 curl 测试

kubectl exec $(kubectl get po -l app=sleep -o=jsonpath='{..metadata.name}') -c sleep -- curl -s -v helloworld:5000/hello

如果在结果中看到类似 * Connected to helloworld (127.128.0.1) port 5000 (#0) 的字样(其中 IP 以 127 开头),表明 Merbridge 已经成功使用 eBPF 代替 iptables 进行流量转发。

3 - 概念

本文介绍 Merbridge 项目中的一些关键概念

eBPF

eBPF 全称为 Extended Berkeley Packet Filter,顾名思义,这是一个用来过滤网络数据包的模块。 例如 eBPF 的 sockops 和 redir 能力,就可以高效地过滤和拦截数据包。

eBPF 是一项起源于 Linux 内核的革命性技术,可以在操作系统的内核中运行沙盒程序,能够安全、有效地扩展 Linux 内核的功能,无需改变内核的源代码,也无需加载内核模块。

iptables

iptables 是建立在 netfilter 之上的流量过滤器,通过向 netfilter 的挂载点上注册钩子函数来实现对流量过滤和拦截。 从 iptables 这个名字上可以看出有表的概念,iptables 通过把这些规则表挂载在 netfilter 的不同链上, 对进出内核协议栈的流量数据包进行过滤或者修改。

iptables 默认有 4 个表:

  • Filter 表(数据过滤表)
  • NAT 表(地址转换表)
  • Raw 表(状态跟踪表)
  • Mangle 表(包标记表)

iptables 默认有 5 个链:

  • INPUT 链(入站规则)
  • OUTPUT 链(出站规则)
  • FORWARD 链(转发规则)
  • PREROUTING 链(路由前规则)
  • POSTROUTING 链(路由后规则)

Service Mesh

中文名为服务网格,这是一个可配置的低延迟基础设施层,通过 API 接口处理应用服务之间的网络进程间通信。 服务网格能确保容器化应用基础结构服务之间的通信快速、可靠和安全。网格提供的关键功能包括服务发现、负载均衡、 安全加密和身份验证、故障恢复、可观测性等。

服务网格通常会为每个服务实例注入一个 Sidcar 的代理实例。这些 Sidcar 会处理服务间的通信、监控和安全等问题。 这样,开发人员就可以专注于服务中应用代码的开发、支持和维护,而运维团队负责服务网格以及应用的维护工作。

目前最著名的服务网格架构是 Istio。

Istio

Istio 是最初由 IBM、Google 和 Lyft 开源的服务网格技术。它可以透明地分层到分布式应用上, 并提供服务网格的所有优点,例如流量治理、安全性和可观测性等。

Istio 能够适配本地部署、云托管、Kubernetes 容器以及虚拟机上运行的服务程序。 通常与 Kubernetes 平台上部署的微服务一起使用。

从根本上讲,Istio 的工作原理是以 Sidcar 的形式将 Envoy 的扩展版本作为代理布署到每个微服务中。 其使用的代理网络构成了 Istio 的数据平面。而这些代理的配置和管理在控制平面完成,为数据平面中的 Envoy 代理提供发现、配置和证书管理。

Linkerd

Linkerd 是市场上出现的第一个服务网格。

Linkerd 是 Buoyant 为 Kubernetes 设计的开源、超轻量级的服务网格。用 Rust 语言完全重写, 使其尽可能小、轻和安全,它提供了运行时调试、可观测性、可靠性和安全性,而无需在分布式应用中更改代码。

Linkerd 有三个基本组件:UI、数据平面和控制平面。Linkerd 通过在每个服务实例旁安装一组超轻、透明的代理来工作, 这些代理会自动处理进出服务的所有流量。

4 - 参与贡献

本文介绍参与 Merbridge 项目的方式

Merbridge 目前托管在 GitHub 上进行开源,所有与代码相关的事情都在 GitHub 上进行管理。

如果您对 Merbridge 有疑问,需要我们帮忙解决问题,或者想要提供一些新的功能,可以在 GitHub 上创建新的 Issue,我们会及时查看并处理。

如果您发现了 Merbridge 的 bug,并且有兴趣帮助我们修复,那么非常欢迎您提交 Pull Request,附带上您的修复代码,我们会及时处理您的 PR。