31

Service Mesh:每位开发者都需要了解的热门技术

 3 years ago
source link: http://dockone.io/article/10870
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

编者按:本文由 SolarMesh 团队进行编写,全文约6000字,阅读约需10分钟。 SolarMesh

目前已提供了下载体验版,如果您想了解和体验更多 Service Mesh 的功能,不妨来 官网 免费体验一下。

VvQfia.jpg!mobile

近几年,Service Mesh 这个概念如火如荼,尤其是经常和后端系统打交道的软件工程师,对这个词应该不陌生。随着技术的发展,网上关于 Service Mesh 的文章日益增多,但是在一些问题上剖析得还不够到位。本文将结合国外部分文章,提供一个深入可靠的、以工程师为中心的Service Mesh 指南,解决“什么是服务网格”“为什么要用服务网格”等问题,相信读完文章的你将有所收获。

什么是服务网格?

大约从 2017 年开始,Service Mesh 这个名词逐渐进入国内开发者的视野,人们开始关注其前沿发展。一般认为 Service Mesh 是由开发 Linkerd 的 Buoyant 公司提出的。Linkerd 的 CEO William Morgan 曾给 Service Mesh 这样一个定义:

The service mesh is typically implemented as a scalable set of network

proxies deployed alongside application code (a pattern sometimes

called a sidecar). These proxies handle the communication between the

microservices and also act as a point at which the service mesh

features can be introduced. The proxies comprise the service mesh’s

data plane, and are controlled as a whole by its control plane.[1]

Service

Mesh(服务网格)是一个专用基础设施层,用于处理服务间通信。它负责在有着复杂的服务拓扑的现代云原生应用中实现请求的可靠传递。在实践中,服务网格通常实现为一组轻量级网络代理,与应用程序部署在一起,而对应用程序透明。

在大部分讨论中,对服务网格的描述都显得很简单:『它是一组部署在业务服务旁的代理』。这些代理通常被称作服务网格的『数据面』,并将其管理进程定义为『控制面』。数据面负责拦截并处理服务之间的调用;控制面则负责协调代理的行为,并为操作人员提供一组 API 来操作服务网格。

这些代理通常被称作服务网格的『数据面』,并将其管理进程定义为『控制面』。数据面负责拦截并处理服务之间的调用;控制面则负责协调代理的行为,并为操作人员提供一组 API 来操作服务网格。

e2a2ayY.jpg!mobile

更具体地说,这些代理类似于 HAProxy 和 Nginx 的 7 层 TCP 代理,它们会负责发起和响应服务间的请求(实际上,它们同时扮演 “代理”和“反向代理” 的角色,处理流量的流入和流出),并对服务间调用提供了一个功能集合。服务网格代理与其他的API网关或入口代理的区别也在于此,它们主要关注服务间流量,而后者则更专注于从外部流量进入集群流量的调用。

相对于由代理构成的数据面,控制面的构成会更简单一些:它是一组用于协调数据面的组件的集合,如服务发现、TLS 证书颁发、指标汇总等。数据面会向控制面传递数据,而控制面则会提供一组 API ,允许用户对数据面的行为进行检查和修改。

关于服务网格架构,还有一点需要额外说明——由于服务网格的代理是为了处理服务间流量而设计的,所以只有当应用程序使用微服务架构时,服务网格才会真正派上用场。通常来说,部分服务网格会为每个节点(主机、虚拟机)添加一个代理,有些则会为服务的每一个实例都添加,这种对代理的大量使用意味着:

  1. 列表无论这些数据层代理是什么,它们必须快速响应。因为每次调用都会被额外增加两次转发,一次在请求侧,一次在响应侧。
  2. 同时,代理必须要小而轻。因为每一个代理都会消耗内存和CPU,而且这种消耗会随着服务数量的增加而线性增加。
  3. 考虑到如此庞大的数量,我们也同时需要一个用于批量部署和更新代理的系统,人工部署和更新是不现实的。

在宏观维度来说,这就是服务网格的全部内容了:部署大量的业务侧代理来处理服务间的通信,并使用控制面来控制它们的行为,或是查询它们生成的数据。

服务网格能做到什么?

当你第一次听到服务网格时,可能会有些近乎本能地排斥,这是正常的。服务网格的设计模式不仅给应用程序增加了延迟,还会消耗资源,并引入一大堆机制。可既然如此,为什么还会有人想使用服务网格呢?

主要有两个原因。第一个原因是由于微服务生态的一些变化,部署这些代理的操作成本大大降低(这部分内容我们后面再细聊)。第二个更重要的原因是,这种设计确实是将附加逻辑引入系统的好方法,它使得您可以在不改变系统本身的情况下,添加大量的附加功能。

大多数服务网格的代理都提供了 7 层网络协议的功能支持,总体可以分为三类:

1.可靠性:请求重试、超时、金丝雀(流量拆分/转移)等。

2.可观测性:每个服务或单个路由的成功率、延迟和请求量的聚合、绘制服务拓扑图等。

3.安全性:双向传输层安全保障、访问控制等。

这些特性中很多都是通过对请求层的操作实现的(即 7 层代理)。例如,如果服务 A 对服务 B发起 HTTP 请求,那么 A 端上的代理可以根据观察到的每个 B 实例的延迟情况,智能地选择 B实例,以实现负载平衡。如果请求失败,代理可以进行重试;而如果请求有幂等性设计,代理可以记录响应码和延时等等;类似地,如果本次请求不被允许,服务 B 的代理可以拒绝响应;当请求超时后,代理依旧可以上报 B 的响应延时等等。

同时,代理也可以在连接层做起作用。例如,A 的代理可以发起一个 TLS 连接,B 的代理则可以终止它,不止如此,双方还可以验证其他的 TLS 证书,这不仅提供了服务之间的加密,还提供了一种加密的安全形式的服务认证—— A 和 B 可以自证身份。

就如下文中所说:

在服务网格之前,为了实现以上任意一个功能,可能都需要应用程序团队编写一些复杂的定制代码,并设计专属的指标收集服务及其关联的存储介质。

这些工作不止不轻松,还常常需要很多额外的工作来削弱连锁效应,例如额外的存储开销或防火墙策略的配置。这些过程本身很容易出错,还会带来潜在的资源和时间成本。而服务网格能够消除这些问题。[2]

这就是服务网格所提供的功能,但为什么要额外引入代理呢?直接在应用程序中实现它们不可以么?

服务网格的核心价值是什么?

虽然服务网格的功能很实用,但它的核心价值实际上并不在功能上,毕竟我们可以直接在应用程序中实现这些功能。William Morgan用一句话概括了服务网格的价值:

The service mesh gives you features that are critical for running

modern server-side software in a way that’s uniform across your stack

and decoupled from application code. [3]

服务网格提供了一些对运行现代服务端软件至关重要的特性,它让你的技术栈变得标准化,同时与应用程序的代码解耦。

让我们一步一步来说明。

对运行现代服务端软件至关重要。如果你正在以多个服务间相互通信的模式来开发一款可供外网访问且需要快速响应的服务器端应用,同时,你在通过不断迭代来增加更多功能的时候又需要确保在更新时系统可以正常运行,那么,你就是正在构建现代服务端应用。服务网格的三类功能对你来说都是至关重要的,应用程序必须可靠和安全,同时你还需要观测到它正在做什么,这正是服务网格带来的价值。

技术栈变得标准化。无论应用中的服务是用什么语言编写、使用什么框架、谁编写、如何部署,以及其他开发或部署中的细节等,都可以接入服务网格。

与应用程序代码解耦。服务网格的功能不仅不受技术栈的限制,而且还不需要更改应用程序本身的代码。服务网格的功能下沉到了平台层,包括配置、更新、操作、维护等操作,与应用层隔离开来。应用程序可以在不涉及服务网格的情况下进行更改,服务网格也可以在不涉及应用程序的情况下进行调整。

简而言之:服务网格不仅提供了重要的功能,而且是以一种全局的、统一的、独立于应用程序的方式提供的。即便在服务代码中可以实现服务网格的功能,也无法做到解耦化和标准化,而这恰恰是服务网格的核心价值。

服务网格可以帮助到谁?

尽管服务网格使用很复杂,但事实证明,它依然被广泛采用了。那么都有谁使用了服务网格?又是谁能从中受益呢?

如果你正在构建微服务,你可以将你的团队分为服务开发和平台开发,前者负责构建业务逻辑,后者负责构建运行这些服务的内部平台。在小团队中,服务开发和平台开发可能是同一拨人,但随着团队规模的扩大,这些角色便会细分。

从这个角度来看,服务网格的直接受益者是平台开发者。毕竟,平台团队的目标是构建一个让服务开发者可以在上面运行业务逻辑的内部平台,不用去关注平台操作的诸多细节。服务网格不仅提供了实现这一点的关键特性,还摆脱了对服务开发者的依赖。

服务开发者也会通过间接的方式受益。他们希望在构建业务逻辑时尽可能高效,需要考虑的平台操作机制越少,这个目标就越容易实现。只需要关注业务逻辑问题,平台会处理其他问题,而不用卡在实现重试策略或TLS上,这对他们来说也是个好事。

服务网格与其说是在解决技术问题,更像是在解决技术问题背后的团队问题。

服务网格可以解决所有的问题吗?

当然不能!

通过上文的三种功能(可靠性,安全性和可观察性)就可以清楚知道,服务网格并不是任何一个领域的完整解决方案,它提供的主要是平台功能。在真正使用时,还需要注意以下问题:

1. 独立于业务逻辑。首先, A 请求 B 时的流量指标采集,与 A 请求 B 的业务是无关的。

2. 难以正确实施。即便是像重试这样听起来很简单的操作,也需要做很多参数化的配置。简单粗暴的重试机制往往会导致 "重试风暴"和其他分布式系统故障。

3. 统一实施时最有效。相互TLS的机制只有在每个人都在做的时候才有意义。

由于这些功能是在代理层实现的,所以服务网格是在平台层而不是应用层发挥作用,服务是用什么语言编写的、使用什么框架、谁编写的,以及如何实现的等等都不重要,代理功能不受这些因素影响,这个功能的操作(包括配置、更新、操作、维护等)完全在平台层上。

总结一下:服务网格并不是可靠性、可观察性或安全性的完整解决方案,这些领域还会涉及众多开发、运维甚至 SRE 团队,以及团队的其他成员,服务网格只是提供了平台层的支撑。

为什么服务网格现在才火起来?

你可能会问:既然服务网格这么好,为什么我们不在十年前就投入使用呢?

有一个比较浅显的答案是,十年前大家普遍在构造单体应用,所以没有人需要服务网格。这话没错,但我认为没说到重点,即使在十年前,"微服务 "作为构建大规模系统的可行方式也曾被广泛讨论,并且在 Twitter、Facebook、Google 和 Netflix 等公司被付诸实践。至少在我接触到的行业中,即使它们做起来真的很痛苦,但大家还是普遍认为微服务是构建大规模系统的 "正确方式"。

当然,即便十年前就已经有一些公司在实践微服务,但是他们也并没有使用大量的代理来形成服务网格。不过如果你仔细观察,就会发现他们也在做一些类似的事情:上述大部分公司都会规定使用特定的内部库(有时称为“胖客户端”库)进行网络通信,Netflix 有 Hysterix,Google 有 Stubby 库,Twitter 有 Finagle。例如,Twitter 的每一个新服务中都强制安装了 Finagle ,它同时处理客户端和服务器端的连接,并实现了重试、请求路由、负载均衡和数据采集的功能,为整个 Twitter 技术栈提供了可靠性和可观察性层,且与服务本身的实际业务无关。当然,它只适用于 JVM ,而且它有一个编程范式,你必须围绕这个范式来构建你的整个应用,但是事实上,它提供的功能几乎与服务网格相同。

所以,十年前不仅已经有了微服务,还有原始的服务网格库,这些库解决的许多问题与今天服务网格在做的事情是相同的。之所以那时还没有服务网格,是因为还有更深层次的问题在当时还没有得到解决。

这个更深层次的答案就隐藏在过去十年之间的不同中:部署微服务的成本已经大幅降低。上面列出的那些十年前就在使用微服务的公司——Twitter,Netflix,Facebook 和 Google,都是规模巨大且资源丰富的公司,它们不仅有需求,而且有能力去构建、部署和运行重要的微服务应用程序,但是这种基础设施的改造对于小公司来说基本上是不可能的。

相比之下,在今天,你可能会发现在创业公司中,微服务数量与开发者的比例已经达到了 5:1 甚至10:1,更重要的是,他们已经具备了处理这一问题的能力,而这显然是有工具帮助它们降低了使用微服务的成本。

RbIVFbF.png!mobile

实际上,是容器和容器编排工具的广泛使用,使得微服务的使用成本显著降低,而这也是服务网格得以广泛使用的深层答案所在:Kubernetes 和 Docker。

究其原因,是因为 Docker 解决了一个大问题:制品打包。Docker 可以将你的应用程序和它(网络无关)的运行时依赖打包到一个容器中,让你的应用程序变为一个可替换的单元,可以被放到任何地方运行。同样的道理,Docker 也让运行多种语言编写的服务更加容易,因为容器在使用时是一个原子单元,对于部署和操作来说,容器里面是什么并不重要,无论它是 JVM 、Node、Go 、Python 还是 Ruby,你只要运行它就可以了。

Kubernetes 解决了另一个问题:处理运行项和运行环境(也就是设备)之间的映射关系。当然,映射关系是动态且不断变化的,因为容器会在各个设备中不停的被创建和销毁,但这也可以被 Kubernetes 处理。

使用 Kubernetes 会让部署时间变得非常快,部署 1 个服务的时间与 10 个服务的时间是差不多的,甚至与部署 100 个服务所需的时间也没有太大差异,再加上以鼓励多语言实现的容器作为打包机制,发展结果就会是,出现大量用各种语言编写的新应用所组成的微服务——而这正是服务网格最适合的环境。

最后解释一下为什么服务网格在现在是可行的:Kubernetes 为服务提供的统一性也同样适用于服务网格。只要将代理打包到容器中,然后告诉 Kubernetes 把它们放在哪里,然后Kubernetes 就会帮你处理所有部署期的事情,这样,你的服务网络就搞定了。

小结一下:之所以服务网格不是在 10 年前而是在现在才真正火起来,是因为 Kubernetes 和 Docker 的兴起,使得构建多语言微服务架构的应用变得简单,也让使用服务网格的需求变得更加迫切,不止如此,它们还极大地降低了运行服务网格中大量代理的部署和维护成本。

作为一个软件工程师,我应该关心服务网格吗?

服务网格对以下类型的软件工程师影响很大,应该着重关注。

如果你在使用了 Kubernetes 的团队中负责平台维护:那么你 100% 应该关心。除非你只是使用 Kubernetes 运行一个单体服务或运行批处理程序(如果是这样,我会很好奇为什么要使用 Kubernetes ),否则,你最终都会遇到这样的情况:你有很多其他人编写的微服务,它们彼此需要相互通信且存在复杂的依赖关系,你需要去解决这个问题。既然你已经在使用 Kubernetes,那么要不要使用服务网格,就已经变成了你接下来要考虑的问题。

如果你在一个尚未使用 Kubernetes,但却在做微服务的团队中负责平台维护:那么你也应该关注服务网格。在这种情况下,当然你也可以通过部署大量代理来实现服务网格带来的价值,但是缺少了 Kubernetes 的部署优势,管理这些代理的成本就会变得非常高。

写在最后

如上文所述,Service Mesh 能给企业带来的价值是巨大的。但不可否认的是,Service Mesh 并不能解决所有问题,从概念到落地实践,也需要耗费大量的成本。不过,可以预见,它将变得越来越重要,尤其对于在 Kubernetes 上构建应用程序的人来说,Service Mesh 的价值是毫无疑义的。

为了能够让企业降低使用门槛,以最快的速度和最简单的方式体验 Service Mesh 的诸多优势, SolarMesh 团队基于当前最流行的 Service Mesh 框架 Istio,打造了一款开箱即用的服务网格产品: SolarMesh ,目前已提供了下载体验版。如果您想了解和体验 Service Mesh 的功能,不妨来免费体验一下。

参考文章:

[1] https://buoyant.io/2020/10/12/ ... mesh/

[2] https://dzone.com/articles/wha ... d-one

[3] https://buoyant.io/service-mesh-manifesto/


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK