Aeraki — 在 Istio 服务网格中管理任何 7 层协议
Aeraki 提供了一个框架,允许 Istio 支持除 HTTP 之外的更多 7 层协议。
Aeraki [Air-rah-ki] 是希腊语中“微风”的意思。Istio 在服务网格中连接微服务,而 Aeraki 提供了一个框架,允许 Istio 支持除 HTTP 和 gRPC 之外的更多 7 层协议。我们希望这阵微风能帮助 Istio 航行得更远。
服务网格中缺少协议支持
我们现在在服务网格方面面临一些挑战
- Istio 和其他流行的服务网格实现对除 HTTP 和 gRPC 之外的 7 层协议的支持非常有限。
- Envoy RDS(路由发现服务)专为 HTTP 设计。其他协议(如 Dubbo 和 Thrift)只能使用监听器内联路由进行流量管理,这会在路由更改时中断现有连接。
- 将专有协议引入服务网格需要付出很多努力。您需要编写一个 Envoy 过滤器来处理数据平面中的流量,以及一个控制平面来管理这些 Envoy。
这些障碍使得用户很难(如果不是不可能的话)在微服务中管理其他广泛使用的 7 层协议的流量。例如,在一个微服务应用程序中,我们可能拥有以下协议
- RPC:HTTP、gRPC、Thrift、Dubbo、专有 RPC 协议…
- 消息传递:Kafka、RabbitMQ…
- 缓存:Redis、Memcached…
- 数据库:MySQL、PostgreSQL、MongoDB…
如果您已经投入大量精力迁移到服务网格,当然,您希望充分利用它——管理微服务中所有协议的流量。
Aeraki 的方法
为了解决这些问题,我们创建了一个开源项目,Aeraki Mesh,以提供一种非侵入性、可扩展的方式来管理 Istio 服务网格中的任何 7 层流量。
如图所示,Aeraki 框架由以下组件组成
- Aeraki:Aeraki 为运维人员提供高级、用户友好的流量管理规则,将规则转换为 envoy 过滤器配置,并利用 Istio 的
EnvoyFilter
API 将配置推送到 sidecar 代理。Aeraki 还充当数据平面中 MetaProtocol 代理的 RDS 服务器。与专注于 HTTP 的 Envoy RDS 相反,Aeraki RDS 旨在为所有 7 层协议提供通用的动态路由功能。 - MetaProtocol 代理:MetaProtocol 代理 为 7 层协议提供通用功能,例如负载均衡、断路器、负载均衡、路由、速率限制、故障注入和身份验证。7 层协议可以构建在 MetaProtocol 之上。要将新协议添加到服务网格中,您唯一需要做的事情就是实现编解码器接口和几行配置。如果您有内置功能无法满足的特殊需求,MetaProtocol 代理还具有应用程序级过滤器链机制,允许用户编写自己的 7 层过滤器以将自定义逻辑添加到 MetaProtocol 代理中。
Dubbo 和 Thrift 已经基于 MetaProtocol 实现。更多协议正在开发中。如果您使用的是闭源的专有协议,您也可以通过为其编写 MetaProtocol 编解码器来在您的服务网格中管理它。
大多数请求/响应样式的无状态协议可以构建在 MetaProtocol 代理之上。但是,某些协议的路由策略过于“特殊”,无法在 MetaProtocol 中标准化。例如,Redis 代理使用槽位号将客户端查询映射到特定的 Redis 服务器节点,并且槽位号由请求中的键计算得出。只要 Envoy 代理端有可用的 Envoy 过滤器,Aeraki 仍然可以管理这些协议。目前,对于此类协议,Redis 和 Kafka 在 Aeraki 中受支持。
深入 MetaProtocol
让我们看看 MetaProtocol 如何工作。在引入 MetaProtocol 之前,如果我们想代理特定协议的流量,我们需要编写一个理解该协议的 Envoy 过滤器,并添加代码来操作流量,包括路由、标头修改、故障注入、流量镜像等。
对于大多数请求/响应样式的协议,流量操作的代码非常相似。因此,为了避免在不同的 Envoy 过滤器中重复这些功能,Aeraki 框架在一个地方实现了 7 层协议代理的大多数常用功能——MetaProtocol 代理过滤器。
这种方法大大降低了编写新 Envoy 过滤器的门槛:现在您只需要实现编解码器接口,而不是编写一个功能齐全的过滤器。除此之外,控制平面已经就绪——Aeraki 在控制平面上工作,为所有构建在 MetaProtocol 之上的协议提供 MetaProtocol 配置和动态路由。
MetaProtocol 代理中有两个重要的数据结构:元数据和变异。元数据用于路由,变异用于标头操作。
在请求路径上,解码器(编解码器实现的解码方法)使用从请求中解析的键值对填充元数据数据结构,然后元数据将传递给 MetaProtocol 路由器。路由器在匹配从 Aeraki 通过 RDS 收到的路由配置和元数据后,选择合适的上游集群。
如果需要修改请求,自定义过滤器可以填充变异数据结构,其中包含任意键值对:添加标头或更改标头的值。然后,变异数据结构将传递给编码器(编解码器实现的编码方法)。编码器负责将键值对写入线协议。
响应路径与请求路径类似,只是方向相反。
一个例子
如果您需要基于 MetaProtocol 实现应用程序协议,您可以按照以下步骤操作(以 Thrift 为例)
数据平面
实现编解码器接口以编码和解码协议包。您可以参考Dubbo 编解码器和Thrift 编解码器来编写自己的实现。
使用 Aeraki
ApplicationProtocol
CRD 定义协议,如以下 YAML 代码片段所示
apiVersion: metaprotocol.aeraki.io/v1alpha1
kind: ApplicationProtocol
metadata:
name: thrift
namespace: istio-system
spec:
protocol: thrift
codec: aeraki.meta_protocol.codec.thrift
控制平面
您不需要实现控制平面。Aeraki 监视服务和流量规则,生成 sidecar 代理的配置,并通过 EnvoyFilter
和 MetaProtocol RDS 将配置发送到数据平面。
协议选择
与 Istio 类似,协议通过服务端口前缀标识。请使用此模式命名服务端口:tcp-metaprotocol-{application protocol}-xxx。例如,Thrift 服务端口应命名为 tcp-metaprotocol-thrift。
流量管理
您可以通过 MetaRouter
CRD 更改路由。例如:将 20% 的请求发送到 v1,80% 发送到 v2
apiVersion: metaprotocol.aeraki.io/v1alpha1
kind: MetaRouter
metadata:
name: test-metaprotocol-route
spec:
hosts:
- thrift-sample-server.thrift.svc.cluster.local
routes:
- name: traffic-spilt
route:
- destination:
host: thrift-sample-server.thrift.svc.cluster.local
subset: v1
weight: 20
- destination:
host: thrift-sample-server.thrift.svc.cluster.local
subset: v2
weight: 80
如果您需要在服务网格中管理除 HTTP 之外的协议,希望这可以帮到您。如有任何疑问,请联系zhaohuabing。