深入了解服务网格(Service Mesh):让微服务通信更高效
- June 20, 2024
![深入了解服务网格(Service Mesh):让微服务通信更高效](/img/cover/servicemesh.png)
什么是服务网格?
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)是处理服务间通信的基础设施层。它负责构成现代云原生应用程序的复杂服务拓扑来可靠地交付请求。在实践中,Service Mesh 通常以轻量级网络代理阵列的形式实现,这些代理与应用程序代码部署在一起,对应用程序来说无需感知代理的存在。这个术语通常用于描述构成这些应用程序的微服务网络以及应用之间的交互。随着规模和复杂性的增长,服务网格越来越难以理解和管理。它的需求包括服务发现、负载均衡、故障恢复、指标收集和监控以及通常更加复杂的运维需求,例如 A/B 测试、灰度发布、限流、访问控制和端到端认证等。
服务网格的历史
- 2012年,微服务被提出,然后逐渐成为行业中默认的标准。
- 2015年,Spring Cloud诞生。
- 2016年,美国Buoyant公司首次提出服务网格,即“The services must mesh”。
- 2017年,Istio诞生。
服务网格特点
服务网格有如下几个特点:
- 应用程序间通讯的中间层
- 轻量级网络代理
- 应用程序无感知
- 解耦应用程序的重试/超时、监控、追踪和服务发现
目前两款流行的服务网格开源软件 Linkerd 🔗 和 Istio 🔗 都可以直接在 Kubernetes 中集成。
为什么需要使用服务网格?
在云的时代,容器通过将应用程序及其(非网络)运行时依赖项打包到一个容器中,应用程序现在是一个可替代的单元,可以随处乱扔并在任何地方运行,它给予了统一的平台,同时赋予了易用性,让构建应用程序有了更多可能,而Kubernetes在弥补了容器难以管理与编排等缺点,增加了应用的扩容能力,可以对应用进行快速编排部署等。
但是这仅仅是解决了部署的问题。而运行时的怎么进行管理,这又是一个问题?毕竟,部署不是生产的最后一步,部署之后还需要运行。所以,服务网格来了。
服务网格解决了哪些问题?
当一个单体应用变得逐渐庞大的时候,那么就会考虑采用微服务。服务发现、滚动部署和灰度部署、问题跟踪 、安全问题 等成为痛点。
- 服务发现,当单体应用拆分为微服务后,各个服务之间的通信就成了问题,当然,每个微服务可以将自己的IP与Port写死,然后通过一种机制将自己注册进去,并且能够感知其他的服务。Spring Cloud中的Eureka、Zookeeper、Nacos就是这么做的。但是这样往往会出现一个问题,当服务发现服务出现问题时,就会导致整个微服务直接瘫痪。
- 滚动部署和灰度部署,当新版本发布时,其中也会带来一系列的部署问题,这也是需要考虑的。
- 监控与问题跟踪,由于网络是不可控的,当服务数量增加时,各个服务之间的通信与管理江边的复杂。并且请求是在多个微服务之间进行调用的,那么一个请求在众多微服务之中进行调用出现问题时,那么追踪该请求也是一个问题。
- 安全问题,一般请求会采用https来加强请求调用的安全性,那么对于这些证书需要进行妥善的管理。
- 等等…
场景模拟:目前一个系统有订单服务与支付服务,在传统时代,当一个订单到来时,订单服务直接将请求发送到支付服务。为了让这个请求看起来高可用,那么我们需要考虑到请求超时、超时重试等等,而这些逻辑都会充斥在代码里面。当然这只是其中的一个请求,当服务越来越多时,那么各个服务之间的调用将变得复杂,无用代码也变得更多。
当然,我们可以尝试将整个请求即请求后的种种保证其可用的逻辑抽离,在各个服务之间复用。但是这还是给我们带来了一些问题,第一:公司依然需要投入人员、时间去维护这段可用的代码;第二:它限制了我们开发时的工具、框架,甚至是语言。
那么,服务是如何解决这些问题的?
一个可行的方案是在原有的协议(例如http)之上,增加一层更高的协议。现在在现有的网络结构中这明显不是一种可行的方案。于是将它抽离成了代理。
Service Mesh 为每一个服务配置一个代理,它将拦截所有的请求,即不同应用的之间的通信由代理来进行控制。
服务网格是用于处理服务间通信的专用基础设施层。它负责通过包含现代云原生应用程序的复杂服务拓扑来可靠地传递请求。实际上,服务网格通常通过一组轻量级网络代理来实现,这些代理与应用程序代码一起部署,而不需要感知应用程序本身。 —— Willian Morgan 🔗 Buoyant CEO
服务网格的实现方式?
网格会为每一个服务(绿色部分)配置一个代理服务(蓝色),最终的部署图如下,看起来就像一个网格,“服务网格”以此而来。
服务网格代理的是一个服务,而这些服务可以是应用、容器、路由、节点,甚至是集群。所以衍生了以下的实现方式。
- Ingress 或边缘代理
- 路由器网格
- Proxy per Node
- Sidecar代理/Fabric模型
- Sidecar代理/控制平面
- 多集群部署和扩展
其中,Sidecar代理/控制平面是市面上大部分服务网格采用的实现方式。
当然,上图并不能完整的表达网格服务的实现原理,这种模式一般由数据平面和控制平面组成。
-
数据平面(Data Plane)负责在服务中部署一个称为“边车”(sidecar)的请求代理,通常与服务一起部署,往往一个服务伴随一个sidecar,。
-
控制平面(Control Plane)负责控制sidecar来实现服务治理的功能,例如配置分发、服务发现、流量路由、授权鉴权等,相当于服务网格的大脑/指挥官。
当然,在Kubernetes中,网格服务并不是通信的唯一选择,也可以采用其他方案,例如:
- 扁平网络(例如Calico、Flannel)
- 共同管理
- 等等…
Kubernetes VS Service Mesh
-
kube-proxy 的设置是全局的,无法对每个服务进行细粒度的控制,Kubernetes 可以做的只有拓扑感知路由、将流量就近路由,为 Pod 设置进出站的网络策略。
而服务网格通过 sidecar proxy 的方式将 Kubernetes 中的流量控制从服务层中抽离出来,为每个 Pod 中注入代理,并通过一个控制平面来操控这些分布式代理。这样可以实现更大的弹性。
也就是说kube-proxy拦截的流量是Kubernetes 节点的进出流量,而Service Mesh拦截的是进出该Pod的流量。
-
在kube-proxy 中,如果转发的 pod 不能正常提供服务,它不会自动尝试另一个 pod,每个 pod 都有一个健康检查的机制,当有 pod 健康状况有问题时,kubelet 会重启对应的 pod,kube-proxy 会删除对应的转发规则。另外,
nodePort
类型的服务也无法添加 TLS 或者更复杂的报文路由机制。
Reference:
![lomtom](/images/avatar-removebg.png)