1 什么是Service Mesh?
Buoyant 的创始人 Wiliam Morgan,于 2016年9月在SFMicroservices 的Meetup上第一次提到 Service Mesh,并且在其公司的博客上给出了 Service Mesh
的定义:Service Mesh 是用于处理服务与服务之间通信的专用基础设施层;在具有复杂拓补结构的现代云原生服务问,它负责请求的可靠交付。在具体实践中,Service Mesh 通常实现为一系列的轻量级网络代理,这些代理与应用程序代码一起部署,对应用程序是透明的。
原文如下:
A service mesh is a dedicated infrastructure layer for handling service-to-service communication. It's responsible for the reliable delivery of requests through the complex topology of services that comprise a modern, cloud native application. In practice, the service mesh is typically implemented as an array of lightweight network proxies that are deployed alongside application code, without the application needing to be aware.
2. 产生背景
2.1 多语言
微服务提倡不同业务使用最适合它的语言进行开发,这就意味着每种语言都需要实现相同功能服务框架。然而,服务框架的 SDK 通常实现都比较“重”,需要实现服务注册与发现、服务路由、负载均衡、服务监权、服务降级、服务限流、网络传输等功能,所以这一块的成本很高。
2.2 产品交付
在服务组件的功能升级、bug 修复过程中,业务系统需要升级依赖的组件包,而且还可能存在各种版本冲突以及验证过程复杂,从而导致一个组件包想要全覆盖升级,需要耗费相当长的时间,交付效率极其低下。组件团队期望以更高的效率去解决此问题。
2.3 云原生
在云原生架构里,单个应用程序可能由数百个服务组成;每个服务可能有数千个实例;而且这些实例中的每一个都可能处于不断变化的状态,因为它们是由像 Kubernetes一样的编排器动态进行调度的,所以服务问通信异常复杂,但它需要一个稳定的高效的通信层来解决云原生微服务架构带来的问题。
3 架构
Service Mesh 在实现上由 Data Plane(数据平面)和 Control Plane(控制平面)构成:
-
Data Plane(数据平面)
如上图的Sidercar,其负责服务间的通信逻辑,包括通信过程中的服务发现、流量控制(动态路由、 负载均衡)、安全通信、监控等。
-
Control Plane(控制平面)
其是负责管理和下发服务发现、沆量控制等策略,当配置下发到 Data Plane 时,就会触发数据平面的相关逻辑,达到控制的目的。
在部署上,Data Plane 作为单独的进程启动,可以每台宿主机共用同一个进程,也可以每个应用独占一个进程。Data Plane对于应用程序来说,它就像边车加装在摩托车上一样,因此又称为Sidecar。
在软件架构中,Sidecar 附加到主应用(或者叫父应用)上,用以扩展或增强功能特性,同时 Sidecar 与主应用是低耦合的。
4. 能做什么?
Service Mesh 的数据平面能够支撑很多服务治理逻辑,如服务发现、流量控制 (路由、负载均衡)、请求熔断、安全通信、Metric 和链路追踪和重试功能。
4.1 服务发现
以微服务模式运行的应用变更非常频繁,应用实例的频繁增加减少带来的问题是如何精确地发现新增实例,以及避免将请求发送给己不存在的实例上。Service Mesh 可以提供简单、统一、平台无关的多种服务发现机制,如基于 DNS、K/V 键值对存储的服务发现机制。
4.2 动态路由
随着服务提供商以提供高稳定性、高可用性及高 SLA 服务为主要目标,为了实现所述目标,出现了各种应用部署策略,尽可能从技术手段上达到无服务中断部署,以此避免变更导致服务的中断和稳定性降低。通过Service Mesh 提供的动态路由机制和特定的部署策略(如Blue/Green 部署)结合起来,就可以更加容易地实现将应用流量从一个版本切到另外一个版本,或者从一个数据中心到另外一个数据中心进行动态切换,甚至可以通过一个中心控制层控制多少比例的流量被切换。
4.3 负载均衡
运行环境中微服务实例通常处于动态变化状态,可能经常出现个别实例不能正常提供服务、处理能力滅弱、卡顿等现象。由于所有请求对 Service Mesh 来说是可见的,因此可以通过提供高级负载均衡算法来实现更加智能、高效的流量分发,降低延时,提高可靠性。
4.4 请求熔断
动态的环境中服务实例中断或不健康导致服务中断的情况可能会经常发生,这就要求应用或其他工具有快速监测并从负载均衡池中移除不提供服务实例的能力,这种能力也称为熔断,以此使得应用无须消耗更多不必要的资源而不断地尝试,而是快速失收或降级,甚至这样可避一些潜在的关联性错误。Service Mesh 可以很容易地实现基于请求和连接级别的熔断机制。
4.5 安全通信
通过将安全机制如TLS 加解密和授权实现在 Service Mesh上,不仅可以避免在不同应用中的重复实现,而且很容易在整个基础设施层更新安全机制,甚至无须对应用做任何操作。
4.6 Metric 和链路追踪
Service Mesh 对整个基础设施层的可见性使得它不仅可以暴露单个服务的运行数据,而且可以暴露整个集群的运行数据,因此可以很轻易地从 Service Mesh 中获取服务的Metric 统计信息和服务调用的链路信息。
4.7 重试
在Service Mesh 中加上重试功能,不仅可以避免将其嵌入业务代码,而且该重试逻辑还可以配置最后期限,使得应用允许一个请求的最长生命周期,防止无限期重试。
5 现状
5.1 开源产品
目前 Service Mesh 的实现非常多,其实在 Sevice Mesh 概念被提出以前,国内有些公司己实现了基于 Proxy 的类似 Service Mesh 的结构,如唯品会的 OSP Local Proxy,以及新浪的Weibo Mesh,这两款产品都是在服务治理框架上增加代理层来降级升级和多语言成本。在Service Mesh 出来之后,又有一些大型互联网企业紧密跟进,如华为的 CSE Mesher、美团的OCTO Mesh、蚂蚁的SOFA Mesh、阿里的 Dubbo Mesh,以及 Google、IBM、Lyft 联合开发的Istio。
目前开源的产品罗列如下:
- Linkerd
- Envoy
- Istio
- Weibo Mesh
- SOFA Mesh
- Dubbo Mesh
5.2 存在的问题
5.2.1 性能
Service Mesh 方式的服务调用相比服务框架的直接调用增加了与 Service Mesh 中数据平面Sidecar 的交互,虽然是本地网络通信,但性能上的损耗还是非常明显的,这也给 Service Mesh大规模落地带来了困难。
5.2.2 可用性
Service Mesh 通过单独的进程的方式来为应用程序提供服务,虽然它相对于应用程序来说比较透明,但其实也在整个服务调用链上增加了故障点,势必导致可 用性问题。在落地的过程中,这是一个不小的挑战,因此需要对 Service Mesh 的整体设计提出更高的要求来保证服务的可用性。
5.2.3 运维治理
(1)规模化部署的问题:特别是大型互联网公司,线上运行实例非常多,这些实例上都需要部署 Sidecar;
(2)如何监控治理的问题: Sidecat 进程“挂了”怎么办?需要具备自动化运维和监控的能力;
(3)本地开发调试的问题:开发人员在本地环境开发调试的时候,也需要依赖 Sidecar,难道每个开发机器上都要安装相关的 Sidecar, 并且在测试前先启动 Sidecar 进程吗?
6. Istio
Istio 是当前开源项目中最完善也是最火热的 Service Mesh 产品,Istio 的数据平面默认使用的是 Envoy,当然还有很多数据平面也对接了 Istio 的接口,如 Linkerd、SOFA MOSN 及华为的CSE Mesher。 Istio 的控制平面使用 Go 语言编写,分为 Pilot、 Mixer、Citadel 三个部分。
- Eavoy:Proxy是Istio在 Envoy 上进行扩展的网格代理,Envoy 是以Ct+开发的高性能代理,用于调解服务网格中所有服务的入站和出站流量。
- Mixer Mixer 是一个独立于平台的组件,在服务网格中实施访问控制和使用策略,并从 Envoy 代理和其他服务收集遥测数据;Mixer 包括灵活的插件模型。
- Pilot Pilot 负责为Proxy 提供服务发现、流量控制等智能路由的相关配置功能,会将控制流量行为的高级路由规则转换为特定于 Eavoy 的配置,并在运行时将它们传播到 Sidecarso Citadel Citadel 通过内置身份和凭证管理提供强大的端到端和最终用户身份验证。可以使用 Citadel 升级服务网格中的未加密流量。从Istio 0.5 开始,就可以使用授权功能来控制服务之间的访问。
6.1 数据平面
istio 的数据平面是 istio-proxy,它是基于 Envoy 的Filter 扩展机制,在 Eavoy 的基础上主要增加了 Mixer 相关的 Fiter, 而其他核心功能还是 Eavoy 自身提供的,Envoy 支持 TCP、HTTP、HTTP2、Thriff、Redis、Mongo 等协议流量的代理转发,而且 Envoy 有完善的集群、连接池管理和灵活的路由、负载均衡功能。另外,Envoy 在设计上也非常出色,比如它的配置、性能、热重启。
6.1.1 配置
Envoy 运行时的功能完全取决于它的配置,配置方式不仅支持静态的、还支持动态的,静态的配置可以是一份静态的 YAML, 或 JSON 文件,动态的配置支持文件或管理服务器来动态发现资源。不管是静态的配置还是动态的配置,概括地讲,对应的发现资源的 API 使用的协议被称作xDS。一般 Envoy通过订阅(subscription)方式来获取资源,如监控指定路径下的文件、启动gRPC 流或轮询 REST-JSON URL。
6.1.2 性能
Service Mesh 的 Sidecar 方式的调用相对以前的 SDK 方式增加了两跳,性能损耗也是非常明显的。
从 Envoy 自身实现来说,它采用了类似 Nginx 的 per thread one eventloop 模型,底层使用 ibevent 进行网络交互,可以配置多个worker 线程,使用非阻塞、异步IO,可以做到多个线程无锁转发请求和结果。另外,Envoy 使用 C++语言开发,因此性能自然不错。
从 Eavoy外部来说,常规做法是通过 iptables 的拦截规则,对应用请求进行拦截并转发到 Envoy,再由Envoy路由转发。因此 iptables 转发的性能也是影响服务调用端到端性能的一个因素,而影响iptables 转发性能主要有两个原因:
- 在规则配置较多时,由于其本身顺序执行的特性,性能会严重下滑;
- 每个request 的处理都要经过内核态到用户态再到内核态的过程,会带来频繁的数据复制和硬件中断、上下文切换等开销。
iptables 确实存在性能问题,因此目前Linux社区与 Envoy社区也正在计划对此做优化。
6.1.3 热部署
Envoy 支持热重启,即重启时可以做到无缝街接,据此Sidcar 能做到在线无感升级,其基本实现原理是:
- 将统计信息与锁放到共享内存中;
- 新老进程采用基本的 RPC 协议,使用 UNIX Domain Socket 通信:
- 新进程启动并完成所有初始化工作后,向老进程请求监听套接字的副本;
- 新进程接管套接字后,通知老进程关闭套接字;
- 通知老进程终止自己。
6.3 控制平面
6.3.1 Pilot
pilot 是Istio 流量管理的核心组件,它管理和配置部署在特定 Isio 服务网格中的所有 Envoy代理实例。
它允许我们指定在Envoy代理之间使用什么样的路由流量规则,并配置故障恢复功能。
每个 Envoy 实例都会从 Pilot 获取负载均衡信息,以及相关服务节点的定期健康检查配置信息;而且允许其在遵守配置的路由规则前提下,在目标实例之间智能
分配流量。
Eavoy 与pilot 之问数据通信格式使用的是 Envoy 的xDS。 Pilot 会从基础设施(如Kubernetes)获取 Service 的 Endpoint 相关信息,直接转换成 xDS 的配置,通过 gRPC 推送到Envoy, Envoy 感知相关的 xDS 配置,就会执行相应的策略。
此外Pilot 还有一个 Agent 模块,它也是Pilot 的一大功能点,主要负责启动 Eavoy,并且在启动前加载一些静态配置,还能对 Envoy 有保活功能,一旦 Envoy 异常退出,Pilot-agent 能够及时拉起 Envoy,Pilot-agent 还能够保证 Eavoy 的热重启。
6.3.2 Mixer
Mixer 是负责提供策略控制和遥测收集的 Istio 组件。
在每次请求执行先决条件检查之前,以及在每次报告遥测请求之后,Envoy Sidecar 在逻辑上调用 Mixer。
Mixer 是高度模块化和可扩展的组件。它的一个关键功能就是把不同后端的策略和遥测收集系统的细节抽象出来,使得 Istio 的其余部分不需要了解这些后端逻辑。
Mixer 通过使用通用插件模型来灵活实现对不同基础设施后端的处理。每个插件都被称为 Adapter, Mixer 通过它们与不同的基础设施后端连接,这些后端可提供核心功能,例如日志、监控、配额、ACI 检查等。通过配置能够决定在运行时使用的确切的适配器套件,并且可以轻松扩展到新的或定制的基础设施后端。
为了提升性能,Sidecar 自身也具有本地缓存,可以在缓存中执行相对较大比例的前提条件检查。此外,Sidecar 缓冲相关的遥测数据,使其实际上不需要经常调用 Mixer。但即使这样,Mixer 还是影响了 Istio 的整体性能,也是被经常诟病的模块。
6.3.3 Citadel
Citadel 用于密钥和证书管理。提供服务及用户之间的认证,确保可以在不需要修改服务代码的前提下增强服务之间的安全性。
- Citadel 创建一个gRPC 服务来接收 CSR 请求。
- Envoy通过密钥发现服务(SDS)API 发送证书和密钥请求。
- 收到 SDS 请求后,节点代理会创建私钥和 CSR,并将 CSR 及其凭据发送给 Citadel 进行签名。
- Citadel 验证 CSR 中携带的凭证,并签署 CSR 以生成证书。
- 节点代理通过 Envoy SDs APT 將以 Ctadel 中按收的证书和私钥发送给 Envoy。上述CSR 过程中会定期重复进行证书和密钥轮换。
文献:《高可用可伸缩微服务架构(基于Dubbo、Spring Cloud和Service Mesh)》 程超、梁桂钊、秦金卫、方志斌、张逸 等著