061 管理设计篇之服务网格

前面,我讨论了 Sidecar 边车模式,这是一个非常不错的分布式架构的设计模式。因为这个模式可以有效地分离系统控制和业务逻辑,并且可以让整个系统架构在控制面上可以集中管理,可以显著地提高分布式系统的整体控制和管理效率,并且可以让业务开发更快速。

那么,我们不妨在上面这个模式下 think big 一下。假如,我们在一个分布式系统中,已经把一些标准的 Sidecar 给部署好了。比如前面文章说过的熔断、限流、重试、幂等、路由、监视等这些东西。我们在每个计算结点上都部署好了这些东西,那么真实的业务服务只需要往这个集群中放,就可以和本地的 Sidecar 通信,然后由 Sidecar 委托代理与其它系统的交互和控制。这样一来,我们的业务开发和运维岂不是简单之极了?

是啊,试想一下,如果某云服务提供商,提供了一个带着前面我们说过的那些各式各样的分布式设计模式的 Sidecar 集群,那么我们的用户真的就只用写业务逻辑相关的 service 了。写好一个就往这个集群中部署,开发和运维工作量都会得到巨大的降低和减少。

什么是 Service Mesh

这就是 CNCF(Cloud Native Computing Foundation,云原生计算基金会)目前主力推动的新一代的微服务架构——Service Mesh 服务网格。

What’s a service mesh? And why do I need one? 中,解释了什么是 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.

Service Mesh 这个服务网络专注于处理服务和服务间的通讯。其主要负责构造一个稳定可靠的服务通讯的基础设施,并让整个架构更为的先进和 Cloud Native。在工程中,Service Mesh 基本来说是一组轻量级的服务代理和应用逻辑的服务在一起,并且对于应用服务是透明的。

说白了,就是下面几个特点。

说起来,Service Mesh 就像是网络七层模型中的第四层 TCP 协议。其把底层的那些非常难控制的网络通讯方面的控制面的东西都管了(比如:丢包重传、拥塞控制、流量控制),而更为上面的应用层的协议,只需要关心自己业务应用层上的事了。如 HTTP 的 HTML 协议。

Pattern: Service Mesh 这篇文章里也详细解释了 Service Mesh 的出现并不是一个偶然,而是一个必然,其中的演化路径如下。

img 图片来自Pattern: Service Mesh

然后呢,Sidecar 集群就成了 Service Mesh。图中的绿色模块是真实的业务应用服务,蓝色模块则是 Sidecar,其组成了一个网格。而我们的应用服务完全独立自包含,只需要和本机的 Sidecar 依赖,剩下的事全交给了 Sidecar。

img 图片来自Pattern: Service Mesh

于是 Sidecar 组成了一个平台,一个 Cloud Native 的服务流量调度的平台(你是否还记得我在《分布式系统的本质》那一系列文章中所说的关键技术中的流量调度和应用监控,其都可以通过 Service Mesh 这个平台来完成)。

img 图片来自Pattern: Service Mesh

加上对整个集群的管理控制面板,就成了我们整个的 Service Mesh 架构。

img 图片来自Pattern: Service Mesh

img 图片来自Pattern: Service Mesh

Service Mesh 相关的开源软件

目前比较流行的 Service Mesh 开源软件是 IstioLinkerd,它们都可以在 Kubernetes 中集成。当然,还有一个新成员 Conduit,它是由 Linkerd 的作者出来自己搞的,由 Rust 和 Go 写成的。Rust 负责数据层面,Go 负责控制面。号称吸取了很多 Linkerd 的 Scala 的教训,比 Linkerd 更快,还轻,更简单。

我虽然不是语言的偏好者,但是,不可否认 Rust/Go 的性能方面比 Scala 要好得多得多,尤其是要做成一个和网络通讯相关的基础设施,性能是比较重要的。

对此,我还是推荐大家使用 Rust/Go 语言实现的 lstio 和 Conduit,后者比前者要轻很多。你可以根据你的具体需求挑选,或是自己实现。

lstio 是目前最主流的解决方案,其架构并不复杂,其核心的 Sidecar 被叫做 Envoy(使者),用来协调服务网格中所有服务的出入站流量,并提供服务发现、负载均衡、限流熔断等能力,还可以收集大量与流量相关的性能指标。

在 Service Mesh 控制面上,有一个叫 Mixer 的收集器,用来从 Envoy 收集相关的被监控到的流量特征和性能指标。然后,通过 Pilot 的控制器将相关的规则发送到 Envoy 中,让 Envoy 应用新的规则。

最后,还有一个为安全设计的 lstio-Auth 身份认证组件,用来做服务间的访问安全控制。

整个 lstio 的架构图如下。

img

Service Mesh 的设计重点

Service Mesh 作为 Sidecar 一个集群应用,Sidecar 需要的微观层面上的那些设计要点在这里就不再复述了,欢迎大家看我之前的文章。这里,更多地说一下 Service Mesh 在整体架构上的一些设计要点。

我们知道,像 Kubernetes 和 Docker 也是分布式系统管理面上的技术解决方案,它们一样对于应用程序是透明的。最重要的是,Kubernetes 和 Docker 对于应用服务的干扰是比较少的。也就是说,Kubernetes 和 Docker 的服务进程的失败不会导致应用服务的异常运行。然后,Service Mesh 则不是,因为其调度了流量,所以,如果 Service Mesh 有 bug,或是 Sidecar 的组件不可用,就会导致整个架构出现致命的问题。

所以,在设计 Service Mesh 的时候,我们需要小心考虑,如果 Service Mesh 所管理的 Sidecar 出了问题,那应该怎么办?所以,Service Mesh 这个网格一定要是高可靠的,或者是出现了故障有 workaround 的方式。一种比较好的方式是,除了在本机有 Sidecar,我们还可以部署一下稍微集中一点的 Sidecar——比如为某个服务集群部署一个集中式的 Sidecar。一旦本机的有问题,可以走集中的。

这样一来,Sidecar 本来就是用来调度流量的,而且其粒度可以细到每个服务的实例,可以粗到一组服务,还可以粗到整体接入。这看来看去都像是一个 Gateway 的事。所以,我相信,使用 Gateway 来干这个事应该是最合适不过的了。这样,我们的 Service Mesh 的想像空间一下子就大多了。

Service Mesh 不像 Sidecar 需要和 Service 一起打包一起部署,Service Mesh 完全独立部署。这样一来,Service Mesh 就成了一个基础设施,就像一个 PaaS 平台。所以,Service Mesh 能不能和 Kubernetes 密切结合就成为了非常关键的因素。

小结

好了,我们来总结一下今天分享的主要内容。首先,边车模式进化的下一阶段,就是把它的功能标准化成一个集群,其结果就是服务网格。它在分布式系统中的地位,类似于七层网络模型中的传输层协议,而服务本身则只需要关心业务逻辑,因此类似于应用层协议。然后,我介绍了几个实现了服务网格的开源软件。最后,我介绍了服务网格的几个设计重点。下篇文章中,我们讲述网关模式。希望对你有帮助。

也欢迎你分享一下你接触到的分布式系统有没有用到服务网格?具体用的是哪个开源或闭源的框架?