原文: https://cloud.tencent.com/developer/article/1488311

伴随着微服务架构,容器编排技术和云原生(Cloud Native)应用的发展,William Morgan 两年前一篇《What’s a service mesh? And why do I need one?》把服务网格(Service Mesh)带入到更多人的视野,近两年服务网格软件Linkerd,Istio等在越来越多的公司生产环境中有所应用。

前言

微服务架构里,服务网格是一个负责专门处理服务到服务之间通讯的基础设施层。
服务网格有两个主要目标

  1. 将原先不可见的服务间通讯可视化
  2. 对服务间的通讯进行一定控制(在路由/跟踪/安全等方面);

实践中, 服务网格通常被设计成轻量的网络代理程序,通过无侵入式的方式与应用集成,接管服务所有入口和出口的网络流量,作为微服务之间网络拓扑中的通讯管道。
image.png
Kubernetes提供了服务抽象及服务发现机制,支持微服务之间的相互通讯,为什么我们还需要服务网格呢?我们先来看看Kubernetes的服务发现。

Kubernetes的服务发现

Kubernetes通过抽象出Service对象来支持微服务架构,运行应用的多个Pod实例通过定义Service对象对外提供服务。应用之间通过Service名来相互访问,通过Service名的DNS解析完成服务发现例子查看

具体的,Pod实例运行时会将实例的地址端口等信息注册到kube-apiserver,与相关的Service建立关联(数据存储于背后的etcd存储),同时K8S节点会监听到该Service与Pod实例节点映射关系的变化。对于通常的一个Service名(非Headless Service),它会被DNS服务解析到一个虚拟IP(Virtual IP),而K8S节点上的kube-proxy进程会根据Service的信息建立这个虚拟IP的iptables转发规则:将发送到该虚拟IP的数据均衡的转发到若干个提供该服务的Pod实例所在的节点,以提供L4层的负载均衡功能。

类似于iptables代理模式,Kubernetes也提供了另一种基于哈希表的IPVS代理模式,以解决当服务数量达到上万级别的场景下iptables查找记录性能低下的问题,IPVS模式也提供了基于连接数,期望时延,加权选择等更多的负载均衡算法。
image.png

服务网格优势

相对于Kubernetes工作在第4层的负载均衡,服务网格通过接管服务的出入口流量,可以提供更多对流量的路由控制,加工和可视化能力:

  • 统一提供安全的双向认证加密通道;
  • 支持7层协议检测,支持HTTP,HTTP/2和gRPC代理;
  • 提供请求重试和超时功能;
  • 自动熔断机制;
  • 支持基于就近/端到端请求时延的负载均衡;
  • 服务请求的指标监控和可视化;

在应用服务网格之前,我们通常需要在各个服务程序内部实现以下的各个功能:服务的指标监控,请求重试及超时设定,熔断机制处理等跟服务业务逻辑代码混杂在一起存在于多个微服务之中。
以Linkerd为例,如下图,在集成了服务网格后,服务指标如请求成功率,延时及每秒请求数等会被自动记录并可以方便的集成到Prometheus和Grafana报表中展示。服务网格使得服务运维所需要的代码逻辑与业务逻辑相分离,服务可以专注于业务逻辑的开发。
对于访问在Kubernetes中定义的Service,Linkerd会从K8S中读到Service对应的后台Pod节点信息用做负载均衡而不依赖于服务DNS。基于就近策略的负载均衡使得当Kubernetes在同城多机房部署时,可以优先路由到同机房的服务节点,减少跨机房访问。
image.png
image.png
服务网格在Kubernetes中有两种常见的部署方式:

  1. Sidecar容器的模式(边车模式)、

Sidecar容器模式下linkerd-proxy被部署为每个pod里的一个容器实例,该模式下各个pod的linkerd独立,单个linkerd的故障不会影响其他pod,缺点是服务网格对系统资源的占用随着pod数量增长。

  1. 主机共享代理模式

在主机共享代理模式下,同节点上的pod共用一个linkerd代理,这种方式可以减少linkerd的集群资源占用,也能够通过共享连接池的方式一定程度上提高吞吐量,缺点是当linkerd故障时同节点里的所有pod都会被影响到。
image.png

最后,服务网格跟API网关有什么联系和区别?

API网关的主要职责在于为你的服务提供API接口,而服务网格的主要职责在于从服务实现里解偶出底层网络通讯及其相关的运维需求。两者在路由等部分功能上有一定的重合,但定位不同。微服务之间的内部依赖调用,如果都通过一个中心的内网网关来完成,那么所有服务形成一个中心化的星状网络。
服务网格去中心化的架构使得拓扑中不存在一个可能影响所有微服务的中心网关节点存在,另一方面每次内部请求调用也少了网关这一跳的网络节点。
image.png
面向外部的API网关面向内部的服务网格这样的分工通常会是一种推荐的部署方式
image.png