云原生社区最新力作《深入理解 Istio》出版

2022-11-07 17:01:20 浏览数 (3)

云原生社区最新力作 —— 《深入理解 Istio》出版发售

❝云原生实验室和电子工业出版社将为大家送出 5 本《深入理解 Istio:云原生服务网格进阶实战》。关注本公众号参与抽奖即可获取。

听说过服务网格并试用过 Istio 的人可能都会有以下 5 个疑问:

  1. 为什么 Istio 要绑定 Kubernetes 呢?
  2. Kubernetes 和服务网格分别在云原生中扮演什么角色?
  3. Istio 扩展了 Kubernetes 的哪些方面?解决了哪些问题?
  4. Kubernetes、xDS 协议(Envoy、MOSN 等)与 Istio 之间是什么关系?
  5. 到底该不该使用 Service Mesh?

❝本文将带读者梳理清楚 Kubernetes、xDS 协议与 Istio 服务网格之间的内在联系。此外,本文还将介绍 Kubernetes 中的负载均衡方式,xDS 协议对于服务网格的意义,以及为什么说即使有了 Kubernetes 还需要 Istio。

使用服务网格并非与 Kubernetes 决裂,而是水到渠成的事情。Kubernetes 的本质是通过声明配置对应用进行生命周期管理,而服务网格的本质是提供应用间的流量和安全性管理,以及可观察性。假如已经使用 Kubernetes 构建了稳定的微服务平台,那么如何设置服务间调用的负载均衡和流量控制?

Envoy 创造的 xDS 协议被众多开源软件所支持,如 Istio、Linkerd、MOSN 等。Envoy 对服务网格或云原生而言最大的贡献就是定义了 xDS。Envoy 本质上是一个网络代理,是通过 API 配置的现代版代理,基于它衍生出了很多不同的使用场景,如 API 网关、服务网格中的 Sidecar 代理和边缘代理。

重要观点

如果想要提前了解下文的所有内容,则可以先阅读下面列出的一些主要观点。

  • Kubernetes 的本质是应用的生命周期管理,具体来说,就是应用的部署和管理(扩缩容、自动恢复、发布)。
  • Kubernetes 为微服务提供了可扩展、高弹性的部署和管理平台。
  • 服务网格的基础是透明代理,先通过 Sidecar 代理拦截到微服务间流量,再通过控制平面配置管理微服务的行为。
  • 服务网格将流量管理从 Kubernetes 中解耦,服务网格内部的流量无须 kube-proxy 组件的支持,通过接近微服务应用层的抽象,管理服务间的流量,实现安全性和可观察性功能。
  • xDS 定义了服务网格配置的协议标准。
  • 服务网格是对 Kubernetes 中的 service 更上层的抽象,它的下一步是 serverless。

Kubernetes 与 Service Mesh

图 1 所示为 Kubernetes 原生与 Service Mesh 的服务访问关系(每个 Pod 中部署一个 Sidecar 的模式)。

图 1

流量转发

Kubernetes 集群的每个节点都部署了一个 kube-proxy 组件,该组件会先与 Kubernetes API Server 通信,获取集群中的 service 信息,再设置 iptables 规则,直接将对某个 service 的请求发送到对应的 Endpoint(属于同一组 service 的 Pod)上。

服务发现

Istio 服务网格不仅可以沿用 Kubernetes 中的 service 做服务注册,还可以通过控制平面的平台适配器对接其他服务发现系统,生成数据平面的配置(使用 CRD 声明,保存在 etcd 中)。数据平面的透明代理(Transparent Proxy)以 Sidecar 容器的形式部署在每个应用服务的 Pod 中,这些 Proxy 都需要请求控制平面同步代理配置。之所以说是透明代理,是因为应用程序容器完全没有感知代理的存在,在该过程中 kube-proxy 组件一样需要拦截流量,只不过 kube-proxy 组件拦截的是进出 Kubernetes 节点的流量,而 Sidecar Proxy 拦截的是进出该 Pod 的流量。图 2 所示为 Istio 中的服务发现机制。

图 2

服务网格的劣势

由于 Kubernetes 的每个节点都会运行众多的 Pod,因此将原先 kube-proxy 方式的路由转发功能置于每个 Pod 中,会导致大量的配置分发、同步和最终一致性问题。为了细粒度地进行流量管理,必须添加一系列新的抽象,从而导致用户的学习成本进一步增加,但随着技术的普及,该情况会慢慢得到缓解。

服务网格的优势

kube-proxy 的设置都是全局生效的,无法对每个服务做细粒度的控制,而服务网格通过 Sidecar Proxy 的方式将 Kubernetes 中对流量的控制从 service 一层抽离出来,做更多的扩展。

kube-proxy 组件

在 Kubernetes 集群中,每个 Node 运行一个 kube-proxy 进程。kube-proxy 负责为 service 实现一种 VIP(虚拟 IP 地址)的形式。

在 Kubernetes v1.0 版本中,代理完全在 userspace 代理模式中实现。

在 Kubernetes v1.1 版本中,新增了 iptables 代理模式,但不是默认的运行模式。从 Kubernetes v1.2 版本起,默认使用 iptables 代理模式。在 Kubernetes v1.8.0-beta.0 版本中,添加了 IPVS 代理模式。

kube-proxy 的缺陷

首先,如果转发的 Pod 不能正常提供服务,那么它不会自动尝试另一个 Pod,不过这个问题可以通过 liveness probes 解决。每个 Pod 都有一个健康检查机制,当 Pod 健康状况有问题时,kube-proxy 会删除对应的转发规则。另外,nodePort 类型的服务也无法添加 TLS,或者更复杂的报文路由机制。

kube-proxy 实现了流量在 Kubernetes 服务中多个 Pod 实例间的负载均衡,但是如何对这些服务间的流量做细粒度的控制,比如,将流量按照百分比划分到不同的应用版本(这些应用版本都属于同一个服务的一部分,但位于不同的部署上),做金丝雀发布(灰度发布)和蓝绿发布?Kubernetes 社区给出了使用 Deployment 做金丝雀发布的方法,该方法本质上就是通过修改 Pod 的 label 将不同的 Pod 划归到 Deployment 的 service 上。

Kubernetes Ingress 与 Istio Gateway

kube-proxy 只能路由 Kubernetes 集群内部的流量,而 Kubernetes 集群的 Pod 位于 CNI 创建的网络中,集群外部是无法直接与其通信的,因此在 Kubernetes 中创建了 Ingress 这个资源对象,并由位于 Kubernetes 边缘节点(这样的节点可以有很多个,也可以有一组)的 Ingress Controller 驱动,负责管理南北向流量。

Ingress 必须对接各种 Ingress Controller 才能使用,比如,Nginx Ingress Controller、Traefik。Ingress 只适用于 HTTP 流量,使用方式也很简单,但只能对 service、Port、HTTP 路径等有限字段匹配路由流量,这导致它无法路由如 MySQL、Redis 和各种私有 RPC 等 TCP 流量。

要想直接路由南北向的流量,只能使用 service 的 LoadBalancer 或 NodePort,前者需要云厂商支持,后者需要进行额外的端口管理。

有些 Ingress Controller 支持暴露 TCP 和 UDP 服务,但是只能使用 service 来暴露,Ingress 本身是不支持的,例如,Nginx Ingress Controller,服务暴露的端口是通过创建 ConfigMap 的方式配置的。

Istio Gateway 的功能与 Kubernetes Ingress 的功能类似,都是负责管理集群的南北向流量。

Istio Gateway 可被看作网络的负载均衡器,用于承载进出网格边缘的连接。

Istio Gateway 规范描述了一系列开放端口和这些端口所使用的协议、负载均衡的 SNI 配置等内容。

Istio 中的 Gateway 资源是一种 CRD 扩展,它同时复用了 Sidecar 代理功能,详细配置请参考 Istio 官方网站。

xDS 协议

图 3 所示为 Service Mesh 的控制平面,读者在了解服务网格时可能看到过,每个方块代表一个服务的实例,例如,Kubernetes 中的一个 Pod(其中包含了 Sidecar 代理)。xDS 协议控制了 Istio 服务网格中所有流量的具体行为,即将图 1-3 中的方块链接到了一起。

图 3

xDS 协议是由 Envoy 提出的,在 Envoy v2 版本的 API 中最原始的 xDS 协议指的是 CDS(Cluster Discovery Service)、EDS(Endpoint Discovery Service)、LDS(Listener Discovery Service)和 RDS(Route Discovery Service),后来在 Envoy v3 版本中 xDS 协议又发展出了 Scoped Route Discovery Service(SRDS)、Virtual Host Discovery Service(VHDS)、Secret Discovery Service(SDS)、Runtime Discovery Service(RTDS)。

下面通过两个服务的通信了解 xDS 协议,如图 4 所示。

图 4

图 4 中的箭头不是流量进入 Proxy 后的路径或路由,也不是实际顺序,而是虚拟的一种 xDS 接口处理顺序。其实在各个 xDS 协议之间也是有交叉引用的。

支持 xDS 协议的代理可以通过查询文件或管理服务器动态发现资源。概括地讲,这些发现服务及其相应的 API 被称作 xDS。Envoy 通过订阅(Subscription)方式获取资源,订阅方式有以下 3 种

  • 文件订阅: 监控指定路径下的文件。发现动态资源的最简单方式就是将其保存于文件中,并将路径配置在 configSource 中的 path 参数中。
  • gRPC 流式订阅: 每个 xDS API 可以单独配置 ApiConfigSource,指向对应的上游管理服务器的集群地址。
  • 轮询 REST-JSON 轮询订阅: 单个 xDS API 可以对 REST 端点进行同步(长)轮询。

Istio 使用 gRPC 流式订阅的方式配置所有的数据平面的 Sidecar Proxy。下面总结关于 xDS 协议的要点

  • CDS、EDS、LDS、RDS 是最基础的 xDS 协议,都可以独立更新。
  • 所有的发现服务(Discovery Service)可以连接不同的管理服务,也就是说管理 xDS 的服务器可以有多个。
  • Envoy 在原始 xDS 协议的基础上进行了一系列扩充,增加了 SDS(密钥发现服务)、ADS(聚合发现服务)、HDS(健康发现服务)、MS(Metric 服务)、RLS(速率限制服务)等 API。
  • 为了保证数据一致性,若直接使用 xDS 原始 API,则需要保证按照 CDS → EDS → LDS → RDS 的顺序更新。这是遵循电子工程中的先合后断(Make-Before-Break)原则的,即在断开原来的连接之前先建立好新的连接,应用在路由里就是为了防止在设置了新的路由规则时无法发现上游集群而导致流量被丢弃的情况,类似于电路里的断路。
  • CDS 用于设置服务网格中有哪些服务。
  • EDS 用于设置哪些实例(Endpoint)属于这些服务(Cluster)。
  • LDS 用于设置实例上监听的端口以配置路由。
  • RDS 是最终服务间的路由关系,应该保证最后更新 RDS。

Envoy

Envoy 是 Istio 服务网格中默认的 Sidecar,Istio 在 Envoy 的基础上按照 Envoy 的 xDS 协议扩展了其控制平面。在讲解 Envoy xDS 协议之前还需要先熟悉下 Envoy 的基本术语。下面列举了 Envoy 中的基本术语及其数据结构解析

  • Downstream(下游): 下游主机连接到 Envoy,发送请求并接收响应,即发送请求的主机。
  • Upstream(上游): 上游主机接收来自 Envoy 的连接和请求,并返回响应,即接收请求的主机。
  • Listener(监听器): 监听器是命名网地址(例如,端口、UNIX Domain Socket 等),下游客户端可以连接这些监听器。Envoy 暴露一个或多个监听器给下游主机连接。
  • Cluster(集群): 集群是指 Envoy 连接的一组逻辑相同的上游主机。Envoy 通过服务发现来发现集群的成员,并且可以通过主动健康检查确定集群成员的健康状态。Envoy 通过负载均衡策略决定将请求路由到集群的哪个成员。

Envoy 中可以设置多个 Listener,每个 Listener 中又可以设置 filterchain(过滤器链表),而且过滤器是可扩展的,这样就可以更方便地操作流量了,例如,设置加密、私有 RPC 等。

xDS 协议是由 Envoy 提出的,目前是 Istio 中默认的 Sidecar 代理。但是,只要实现了 xDS 协议,理论上就可以作为 Istio 中的 Sidecar 代理,例如,蚂蚁集团开源的 MOSN。

Istio Service Mesh

Istio 是一个功能十分丰富的 Service Mesh 实现产品,包括如下功能。

  • 流量管理: 这是 Istio 最基本的功能。
  • 策略控制: 通过 Mixer 组件和各种适配器可以实现访问控制系统、遥测捕获、配额管理和计费等策略控制。
  • 可观测性: 通过 Mixer 实现。
  • 安全认证: 通过 Citadel 组件做密钥和证书管理。

Istio 中定义了如下的 CRD 来帮助用户进行流量管理。

  • Gateway: 描述了在网络边缘运行的负载均衡器,用于接收传入或传出的 HTTP / TCP 连接。
  • VirtualService: 实际上可以将 Kubernetes 服务连接到 Istio Gateway 上,并且可以执行更多操作,例如,定义一组流量路由规则,以便在主机被寻址时应用。
  • DestinationRule: 决定了经过路由处理之后的流量的访问策略。简单来说,就是定义流量如何路由。这些策略中可以定义负载均衡配置、连接池尺寸及外部检测(用于在负载均衡池中对不健康主机进行识别和驱逐)配置。
  • EnvoyFilter: 描述了针对代理服务的过滤器,这些过滤器可以定制由 Istio Pilot 生成的代理配置。初级用户一般很少用到这个配置。
  • ServiceEntry: 在默认情况下,Istio 服务网格中的服务是无法发现 Mesh 以外的服务的。ServiceEntry 能够在 Istio 内部的服务注册表中加入额外的条目,从而让服务网格中的服务能够访问和路由到这些被手动加入的服务。

什么是 Istio

通过前面的介绍,读者已经对 Service Mesh 已经有了初步的认识。Istio 作为一个开源的 Service Mesh 实现产品,一经推出就备受瞩目,成为各大厂商和开发者争相追捧的对象。因此,Istio 很有可能会成为继 Kubernetes 之后的又一个明星级产品。

Istio 官方文档是这样定义的:

❝“它是一个完全开源的服务网格,以透明的方式构建在现有的分布式应用中。它也是一个平台,拥有可以集成任何日志、遥测和策略系统的 API 接口。Istio 多样化的特性使你能够成功且高效地运行分布式微服务架构,并提供保护、连接和监控微服务的统一方法。”

从官方定义可以看出,Istio 提供了一种完整的解决方案,可以使用统一的方式管理和监测微服务应用。

同时,它具有管理流量、实施访问策略、收集数据等方面的功能,而且所有的这些都对应用透明,几乎不需要修改业务代码就能实现。

有了 Istio,用户几乎可以不再使用其他的微服务框架,也不需要自己去实现服务治理等功能。只要把网络层委托给 Istio,它就能帮用户完成这一系列的功能。

简单来说,Istio 就是一个提供了服务治理功能的服务网格。

为什么使用 Istio

Service Mesh 是一种服务治理技术,其核心功能是对流量进行控制。

从这一点来说,Service Mesh 和现有的服务治理产品在功能上是有重合的。如果一个企业使用的微服务应用已经具有了非常完善的服务治理功能,则不一定非得引入 Service Mesh。

但是,如果企业使用的系统不具有完善的治理功能,或者系统架构中的痛点正好可以被 Service Mesh 解决,则 Service Mesh 是最佳选择。

相对于基于公共库的服务治理产品,Service Mesh 最大的特性就是对应用透明。用户不仅可以将自己的微服务应用无缝地接入网格,而且无须修改业务逻辑。目前 Istio 提供了以下 4 个重要的功能

  • 为 HTTP、gRPC、WebSocket 和 TCP 流量自动负载均衡。
  • 通过丰富的路由规则、重试、故障转移和故障注入对流量行为进行细粒度控制。
  • 提供完善的可观察性方面的功能,包括对所有网格控制下的流量进行自动化度量、日志记录和追踪。
  • 提供身份认证和授权策略,在集群中实现安全的服务间通信。

Istio 的平台支持

Istio 独立于平台,被设计为可以在各种环境中运行,包括跨云、内部环境、Kubernetes 等。目前 Istio 支持的平台有:

  1. 部署在 Kubernetes 集群的服务。
  2. 在 Consul 中注册的服务。
  3. 在独立的虚拟机中运行的服务。

❝本文节选自《深入理解 Istio:云原生服务网格进阶实战》一书,欢迎阅读此书了解更多相关内容!

0 人点赞