共计 9278 个字符,预计需要花费 24 分钟才能阅读完成。
赵化冰,腾讯云高级工程师,Istio Member,ServiceMesher 治理委员,Istio 我的项目贡献者,Aerika 我的项目创建者,热衷于开源、网络和云计算。目前次要从事服务网格的开源和研发工作。
唐阳,知乎基础架构工程师。Istio 我的项目贡献者,Argo 我的项目贡献者,专一于开源,云原生与微服务。目前负责知乎服务网格的研发工作。
备注:本文依据腾讯云赵化冰和知乎唐阳在 IstioCon 2021 中的演讲“How to Manage Any Layer-7 Traffic in an Istio Service Mesh?”整顿而成。
大家好,明天咱们想和大家分享的主题是如何扩大 Istio 以反对任何七层协定?作为云原生畛域中一个人气十分高的开源我的项目,Istio 目前曾经根本成为了 Service Mesh 的事实标准。腾讯云上也提供了基于 Istio 进行加强,和 Istio API 齐全兼容的 Service Mesh 治理服务 TCM(Tencent Cloud Mesh),以帮忙咱们的用户以较小的迁徙老本和保护代价疾速利用到 Service Mesh 提供的流量治理和服务治理能力。明天非常高兴可能有这个机会来和大家一起分享一下咱们在此过程中的一些教训。
Service Mesh 提供了一个对利用通明的基础设施层,能够解决咱们在分布式应用 / 微服务中遇到的常见挑战,例如:如何找到服务提供者?如何保障服务之间的通信安全?如何得悉服务之间的调用关系?如何进行流量治理如灰度公布?等等。Service Mesh 的实现形式是随同利用部署一个 Sidecar Proxy,该 Sidecar Proxy 会拦挡利用的出向和入向流量,对这些流量进行剖析和解决,以达到在不批改利用代码的状况下对服务进行流量治理、平安加密,遥测数据收集的目标。为了实现这些服务治理能力,Sidecar Proxy 不只须要在 OSI 网络模型的三、四层上对流量进行解决,更重要的是须要在七层上进行解决。在七层上,Istio 缺省只反对了 HTTP 和 gPRC 两种协定。但咱们在微服务中常常还会应用到的其余七层协定,当将这些微服务利用迁徙到 Service Mesh 时,咱们心愿应用统一的形式对所有的这些七层协定进行对立治理,以充分利用 Service Mesh 基础设施提供的云原生能力。
在明天的分享中,我将会介绍几种将 Istio 流量治理能力扩大到其余七层协定的办法,并比照剖析这几种办法各自的优缺点。我会介绍如何利用 Aeraki 开源我的项目来在 Istio 中治理任何七层协定,包含 Dubbo、Thrift、Redis 等。为了让大家理解 Aeraki 是如何工作的,会展现一个采纳 Aeraki 实现 Thrift 服务 Traffic Splitting 的例子。来自知乎的唐阳还会为咱们展现如何应用 Aeraki 的一些乏味的实在案例。
Service Mesh 中常见的七层协定
如下图所示,一个典型的微服务利用中通常会应用到这些七层协定:
- 同步调用:不同服务之间会采纳 RPC(近程办法调用)进行互相调用。常见的 RPC 调用协定包含 gRPC,Thrift,Dubbo,HTTP 也能够看做一种 RPC(只反对 GET/SET/POST 这几种规范办法)。一些大的公司为了满足本人特定业务场景的需要,往往还会采纳一些私用的 RPC 协定。
- 异步音讯:除了 RPC 之外,异步音讯也是微服务通信的一种常见模式,包含 Kafka,RabbitMQ,ActiveMQ 等。
- 各种数据库和缓存零碎:例如 Redis,MySQL,MongoDB 等等。
那么当将这样一个微服务利用退出到 Service Mesh 当前,咱们心愿可能通过 Service Mesh 失去哪些治理能力呢?
现实状况下,咱们心愿 Service Mesh 可能治理微服务中用到的所有七层协定的流量,包含 RPC、Messaging、Cache、DB 等。例如:
- 基于申请的负载平衡:能够将来自同一个 TCP 链接的多个独立的申请散发到不同的后端服务器,以实现更智能,更正当的负载平衡。
- 基于七层 Header 的流量路由:依据七层 Header 中的属性进行路由,例如依据 Dubbo 申请中的服务名或者 Redis 申请的 Key 进行路由。
- 对客户端的申请响应注入提早或者谬误,以测试应微服务用的弹性。
- 提供利用级平安,例如基于 HTTP Header 中的 JWT Token 进行认证,或者对 Redis 服务器进行认证。
- 申请层面的遥测数据,包含申请成功率、申请耗时、调用跟踪等等。
要实现以上这些流量治理和服务治理能力,Service Mesh 须要剖析和解决 TCP 数据包中的七层协定的 Header。即 Service Mesh 必须具备七层协定的治理能力,而不只是在 TCP 层面上进行解决。
然而在 Istio 中,对于除了 HTTP 和 gRPC 之外的协定,咱们只能在 OSI 三到六层对这些协定进行解决。这意味着咱们只能基于三层的 IP 地址,四层的 TCP 端口或者六层的 SNI(Server Name Indication)对这些协定进行路由。只能收集到 TCP 层面的指标,例如 TCP 收发包数量或者关上 / 敞开的 TCP 链接数量。只能采纳 mTLS 进行链路层面的认证和权限管制。换而言之,对于这些协定,咱们仍然须要在利用代码中解决流量管制、可观测性、平安认证这些本应该由 Service Mesh 基础设施来对立解决的共性问题。这违反了咱们将微服务迁徙到 Service Mesh 的初衷:将微服务通信和治理的共性问题从利用代码下沉到 Service Mesh 基础设施层。
如何扩大 Istio 的协定治理能力?
如果咱们心愿可能在 Istio 中治理这些七层协定,咱们应该如何实现呢?假如咱们有一个 BookInfo 微服务,但该微服务采纳了一种称为 AwesomeRPC 的协定而不是 HTTP 来实现服务间的近程调用。
咱们来看一下如何才可能在 Istio 中实现 AwesomeRPC 协定的流量治理,例如依据申请 header 中的 user name 字段将来自 ProductPage 的申请路由到不同版本的 Reviews 中,以实现一个灰度公布的场景。
咱们想到的最不言而喻的形式就是间接批改 Istio 代码。首先咱们须要在 Istio 的 VirtualService CRD 中反对 AwesomeRPC 协定。加强后的 VirtualService CRD 如下图中最左的规定配置所示。AwesomeRPC 和 HTTP 路由的语义相似,都是依据 Header 中某些属性的值进行路由。因而咱们只须要将 HTTP 协定类型改为 AwesomeRPC,能够间接采纳 VirtualService 中的 HTTPRoute 构造来示意 AwesomeRPC 的路由规定。而后咱们须要在 Pilot 代码中依据 AwesomeRPC 的服务定义和 VirtualService 定义的路由规定生成 Envoy 所需的实在配置,并通过 xDS 下发给数据面的 Envoy。当然,以上的前提是咱们曾经通过 Envoy 的 Filter 扩大机制编写了 AwesomeRPC 的 Filter 插件,实现 AwesomeRPC 的编解码,Header 解析,动静路由等数据面所需的性能。
采纳这种形式,在 Envoy Filter 曾经实现了的状况下,在管制面减少一个新的七层协定的过程是绝对比较简单的。然而因为咱们批改了 Istio 的源码,因而须要本人保护一个 Istio 的公有分支,这导致了额定的保护代价,并且很难跟上 Istio 疾速的迭代步调。
如果不心愿保护本人的 Istio 代码分支,一种可行的代替形式是采纳 Istio EnvoyFilter CRD:EnvoyFilter 是 Istio 提供的一种灵便弱小的配置机制。咱们能够应用 EnvoyFilter 为 Pilot 生成的缺省 Envoy 配置打一个补丁,增加、批改或者删除缺省 Envoy 配置中的局部内容,以按咱们的要求批改 Envoy 在 Istio Service Mesh 中的缺省行为。
如下图所示,因为 Pilot 并不了解 AwesomeRPC 协定,对于 Pilot 来说,AwesomeRPC 服务只是一个 TCP 服务。在 Pilot 生成的缺省配置中,AwesomeRPC 服务对应的 Outbound Listener 的 FilterChain 中采纳了一个 TCP Proxy 来解决其流量。咱们在 EnvoyFilter 的 Match 局部中选中该 TCP Proxy,并在 Operation 局部将其替换为一个配置了 Traffic Splitting 规定的 AwesomeRPC Filter。Pilot 会依据 EnvoyFilter 批改其生成的缺省 Envoy 配置,而后下发到数据面的 Envoy 上。这样咱们就通过 EnvoyFilter 在 Istio 中实现了对 AwesomeRPC 协定的反对。
上面咱们来看一个采纳 Thrift 协定的实在案例。Thrift 是 Apache 基金会下一个轻量级、反对多语言的开源 RPC 框架。Envoy 中曾经反对 Thrift,但 Istio 中只对 Thrift 提供了无限的反对,并不能实现 Traffic Splitting 等高级流量治理性能。如果咱们心愿在 Istio 中提供下图中右下角所示 Thrif 服务的 Traffic Splitting 流量管制,咱们能够通过 EnvoyFilter 来实现。
(本示例相干源码能够从 https://github.com/aeraki-fra… 下载)
首先,咱们须要创立一个图中右边所示的 EnvoyFilter 来解决客户端的出向流量,该 EnvoyFilter 的 Match 条件选中了 $(thrift-sample-server-vip)_9090 这个 Outbound Listener 中 的 tcp_proxy,在 Patch 局部将其替换为一个 thrift_proxy。在该 thrift_proxy 中,咱们依照 Traffic Splitting 的要求为其配置了相应的路由:将 30% 的流量路由到 Server v1 版本,70% 的流量路由到 Server v2 版本。咱们也须要为 Thrift Server 端创立一个如图右上所示的 EnvoyFilter 来解决服务器端的入向流量。相比客户端的 EnvoyFilter 而言,服务器端的 EnvoyFilter 配置要简略一些,因而咱们不须要在服务器端配置任何路由规定,只须要将 tcp_proxy 替换为 thrift_proxy 即可。这个 thrift_proxy 尽管没有路由规定,但提供了大量七层的服务通信和治理能力,包含申请层面的负载平衡、产生申请层面的 Metrics 数据等。
从下面的介绍和示例能够看到,EnvoyFilter CRD 好比是 Istio 中的一把瑞士军刀,能够对 Pilot 生成的 Envoy 配置进行非常灵活的定制,以达到对七层协定进行治理的目标。然而 EnvoyFilter 也带来了一些难以解决的问题:
- EnvoyFilter 将 Envoy 的底层实现细节间接裸露给了运维人员:运维人员必须十分理解 Envoy 的配置细节,而这些配置细节往往和 Envoy Filter 外部的实现机制严密相干,例如 Filter 的名称和 Filter 外部的配置格局等。这导致创立 EnvoyFilter 成为了一种和代码细节高度耦合的工作,难以间接交付给运维人员。更为正当的形式则应该是采纳一种面向用户的高级配置语言来屏蔽这些实现细节,例如 Istio 中的 VirtualService 和 DestinationRule。
- EnvoyFilter 中的匹配条件依赖于 Pilot 生成的 Envoy 配置中的构造组成和元素命名,例如 Listener 的名称,FilterChain 的形成等。而这些构造和命名在不同的 Istio 版本之间可能发生变化,导致本来可能失常工作的 EnvoyFilter 在新版本中呈现问题。
- EnvoyFilter 中的匹配条件还依赖于一些和特定 K8s 集群相干的内容,例如 Service Cluster IP,这意味着一个 EnvoyFilter 不能用于多个不同集群中的雷同服务。当 Service 被重建时,因为 Cluster IP 会发生变化,相应的 EnvoyFilter 也必须进行改变,批改 Match 条件中的 Cluster IP。
- 咱们须要为每个 Service 创立相应的 EnvoyFilter,当 Mesh 中治理的服务较多时,手动创立成千盈百的 EnvoyFilter 的工作是十分繁琐而且及易出错的。
- 对 Istio 而言,EnvoyFilter 中的 Patch 局部基本上是一个黑盒,因而 Istio 只能对 EnvoyFilter 的正确性进行十分无限的验证。这导致 EnvoyFilter 的调试十分艰难,当 Envoy 未能依照你的构想工作时,你很难晓得到底是 EnvoyFilter 的什么中央呈现了问题。
因为上述的种种问题,咱们能够看到,尽管能够应用 EnvoyFilter 来在 Istio 中实现七层协定的治理,然而在一个生产零碎,特地是一个中大型的 Service Mesh 中治理和保护这些 EnvoyFilter 是十分艰难的。
Aeraki:在 Istio 中治理任何七层协定
因为难以手动对 EnvoyFilter 进行治理和保护,咱们创立了 Aeraki (发音:[Air-rah-ki])我的项目来自动化这个流程。Aeraki 是希腊语中“大风”的意思,咱们心愿 Aeraki 这股大风能帮忙 Istio 在云原生的旅程中航行得更远。
Aeraki 的根本工作原理如下图所示:Aeraki 从 Istio 中拉取服务数据,依据 ServiceEntry 和 Aeraki 流量规定生成 Envoy 配置,并采纳 EnvoyFilter 将生成的配置推送到 Istio 中。简而言之,你能够把 Aeraki 看做 Istio 中治理的七层协定的 Operator。
相比于间接批改 Istio 代码和采纳 EnvoyFilter 这两种扩大 Istio 流量治理能力的形式,采纳 Aeraki 为咱们带来了以下的益处:
- 不须要批改 Istio 代码,因而节俭了独自保护一个 Istio 的公有代码分支的额定工作量,能够疾速追随 Istio 的版本迭代进行降级。
- Aeraki 作为一个独立组件部署在 Mesh 的管制面,能够很不便地作为一个插件和 Istio 进行集成,对 Istio 的流量治理能力进行扩大。
- 协定相干的缺省配置由 Aeraki 主动生成,并且这些配置能够依据 Istio 版本和 K8s 集群相干信息主动进行调整。节约了大量 EnvoyFilter 的手动创立和保护工作。
- Aeraki 在 Envoy 配置之上进行了形象,提供了一层面向用户的配置 CRD 来对这些七层协定进行治理。这些高级 CRD 暗藏了 Envoy 的配置细节,屏蔽了不同 Istio 版本生成的缺省 Envoy 配置的差别,对于运维十分敌对。对于 Thrift 和 Dubbo 这样的 RPC 协定,因为其语义和 HTTP 相似,Aeraki 间接采纳了 Istio VirtualService 和 DestinationRule;对于非 RPC 协定,Aeraki 则定义了一些新的 CRD 来进行治理,例如 RedisService 和 RedisDestination。咱们前面将进一步介绍如何应用这些配置 CRD 来定制规定,例如实现 Traffic Splitting。
和 Istio 相似,Aeraki 也采纳了端口名称来辨认协定类型。端口取名须要遵循“tcp- 七层协定名 -xxx”的命名规定。例如,一个 Thrift 服务应取名为“tcp-thrift-service”。须要留神的是,咱们必须保留端口名中的“tcp-”前缀,因为对于 Istio 而言,这是一个 TCP 协定的服务。Aeraki 则会依据端口名中的七层协定来生成相应的 Envoy 配置,并替换 Istio 缺省生成的 tcp_proxy。
咱们来看看如何采纳 Aeraki 来实现下面 Thrift 服务的 Traffic Splitting 用例。首先咱们须要在 Thrift Service 定义的 Port 命名中申明该 Service 的七层协定类型:“tcp-thrift-hello-server”,而后创立一个 VirtualService 将 Thrift 申请依照指定比例路由到不同的服务版本中。Aeraki 将依据服务定义和 VirtualService 生成所需的 Envoy 配置,并通过 EnvoyFilter 发送给 Istio。
能够看到,绝对于手动创立 EnvoyFilter,采纳 Aeraki 来治理 Thrift 要简略得多。如果不须要非凡的流量规定,则会更简略,只须要依照命名标准在 Port 名称中申明 Thrift 协定即可,Aeraki 会生成所需的 Envoy 配置,无需任何额定的工作。
想本人试试 Aeraki 的 Thrift、Dubbo、Redis 服务治理能力?非常简单,只需在一个连贯到 K8s 集群的命令行终端上运行上面两行代码,就能够装置一个带有 Aeraki 插件的 Istio 集群以及相应的 Demo 程序,欢送大家尝试!
`git clone https:``//github``.com``/aeraki-framework/aeraki``.git``aeraki``/demo/install-demo``.sh`
也能够拜访 Aeraki 的在线 Demo,查看从 Thrift、Dubbo、Redis 等服务收集到的监控指标面板:http://aeraki.zhaohuabing.com:3000/d/pgz7wp-Gz/aeraki-demo?orgId=1&refresh=10s&kiosk
应用 Aeraki 加强 Service Mesh
上面咱们来看一下应用 Aeraki 的七层协定治理能力来加强 Service Mesh 的一些案例。
屏蔽开发 / 生产环境的差别
咱们在开发、测试和生产环境中通常须要拜访不同的后端资源,例如须要连贯到不同的 Redis 缓存或者不同的 mySQL 数据库。一般来说,咱们须要批改随应用程序公布的配置文件中的后端资源地址,以达到在不同环境中切换后端资源的目标。通过 Aeraki 的帮忙,咱们能够用 Service Mesh 来屏蔽不同后端资源的配置差别,使得应用程序能够用雷同的形式拜访不同环境中的后端资源。
如下图所示,咱们在 Dev、Staging 和 Prod 三个环境中都须要拜访 Redis 服务,这三个 Redis 服务有不同的 IP 地址和拜访明码,部署形式也可能不同:在开发环境中,为了节约资源和简化部署,咱们可能应用单个 Redis 实例;在测试和生产环境中,咱们会应用 Redis 集群来保障 Redis 服务的高可用和扩展性,咱们也可能间接应用云服务商提供的 Redis 托管服务。当在这三个环境中进行切换时,咱们须要配置不同的 IP 地址和拜访明码,如果 Redis 部署的形式不同,咱们甚至可能须要批改客户端代码来切换 Redis 单实例模式和集群模式,这极大影响了咱们开发、测试和上线的效率。
通过 Aeraki 提供的 RedisService 和 RedisDestination CRD,咱们能够屏蔽这些不同 Redis 服务提供者之间的差别,容许客户端以对立的形式拜访后端的 Redis 服务。
在采纳 Aeraki 之前,咱们在不同的环境中须要配置不同的 IP 地址和 Redis 拜访明码。采纳 Aeraki 之后,在客户端能够采纳雷同的代码和配置,通过批改 Aeraki CRD 来切换不同环境中的 Redis 配置,大大减少在不同环境之间进行切换的老本。即便 Redis 从单实例改为了 Redis 集群,客户端也能够采纳雷同的形式进行拜访。
采纳流量镜像进行比照测试
有一些数据库或者数据库代理采纳雷同的网络协议。例如 TiDB、Oceanbase、Aurora、Kingshard 等都兼容 MySQL 协定;Twemproxy、Codis、Tendis、Pika 等都采纳了 Redis 协定。因为业务需要,咱们有时须要从一个实现迁徙到另一个实现上。在迁徙之前,咱们须要进行比照测试,以比照不同实现的性能、性能及兼容性。
例如上面的场景:咱们最后只用了一个单实例 Redis 来做缓存,随着线上业务的一直扩大,该 Redis 实例曾经呈现了拜访瓶颈,咱们心愿切换为采纳 Twemproxy 来对 Redis 进行程度扩大。通过采纳 Aeraki 来将线上的 Redis 流量镜像到 Twemproxy 测试环境,咱们能够采纳实在的业务数据对 Twemproxy 进行充沛的测试,以评估其对线上业务的影响。
采纳全流量故障注入测试零碎弹性
Istio 能够实现 HTTP 和 gRPC 的故障注入,但这还不够。在一个分布式系统中,应用服务、数据库、缓存、音讯零碎等都可能因为网络或者其余起因呈现不可用的状况。采纳 Aeraki,咱们能够对系统中的所有这些可能的故障点进行残缺的模仿,以测试零碎的弹性,保障咱们的零碎在一部分呈现问题后能够自愈或者通过降级保证系统根本可用,而不至于整个零碎解体。
小结
Service Mesh 中有大量的七层协定流量,包含 RPC、Database、Cache、Messaging 等类型的七层协定,但 Istio 只提供了 HTTP 和 gRPC 的七层治理能力,对其余七层协定的反对十分无限。Aerkai 开源我的项目通过非侵入的形式为 Istio 提供了任意七层协定的反对能力,并提供了面向用户的高级配置 CRD,能够很不便地对这些协定的流量进行治理,实现灰度公布等高级流量治理能力。目前 Aeraki 曾经反对了 Thrift、Dubbo、Redis、Kafka、Zookeeper,并行将反对更多的协定。Aeraki 的定位是做成一个非侵入式 Istio 性能加强工具集,除了协定扩大之外,还会关注解决在 Istio 应用过程中遇到的其余常见问题,包含效率优化、配置简化、第三方服务发现接入、性能扩大等。如果您心愿理解更多对于 Aeraki 的内容,欢送拜访 Github 主页 https://github.com/aeraki-fra…。
** 招聘信息
腾讯云 Service Mesh 团队正在炽热招聘中,Base 成都、北京、深圳或者西安,要求候选者相熟 Kubernetes/Istio/Envoy。欢送大家发送简历到 huabingzhao@tencent.com 或者微信分割 zhao_huabing。
参考链接:
- IstioCon talk“How to Manage Any Layer-7 Traffic in an Istio Service Mesh?”视频回放 https://www.bilibili.com/vide…
- IstioCon talk“How to Manage Any Layer-7 Traffic in an Istio Service Mesh? 讲稿下载 https://zhaohuabing.com/slide…
- Aeraki Github 主页 https://github.com/aeraki-fra…
- Aeraki 在线 Demo http://aeraki.zhaohuabing.com:3000/d/pgz7wp-Gz/aeraki-demo?orgId=1&refresh=10s&kiosk
【腾讯云原生】云说新品、云研新术、云游新活、云赏资讯,扫码关注同名公众号,及时获取更多干货!!