一、Service Mesh 是什么 ?
“A service mesh is a dedicated infrastructure layer for handling service-to-service communication. “ —— William Morgan。ervice Mesh 是一个专注于处理服务间通信的基础设施层。云原生应用有着复杂的服务拓扑,而 Service Mesh 保证请求可以在这些拓扑中可靠地穿梭。在实际应用当中,Service Mesh 通常是由一系列轻量级的网络代理组成的,它们与应用程序部署在一起,但应用程序不需要知道它们的存在。微服务对于每个功能的开发细化了,但是对与系统的管理复杂度增强了,尤其是网络流量的管理。试想一下:黑名单,导流,加密,访问控制,流量监控,熔断,限速,收费功能,数据流阶段延迟 这种在网络层上的功能难道要在每个应用代码中实现么?
Service Mesh 的概念最早由前 twitter 的基础设施工程师 William Morgan 于 2017 年 4 月 25 日提出。虽然在此之前,微服务领域也有类似的概念被提出或用于开发项目,但在业界始终没有一个统一的名称。 William Morgan 在自己的博文 "What’s a service mesh? And why do I need one?" 中正式给 Service Mesh 做出了权威的定义。至此,"Service Mesh" 这个名词正式出现在各大公司以及技术社区的视野中。随着云计算的普及,越来越多的开发者和企业开始使用“微服务”的开发模式。这种开发模式拥有诸如耦合度低、跨语言开发、更小粒度扩容等许多优势,但同样也面临着许多挑战。微服务从出现至今总共经历了三个阶段:微服务初期、Sidecar 时期和 Service Mesh 时期。
微服务初期:在微服务初期( 2015年前 )开发微服务应用的过程中,我们需要重复性地处理一系列基础工作,比如:服务注册、服务发现、得到服务实例后的负载均衡、熔断机制等。这些工作在 Service Mesh 出现之前统统都要开发人员在项目中用代码解决并实现,导致应用程序中加入了大量的非功能性代码。即使使用类似 Netflix OSS 的库和 Spring Cloud 的框架,开发人员依然面临着需掌握内容多、技术门槛高等诸多困难。
Sidecar 的出现:"Sidecar" ( Sidecar ,中文意思为摩托车的跨斗,不由赞叹命名的非常生动 ) 这个词最早由 Netflix 提出并被用于 Eureka 项目。由于这个项目的广泛应用,故在此之后,凡是微服务中“用于端对端通信的、被单独分离出来的“组件,就都被称为 "Sidecar" 了。仔细分析上述一系列的重复性工作,我们可以发现,这些工作几乎全部集中在处理各个服务间的通信问题。那么,为何我们不把这些工作从业务逻辑中抽离出来,使其专注于服务间通信,并形成单独的组件呢?Sidecar 模式,即在微服务中将关于服务通讯的功能抽离出来,并作为一个单独的组件运行在微服务中。这种在微服务中独立负责端对端通信的组件,我们称之为 Sidecar 。这种在微服务中将业务逻辑与服务通信解藕,并分离为两个独立运行组件的做法,正是 Service Mesh 概念的雏形。但在这个阶段,每个微服务中的 Sidecar 还无法通用,即这个微服务的 Sidecar 没有办法拆出来给另一个微服务使用。
Service Mesh 的提出:Service Mesh 在 Sidecar 模式的基础上更进一步。Service Mesh 是专用的基础设施层,轻量级高性能网络代理。提供安全的、快速的、可靠地服务间通讯,与实际应用部署一起,但对应用透明。应用作为服务的发起方,只需要用最简单的方式将请求发送给本地的服务网格代理,然后网格代理会进行后续操作,如服务发现,负载均衡,最后将请求转发给目标服务。当有大量服务相互调用时,它们之间的服务调用关系就会形成网格。服务网格呈现出一个完整的支撑态势,将所有的服务”架”在网格之上。Service Mesh 的定义——一个专注于处理服务间通信的基础设施层——站在开发者的角度来讲,就是在每一个微服务中将用于通信的部分从业务中彻底解藕,应用程序甚至不需要知道它们的存在。在 Service Mesh 中,每个微服务至少含有两个组件:一个用于处理业务功能的“应用程序”和一个专职处理服务间通信的“ Sidecar ”( 类似代理 )。Service Mesh 的愿景是希望开发者再也不需要将精力花费在服务通信上。服务通信由每个微服务的 Sidecar 负责,而 Sidecar 由专门的项目来接管。目前,许多被熟知的项目都可以被我们当作 Sidecar 来运用,比如 Envoy 、 HAProxy 和 Nginx 。使用了 Service Mesh 之后,开发团队和运维团队就可以更加明确的划清自己的职责范围——开发团队专注于业务的开发,而运维团队只需关注微服务中的 Sidecar 就可以明确地了解到每个微服务的健康情况和各种指标。
Service Mesh 的设计理念和作用:随着云原生应用的崛起,Service Mesh 逐渐成为一个独立的基础设施层。在云原生模型里,一个应用可以由数百个服务组成,每个服务可能有数千个实例,而每个实例可能会持续地发生变化。服务间通信不仅异常复杂,而且也是运行时行为的基础。管理好服务间通信对于保证端到端的性能和可靠性来说是非常重要的。Service Mesh 实际上就是处于 TCP/IP 之上的一个抽象层,它假设底层的 L3/L4 网络能够点对点地传输字节(当然,它也假设网络环境是不可靠的,所以 Service Mesh 也必须具备处理网络故障的能力)。从某种程度上说,Service Mesh 有点类似 TCP/IP 。TCP 对网络端点间传输字节的机制进行了抽象,而Service Mesh则是对服务节点间请求的路由机制进行了抽象。Service Mesh 不关心消息体是什么,也不关心它们是如何编码的。
应用程序的目标是“将某些东西从A传送到B”,而 Service Mesh 所要做的就是实现这个目标,并处理传送过程中可能出现的任何故障。与TCP不同的是,Service Mesh有着更高的目标:为应用运行时提供统一的、应用层面的可见性和可控性。通过每个微服务中的 Sidecar ,Service Mesh 得以将服务间通信从底层的基础设施中分离出来,让它成为整个生态系统的一等公民——它不再是单纯的基础设施,更可以被监控、托管和控制。尽管 Service Mesh 在云原生系统方面的应用已经有了快速的增长,但仍然存在巨大的提升空间。服务发现和访问策略在云原生环境中仍显初级,而 Service Mesh 毫无疑问将成为这方面不可或缺的基础。就像 TCP/IP 作为互联网的基础一样,Service Mesh 将在微服务的底层基础设施这条路上更进一步。目前,由 Google , IBM 和 Lyft 公司共同研发的 Istio 非常火爆。Istio 是 Service Mesh 的一个实现,可以看作是一个“微服务管理框架”,一般配合 Kubernetes 使用。Istio 使用 Envoy 作为 Sidecar,并精细地实现了 Service Mesh 对于上述微服务之间传输的诸多设想,并且添加了许多很棒的额外功能。
二、Istio 的设计目标
为了实现由 William Morgan 提出的微服务 Service Mesh 模式和诸多理念,Google , IBM 和 Lyft 这三家公司协同研发,并于 2017 年 6 月 8 日( 根据 Github 最后一次提交的时间 )发布了 Istio 的第一个发行版——Istio 0.1 版本。Istio 是一个连接,管理和保护微服务的开放平台,Istio 提供一种简单的方式来建立已部署的服务的网络,具备负载均衡,服务到服务认证,监控等等功能,而不需要改动任何服务代码。简单的说,有了 Istio,你的服务就不再需要任何微服务开发框架(典型如 Spring Cloud,Dubbo),也不再需要自己手动实现各种复杂的服务治理功能(很多是 Spring Cloud 和 Dubbo 也不能提供的,需要自己动手)。只要服务的客户端和服务端可以进行简单的直接网络访问,就可以通过将网络层委托 Istio,从而获得一系列的完备功能。作为一款 Service Mesh 模式的实现,Istio 最根本的设计目标就是实现 Service Mesh 的设计构想:
- 将“应用程序”与“网络”解藕: 将服务之间、服务与集群外部的网络通讯和安全机制从微服务的业务逻辑中解藕,并作为一个与平台无关的、独立运行的程序,以减少开发和运维人员的工作量。
- 保障网络环节: 应用程序的目标是“将某些东西从A传送到B”,而 Service Mesh 所要做的就是实现这个目标,并处理传送过程中可能出现的任何故障。
- 提供应用层面的可见性和可控性: 通过每个微服务中的 Sidecar ,Service Mesh 得以将服务间通信从底层的基础设施中分离出来,让它成为整个生态系统的一个独立部分——它不再是单纯的基础设施,更可以被监控、托管和控制。
- 最大化透明度( 与“解藕”类似,但具体到基于 Pod 实现 ): Istio 使用 Sidecar 代理来捕获流量,并且在尽可能的地方自动编程网络层,以路由流量通过这些代理,而无需对已部署的应用程序代码进行任何改动。注入 sidecar 代理到 pod 中并且修改路由规则后,Istio 就能够调解所有流量。
- 增量扩容策略: 扩展策略系统,集成其他策略和控制来源,并将网格行为信号传播到其他系统进行分析。策略运行时支持标准扩展机制以便插入到其他服务中。
- 可移植性: Istio 必须能够以最少的代价运行在任何云或预置环境中。将基于 Istio 的服务移植到新环境应该是轻而易举的,而使用 Istio 将一个服务同时部署到多个环境中也是可行的(例如,在多个云上进行冗余部署)。
- 策略一致性: 在服务间的 API 调用中,策略的应用使得可以对网格间行为进行全面的控制,但对于无需在 API 级别表达的资源来说,对资源应用策略也同样重要。策略系统作为独特的服务来维护,具有自己的 API,而不是将其放到代理或 Sidecar 中,这容许服务根据需要直接与其集成。
三、Istio 的核心功能
Istio 的核心功能有以下五点:
- 流量管理: Istio 通过 Pilot 所提供的 API 动态地配置所有 Pod 中 Sidecar 的路由规则,进而控制服务间的流量和 API 调用。Istio 简化了断路器、超时和重试等服务级别属性的配置,并且可以轻松设置 A/B 测试、金丝雀部署和基于百分比的流量分割的分阶段部署等重要任务。
- 安全: Istio 提供给开发人员应用程序级别的安全性。Istio 提供底层安全通信信道,并大规模管理服务通信的认证、授权和加密。使用 Istio ,服务通信在默认情况下是安全的,它允许跨多种协议和运行时一致地实施策略——所有这些都很少或根本不需要应用程序更改。将 Istio 与 Kubernetes 的网络策略结合使用,其优势会更大,包括在网络和应用层保护 Pod 间或服务间通信的能力。
- 可观察性: Istio 的 Mixer 组件负责策略控制和遥测收集。通过 Istio 的监控功能,可以了解服务性能如何影响上游和下游的功能;其自定义仪表板可以提供对所有服务性能的可视化,从而了解性能如何影响其他进程。
- 平台独立: Istio 是独立于平台的,旨在运行在各种环境中,包括跨云、内部部署、Kubernetes、Mesos 等。您可以在 Kubernetes 上部署 Istio 或具有 Consul 的 Nomad 上部署。
- 集成和定制: 策略执行组件可以扩展和定制,以便与现有的 ACL、日志、监控、配额、审计等方案集成。
四、Istio 的实现原理
Istio 的架构在逻辑上分为控制面和数据面:
- “数据面“:由一组 Sidecar 构成。这些 Sidecar 可以调节和控制微服务及 Mixer 之间所有的网络通信。
- “控制面“:负责管理和配置代理路由流量。此外,控制面通过 Mixer 来实施策略和收集各个 Sidecar 的遥测数据。
Istio 架构图
Istio 架构中每个部分的作用如下:
- Sidecar ( 在 Istio 中,默认的 Sidecar 是 Envoy ):Envoy 是使用 C++ 开发的高性能代理,用于调解服务网格中所有服务的入站和出站流量。在 Istio 中,Envoy 被用于 Sidecar ,和对应的应用服务部署在同一个 Kubernetes 的 Pod 中。Envoy 调解所有出入应用服务的流量。所有经过 Envoy 的流量行为都会调用 Mixer,为Mixer 提供一组描述请求和请求周围环境的 Attribute 。根据 Envoy 的配置和 Attribute,Mixer 会调用各种后台的基础设施资源。而这些 Attribute 又可以在 Mixer 中用于决策使用何种策略,并发送给监控系统,以提供整个网格行为的信息。
- Pilot:Pilot 为 Sidecar 提供“服务发现”功能,并管理高级路由( 如 A/B 测试和金丝雀部署 )和故障处理( 超时、重试、熔断器等 )的流量。Pilot 将这些“高级”的流量行为转换为详尽的 Sidecar (即 Envoy) 配置项,并在运行时将它们配置到 Sidecar 中。Pilot 将服务发现机制提炼为供数据面使用的 API ,即任何 Sidecar 都可以使用的标准格式。这种松耦合的设计模式使 Istio 能在多种环境( Kubernetes、Consul 和 Nomad )下运行,同时保持用于流量管理操作的相同。
- Mixer:Mixer 是一个独立于平台的组件,通过从 Sidecar 和一些其他服务处收集数据,进而在整个 Service Mesh 上控制访问和执行策略。Sidecar 请求级别的 Attribute 被发送到 Mixer 进行评估。Mixer 中还包括一个灵活的插件,使其能接入各种主机环境和基础设施的后段,并得到 Sidecar 代理和 Istio 所管理的服务。Mixer 的设计还具有以下特点:
a) 状态:Mixer 本身是无状态的,它没有持久化存储的管理功能。
b) 高可用:Mixer 被设计成高度可用的组件,任何单独的 Mixer 实例实现 > 99.999% 的正常运行时间。
c) 缓存和缓冲:Mixer 能够积累大量短暂的瞬间状态。
- Citadel:Citadel 通过内置身份和凭证管理提供“服务间”和“最终用户”身份验证。Citadel 可用于升级服务网格中未加密的流量,并能够为运维人员提供基于服务标识( 如 Kubernetes 中 Pod 的标签或版本号 )而不是网络层的强制执行策略。
Istio 与 Envoy 的关系
Istio 与容器管理平台的关系 ( 以 K8s 为例 ),从设计上来说,Istio 是平台无关的,它可以在许多容器管理平台上部署。但是当 Istio 与 Kubernetes 共同使用时,它的能力将得到最大化应用。比如,Istio 可以通过 yaml ( Istio 有提供 yaml )的形式快速在 K8s 上部署;其服务注册机制由 K8s 提供,而服务发现由 Istio 中的 Pilot 负责。综上所述,在 Kubernetes 上使用 Istio 是非常合适的。
流量管理及请求路由
将流量从应用程序中解藕,使得 Istio 能提供各种流量管理的功能,例如:动态路由( 负载均衡,A/B 测试,金丝雀部署 )、故障处理( 超时,重试,熔断器,故障恢复 )以及故障注入( 测试服务之间的故障恢复策略的兼容性 )。这些都是通过 Pilot 与 Sidecar 共同协作完成的。
Pilot 的构成及其与 Sidecar 协同工作原理
由上图可以看出,一个 Pilot 主要由“平台适配器”、“抽象模型”、用于配置和调用 Envoy 的“Envoy API” 和 用于用户指定流量管理规则的“Rules API”所组成。Sidecar 的服务发现及传输规则机制,主要遵循以下流程:
- 平台适配器( Platform Adapter )从 Kubernetes API server 中获取 Pod 的注册信息。( 注意:Istio 本身并不具备服务注册的功能,它需要通过平台适配器和特定的平台结合才能具有完整的服务发现的功能。)
- 用户通过 Pilot 的 Rules API 对所有被发现的服务的 Sidecar 进行各种高级特性( 包括路由规则、HTTP层的流量管理等 )的配置
- 用户配置的这些规则被抽象模型翻译成低级配置
- Sidecar API(即 Envoy API) 将这些翻译好的低级配置通过 discovery API 分发到每个微服务上的 SIdecar(即 Envoy) 实例中
服务间通讯
运维人员可以用 Pilot 指定路由规则,而 Envoy 根据这些规则动态地确定其服务版本的实际选择。Envoy 拦截并转发客户端和服务器之间的所有请求和相应。路由规则让 Envoy 能够根据诸如 header、source/destination 或分配给每个版本的权重等标准来进行版本选择。
Service A 访问不同版本的 Service B 的工作流程如下:
- 运维人员通过 Polit 的 Rules API 根据 destination 的相关标签配置分流规则
- Service A 运行时,其 Envoy 的配置规则更新
- Service A 根据新配置的规则访问带有不同标签的 Service B 的版本
集群出入站规则
Istio 默认进入和离开网络的所有流量都会通过 Envoy 进行传输。通过 Envoy 将流量路由到外部 Web 服务( 例如访问 Maps API 或 视频服务 API )的方式,运维人员可以为这些服务添加超时控制、重试、熔断器等功能;还能从服务连接中获得各种细节指标。
流量从外网进入集群再流出的流程如下:
- 通过 Kubernetes 的准入控制,外部流量进入 Istio
- 流量与 Service A 和 Service B 的 Envoy 交互,并由 Envoy 获取服务具体相应的内容
- 流量通过 Egress gateway 或 直接流出的方式流出 Istio
服务发现和负载均衡
Istio 的服务注册功能是基于平台来实现的。Istio 默认存在用于跟踪 Pod 的服务注册表,而且还默认新的服务自动注册,不健康的服务被自动删除。目前,Kubernetes、Mesos 等平台已经为基于容器的应用程序提供了这样的功能。Pilot 使用服务注册的信息,并提供与平台无关的 discovery API。网格中的 Envoy 提供服务发现功能,并相应地动态更新负载均衡池。
运行流程如下:
- 每个微服务的 Pod 通过 Kubernetes 提供的服务注册机制进行注册
- 已注册的 Service A 的 Envoy 通过 Pilot 中汇总的 Envoy 信息发现欲访问的 Service B
- Service A 的 Envoy 根据设置好的负载均衡或流量管理规则,对 Service B 的 Envoy 发起请求
- Service B 的 Envoy 根据设置好的规则确认是否接收 Service A 发出的请求。
Attribute 与服务监控
Attribute 是 Istio 策略和遥测功能中的基本概念。Attribute 是一小段数据,用于描述服务请求的一系列属性( 例如特定请求的大小、操作相应代码、请求来自的 IP );通过 Attribute,我们就可以洞悉服务的方方面面。Mixer 是 Istio 中用于实现策略和遥测功能的组件,其本质上是一个 Attribute 处理机。每个经过 Sidecar 的请求都会调用 Mixer,为 Mixer 提供一组描述请求及其周围环境的 Attribute。基于 Envoy 的配置和相应 Attribute,Mixer 会调用各种基础设施后端。
遥测功能的信息汇总流程如下( 注意所有微服务都是通过 Envoy 进行通信的 ):
- Envoy 通过调用将 Attribute 传递给 Mixer
- Mixer 得到 Envoy 的 Attribute,并根据 Attribute 调用各种后端资源
- 同时,Mixer 可以汇总所有 Envoy 的 Attribute,用于集群范围的监控以及为运维人员提供可观测性
位于网格中每个服务实例旁边的 Sidecar 代理必须在内存消耗方面节约,这限制了本地缓存和缓冲的可能数量。然而,Mixer 独立运行,可以使用相当大的缓存和输出缓冲区。因此,Mixer 可用作 Sidecar 的高度扩展且高度可用的二级缓存。
五、Istio 与主流 Service Mesh 的比较
目前,市面上有许多 Service Mesh 的实现。我们这里挑选 4 种当前最主流的 Service Mesh,对其诸多方面( 包括功能特性、支持平台、是否付费等 )进行横向对比,用以说明 Istio 所存在的优势和不足。Istio, Linkerd, Linkerd2 和 Consul 四种 Service Mesh 的横向对。
根据上表所示,目前选择 Istio 作为 Service Mesh 的主要优劣势如下:
优势:
- 使用 Sidecar 模式开发,便于流量控制和监测及安全机制
- 与 K8s 完美兼容
- 使用高性能的 Go 语言开发
- 支持多种高级快速的网络协议
- Sidecar 默认 Envoy 并自动注入
- 容错机制完善
- 集成了用于监测的可视化界面
- Jaeger 作为跟踪机制集成
- 具备权限认证功能
- Sidecar 代理具有缓存功能
- 完全免费
- 文档和技术博客数量远多于其他 3 种 Service Mesh
劣势:
- 复杂度高,技术门槛和学习成本高
- 目前 Istio 不支持集群内外通信的安全连接