Service Mesh介绍

本周我们很开心邀请到了Becky和Hongbo给我们带来了Service Mesh的介绍,相关的总结如下:

Slides

  1. Becky的slides
  2. Hongbo的slides

Q&A

感谢琅琊王伯興和Nancy给我们整理的笔记。

Service Mesh出现的原因,优势和存在的局限性

讲座中大家讨论了很多关于service mesh出现的原因以及对client端和service端带来的作用,这里整理了一部分内容参考:

Motivation of service mesh:

  • 微服务带来的通信问题及相应解决方案: 随着分布式系统的发展,很多分布式独有的通信问题随之出现:负载均衡(load balancing), 服务发现(service discovery), 熔断机制(circuit breaker), trace, monitor等。因此,为了避免每个微服务(microservice)都实现一套通用的分布式系统通信,开始出现面向微服务架构的开发框架 (e.g. spring cloud)。这些框架实现了分布式系统中微服务通信的通用逻辑,只需要少量代码和注解,即可集成各种所需的通信功能,如此一来,工程师可以集中精力在busniess logic层面的开发。
  • 微服务开发框架存在的问题促进了service mesh的诞生: 微服务开发框架虽然解决了统一通信的问题,但也存在一些问题:1)开发者仍需要大量精力去理解和管理复杂的框架;2)微服务很重要的特性是和语言无关,但是开发框架却可能存在不支持的语言;3)升级维护成本高:因为SDK耦合在业务进程中,一方面这种依赖很可能带来版本兼容相关的问题,另一方面SDK的升级必然绑定业务一起升级。 因此,service mesh应运而生, 它将分布式系统中的通用通信逻辑抽离出来放入单独的sidecar container中。sidecar和application 作为独立的container共同部署在同一台机器上。因此,application上所有ingress和egress的通信都通过独立的sidecar来接管,从而根本上解决了开发框架的三个本质问题, 具体如下图。这也是service mesh名字的由来,因为从全局上看, 他就是一个服务网格,比较有代表性的框架有Linkerd和Istio.
  • service mesh的优势 基本上来说,微服务框架开发的痛点就是service mesh的优点。
    • 真正实现了微服务要求的和语言无关:由于没有SDK的依赖,application可以用任意语言开发;
    • 升级难度和成本降低:service mesh的组件可以单独开发。
    • 使用简单:如负载均衡、熔断、限流等策略配置,由ControlPlane统一管理和配置,并下发到Dataplane生效。 service mesh的配置非常简单,几乎是开箱即用的。
  • service mesh的局限性(以Istio为例)
    • 性能损耗:原通信多经历了service mesh一层,会带来通信的延时。目前公开的 Service Mesh 中 Envoy 造成的额外访问延时大概是 3 毫秒。另外原有的设计也会经过API Gateway,所以只是南北向通信到东西向的转换,性能的损耗并没有想象中大。
    • 资源占用:service mesh会增加系统资源开销。以Istio为例,Envoy作为流量代理是CPU密集型应用,在测压环境下,envoy占用的CPU资源可高达20%-30%.
    • 对非 Kubernetes 环境支持有限: 目前主流的service mesh,如Istio和Linkerd都是比较依赖Kubernetes的
    • 数据流复杂性增加:service mesh是侵入了micro service的数据流的,这将增加调试难度和运维的难度。

【扩展】service间通信变迁 — 从TCP出现前到最新一代serivce mesh:下一代微服务,到底什么是Service Mesh?

【扩展】service mesh有它的优势和局限性,不是所有的应用都适合采用service mesh,做好前期调研很重要: InfoQ文章—不是所有的应用都需要Service Mesh架构

【扩展】service mesh的诞生,定义,特性,架构和用例:InfoQ文章 — Service Mesh 终极指南(第二版):次世代微服务开发

Service mesh vs. API Gateway

从定位和职能上,service mesh和API Gateway分工明确; 但从具体实现上,两者开始出现融合。

  • 分工明确的定位和职责
    • Service Mesh:微服务的网络通信基础设施,负责系统内部的服务间的通讯, service mesh不了解任何的业务逻辑;
    • API Gateway:负责将服务以 API 的形式暴露给系统外部,以实现业务功能。正是基于两者在职能和部署上的区别,通常说API Gateway负责南北向通讯,service mesh负责东西向通讯。
    • 东西向通讯:指服务间的相互访问,其通讯流量在服务间流转,流量都位于系统内部;
    • 南北向通讯:指服务对外部提供访问,通常是通过 API Gateway 提供的 API 对外部保罗,其通讯流量是从系统外部进入系统内部。
  • service mesh和API gateway的融合 随着service mesh的出现,一个重要课题就是如何基于service mesh服务采用合适的API gateway。其中重用service mesh服务到API Gateway中成为了一个研究方向,例如基于service mesh的sidecar来实现API Gateway,如此一来,API Gateway也可以拆分成两个部分:Sidecar + API Gateway本体。
    • API Gateway本体:实现原API Gateway除内部访问外所有的功能
    • Sidecar:参考service mesh的部署方法,将API Gateway视为service,为其1:1部署sidecar,如下图所示

【扩展】service mesh如何和API Gateway从泾渭分明到深度融合:相爱相杀:Service Mesh 和 API Gateway 关系深度探讨

【扩展】《Microservices for the Enterprise: Designing, Developing, and Deploying》的作者Kasun Indrasiri 写的一篇文章:Service Mesh vs API Gateway,这里也有一篇译文

【扩展】这一篇主要从Istio的角度来进行了比较:如何理解 Istio Ingress, 它与 API Gateway 有什么区别?

RPC vs. service mesh

这里假定读者已对微服务架构有一定之了解。

RPC的定义如下:

Wikipedia: In distributed computing, a remote procedure call(RPC) is when a computer program causes a procedure (subroutine to execute in a different address space (commonly on another computer on a shared network), which is coded as if it were a normal (local) procedure call, without the programmer explicitly coding the details for the remote interaction.

Service Mesh的定义如下:

Wikipedia: In software architecture, a service mesh is a dedicated infrastructure layer for facilitating service-to-service communications between services or microservices, using a proxy.[1]

从概念上来说,这两者解决的问题并不冲突。我们先来看一下RPC解决了何种问题。下图展示了一次完整的RPC调用过程。大多数的RPC框架,提供的是RPC协议这一部分。

以gRPC为例,以下代码(https://grpc.io/docs/languages/python/basics/)定义了server提供的interface,用户定义如下interface之后,部署在client端和server端。client调用时,gRPC负责将RPC request序列化并通过网络传输到server的端口, server端收到后进行反序列化,并调用本地函数,返回结果。

// The greeter service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

以上过程详见下图:

当然,其他问题诸如服务发现与注册,即Binding的过程,仍需特别处理。

序列化的协议传输有HTTP 2,HTTP 1.1,TCP多种实现方式,视框架而定。譬如gRPC建立在HTTP 2的基础之上。

Service Mesh将如何影响RPC呢?我并未找到可靠的资料回答这一问题,以下引自https://www.cnblogs.com/Duxue/p/11958586.html

在服务mesh化之前,服务调用方实例通过自己内部的RPC库来与服务提供方实例进行通信。

在服务mesh化之后,会与服务调用方同机部署一个local Proxy也就是ServiceMesh的proxy,此时服务调用的流量会先走到这个proxy,再由它完成原先RPC库响应的工作。至于如何实现这个流量的劫持,答案是采用iptables,将特定端口的流量转发到proxy上面即可。

有了这一层的分拆,将业务服务与负责RPC库作用的Proxy分开来,上面的两个痛点问题就变成了对每台物理机上面的mesh proxy的升级维护问题,多语言也不是问题了,因为都是通过网络调用完成的RPC通信,而不是进程内使用RPC库。

然而这个方案并不是什么问题都没有的,最大的问题在于,多了这一层的调用之后,势必有影响原来的响应时间。

【扩展】上述图片均来自于RPCRPC,微服务,Service Mesh这些服务之间的调用是什么原理?

【扩展】RPC的介绍:Remote Procedure Call (RPC)

【扩展】gRPC的使用文档

【扩展】一篇介绍RPC和Service Mesh的文章: 现代 RPC 形态与 Service Mesh

【扩展】一篇有意思的文章,从Service Mesh演变的角度来看了RPC和Service Mesh的关系: ServiceMesh究竟解决什么问题?

【扩展】蚂蚁金服从落地角度对这个问题的思考:蚂蚁金服 Service Mesh 大规模落地系列 – RPC 篇

service discovery 在service mesh中的实现:register, load balancing

Service discovery是微服必不可少的一环。不熟悉微服务的同学也很容易理解。承接上图(https://www.cnblogs.com/Duxue/p/11952952.html),有了RPC框架之后,client需要知道server的ip地址,即服务发现与服务暴露的过程。

微服务中,service discovery是一个复杂的过程。概而言之,需要额外的client library,service registry与load balancer来解决这个问题,如下图(https://www.nginx.com/blog/service-discovery-in-a-microservices-architecture/)所示:

常见框架有Netflix的Eureka,Zuul等。

简言之,server的具体ip地址对client是透明的,每当一个新的service instance启动,就会在service registry中报告自己的ip,最后由load balancer分配给client.

以上问题在Kubernetes都提供了out-of-box的解决方法。

Service是Kubernetes原生的概念,以下摘自官网(https://kubernetes.io/docs/concepts/services-networking/service):

In Kubernetes, a Service is an abstraction which defines a logical set of Pods and a policy by which to access them (sometimes this pattern is called a micro-service).

If you’re able to use Kubernetes APIs for service discovery in your application, you can query the API server  for Endpoints, that get updated whenever the set of Pods in a Service changes.

这意味着client可以直接获取Pod(对应微服务中一个server instance)的ip并访问,实现client-side server discovery.

此外,Kubernetes会自动完成service discovery。具体的实现过程大致如下,在client端的iptable中,每个Service会有一个唯一对应的clusterIp,这个cluterIp是虚拟不变的,Kubernetes中的kube-proxy负责更新解析clusterIp,每当client需要访问server端时,clusterIp会被替换为真实ip并发送。可参考下图(https://iximiuz.com/en/posts/service-discovery-in-kubernetes/)理解。实际的过程非常复杂,需要精读Kubernetes文档。关于clusterIp如何在协议中被替换,可以参考《Tracing the path of network traffic in Kubernetes》中《Intercepting and rewriting traffic with Netfilter and Iptables》一节**(**https://learnk8s.io/kubernetes-network-packets#inspecting-pod-to-service-traffic)。

【扩展】“Microservice Pattern”中关于service registryclient-side service discovery以及server-side service discovery的介绍,大家可以参考。

【扩展】关于Microservice中service discovery介绍的一篇文章:Service Discovery in a Microservices Architecture

【扩展】想深入了解Kubernetes内部网络流程的可以参考这篇文章:Tracing the path of network traffic in Kubernetes

【扩展】一篇对于Service mesh进行实践的文章:Microservices — Discovering Service Mesh

【扩展】Service Mesh,service discovery和API GateWays三者介绍的文章:Service Mesh, Service Discovery and API Gateways

Istio,Linkerd以及Consul的比较

他们三者算是目前Service Mesh最流行的三个方面了,相关的详细比较可以见扩展阅读。

【扩展】详细的三者比较:Kubernetes Service Mesh: A Comparison of Istio, Linkerd, and Consul,有一篇译文

【扩展】从benchmark的角度对Istio以及Linkerd进行了比较:Linkerd vs Istio

【扩展】这篇文章包含了一些选择上的思考,大家可以参考:(2021)服务网格除了 Istio,其实你还可以有其它 8 种选择

【扩展】这篇比较的文章也不错:Networking with a service mesh: use cases, best practices, and comparison of top mesh options

再次感谢大家的参与,也希望大家有好的资源能联系我更新这篇文章。谢谢大家。

下周话题安排和往期话题回顾敬请参见《系统设计开荒小分队话题讨论简介

You may also like...

Leave a Reply

Your email address will not be published.