云原生社区最新力作 —— 《深入理解 Istio》出版发售
❝云原生实验室和电子工业出版社将为大家送出 5 本《深入理解 Istio:云原生服务网格进阶实战》。关注本公众号参与抽奖即可获取。
听说过服务网格并试用过 Istio 的人可能都会有以下 5 个疑问:
❝本文将带读者梳理清楚 Kubernetes、xDS 协议与 Istio 服务网格之间的内在联系。此外,本文还将介绍 Kubernetes 中的负载均衡方式,xDS 协议对于服务网格的意义,以及为什么说即使有了 Kubernetes 还需要 Istio。
使用服务网格并非与 Kubernetes 决裂,而是水到渠成的事情。Kubernetes 的本质是通过声明配置对应用进行生命周期管理,而服务网格的本质是提供应用间的流量和安全性管理,以及可观察性。假如已经使用 Kubernetes 构建了稳定的微服务平台,那么如何设置服务间调用的负载均衡和流量控制?
Envoy 创造的 xDS 协议被众多开源软件所支持,如 Istio、Linkerd、MOSN 等。Envoy 对服务网格或云原生而言最大的贡献就是定义了 xDS。Envoy 本质上是一个网络代理,是通过 API 配置的现代版代理,基于它衍生出了很多不同的使用场景,如 API 网关、服务网格中的 Sidecar 代理和边缘代理。
如果想要提前了解下文的所有内容,则可以先阅读下面列出的一些主要观点。
图 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 一层抽离出来,做更多的扩展。
在 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 代理模式。
首先,如果转发的 Pod 不能正常提供服务,那么它不会自动尝试另一个 Pod,不过这个问题可以通过 liveness probes 解决。每个 Pod 都有一个健康检查机制,当 Pod 健康状况有问题时,kube-proxy 会删除对应的转发规则。另外,nodePort 类型的服务也无法添加 TLS,或者更复杂的报文路由机制。
kube-proxy 实现了流量在 Kubernetes 服务中多个 Pod 实例间的负载均衡,但是如何对这些服务间的流量做细粒度的控制,比如,将流量按照百分比划分到不同的应用版本(这些应用版本都属于同一个服务的一部分,但位于不同的部署上),做金丝雀发布(灰度发布)和蓝绿发布?Kubernetes 社区给出了使用 Deployment 做金丝雀发布的方法,该方法本质上就是通过修改 Pod 的 label 将不同的 Pod 划归到 Deployment 的 service 上。
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 官方网站。
图 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 种。
Istio 使用 gRPC 流式订阅的方式配置所有的数据平面的 Sidecar Proxy。下面总结关于 xDS 协议的要点。
Envoy 是 Istio 服务网格中默认的 Sidecar,Istio 在 Envoy 的基础上按照 Envoy 的 xDS 协议扩展了其控制平面。在讲解 Envoy xDS 协议之前还需要先熟悉下 Envoy 的基本术语。下面列举了 Envoy 中的基本术语及其数据结构解析。
Envoy 中可以设置多个 Listener,每个 Listener 中又可以设置 filterchain(过滤器链表),而且过滤器是可扩展的,这样就可以更方便地操作流量了,例如,设置加密、私有 RPC 等。
xDS 协议是由 Envoy 提出的,目前是 Istio 中默认的 Sidecar 代理。但是,只要实现了 xDS 协议,理论上就可以作为 Istio 中的 Sidecar 代理,例如,蚂蚁集团开源的 MOSN。
Istio 是一个功能十分丰富的 Service Mesh 实现产品,包括如下功能。
Istio 中定义了如下的 CRD 来帮助用户进行流量管理。
通过前面的介绍,读者已经对 Service Mesh 已经有了初步的认识。Istio 作为一个开源的 Service Mesh 实现产品,一经推出就备受瞩目,成为各大厂商和开发者争相追捧的对象。因此,Istio 很有可能会成为继 Kubernetes 之后的又一个明星级产品。
Istio 官方文档是这样定义的:
❝“它是一个完全开源的服务网格,以透明的方式构建在现有的分布式应用中。它也是一个平台,拥有可以集成任何日志、遥测和策略系统的 API 接口。Istio 多样化的特性使你能够成功且高效地运行分布式微服务架构,并提供保护、连接和监控微服务的统一方法。”
从官方定义可以看出,Istio 提供了一种完整的解决方案,可以使用统一的方式管理和监测微服务应用。
同时,它具有管理流量、实施访问策略、收集数据等方面的功能,而且所有的这些都对应用透明,几乎不需要修改业务代码就能实现。
有了 Istio,用户几乎可以不再使用其他的微服务框架,也不需要自己去实现服务治理等功能。只要把网络层委托给 Istio,它就能帮用户完成这一系列的功能。
简单来说,Istio 就是一个提供了服务治理功能的服务网格。
Service Mesh 是一种服务治理技术,其核心功能是对流量进行控制。
从这一点来说,Service Mesh 和现有的服务治理产品在功能上是有重合的。如果一个企业使用的微服务应用已经具有了非常完善的服务治理功能,则不一定非得引入 Service Mesh。
但是,如果企业使用的系统不具有完善的治理功能,或者系统架构中的痛点正好可以被 Service Mesh 解决,则 Service Mesh 是最佳选择。
相对于基于公共库的服务治理产品,Service Mesh 最大的特性就是对应用透明。用户不仅可以将自己的微服务应用无缝地接入网格,而且无须修改业务逻辑。目前 Istio 提供了以下 4 个重要的功能。
Istio 独立于平台,被设计为可以在各种环境中运行,包括跨云、内部环境、Kubernetes 等。目前 Istio 支持的平台有:
❝本文节选自《深入理解 Istio:云原生服务网格进阶实战》一书,欢迎阅读此书了解更多相关内容!