第1篇----Istio原理篇
阅读原文时间:2023年07月08日阅读:3

Istio是什么

◎ Istio是一个用于服务治理的开放平台。

◎ Istio是一个Service Mesh形态的用于服务治理的开放平台。

◎ Istio是一个与Kubernetes紧密结合的适用于云原生场景的Service Mesh形态的用于服务治理的开放平台。

这里的关键字“治理”不局限于“微服务治理”的范畴,任何服务,只要服务间有访问,如果需要对服务间的访问进行管理,就可以使用 Istio。根据 Istio 官方的介绍,服务治理涉及连接(Connect)、安全(Secure)、策略执行(Control)和可观察性(Observe).

◎ 连接:Istio 通过集中配置的流量规则控制服务间的流量和调用,实现负载均衡、熔断、故障注入、重试、重定向等服务治理功能。

◎ 安全:Istio 提供透明的认证机制、通道加密、服务访问授权等安全能力,可增强服务访问的安全性。

◎ 策略执行:Istio 通过可动态插拔、可扩展的策略实现访问控制、速率限制、配额管理、服务计费等能力。

◎ 可观察性:动态获取服务运行数据和输出,提供强大的调用链、监控和调用日志收集输出的能力。配合可视化工具,可方便运维人员了解服务的运行状况,发现并解决问题。

简单起见,这里以一个天气预报应用中forecast服务对recommendation服务的访问为例。

这个示例对两个服务的业务代码没有任何要求,可以用任何语言开发。在这个示例中,forecast服务是用Node.js开发的,recommendation服务是用Java开发的。在forecast服务的代码中通过域名访问recommendation服务,在两个服务中都不用包含任何服务访问管理的逻辑。

我们看看Istio在其中都做了什么:

◎ 自动通过服务发现获取recommendation服务实例列表,并根据负载均衡策略选择一个服务实例;

◎ 对服务双方启用双向认证和通道加密;

◎ 如果某个服务实例连续访问出错,则可以将该实例隔离一段时间,以提高访问质量;

◎ 设置最大连接数、最大请求数、访问超时等对服务进行保护;

◎ 限流;

◎ 对请求进行重试;

◎ 修改请求中的内容;

◎ 将一定特征的服务重定向;

◎ 灰度发布;

◎ 自动记录服务访问信息;

◎ 记录调用链,进行分布式追踪;

◎ 根据访问数据形成完整的应用访问拓扑;

◎ ……

所有这些功能,都不需要用户修改代码,用户只需在 Istio 的控制面做些配置即可,并且动态生效。以灰度发现为例,在 Istio 中是通过简单配置实现灰度发布的,其核心工作是实现两个版本同时在线,并通过一定的流量策略将部分流量引到灰度版本上。我们无须修改代码,只要简单写一个配置就可以对任意一个服务进行灰度发布了:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: recommendation
spec:
  hosts:
  - recommendation
  http:
  - match:
    - headers:
        cookie:
          exact: "group=dev"
    route:
    - destination:
        name: v2
  - route:
    - destination:
        name: v1

Istio采用了与Kubernetes类似的语法风格,其功能大意:将 group是 dev的流量转发到 recommendation服务的 v2版本,其他用户还是访问 recommendation服务的 v1版本,从而达到从 v1版本中切分少部分流量到灰度版本 v2的效果。对Istio提供的功能都进行类似配置即可,无须修改代码,无须额外的组件支持,也无须其他前置和后置操作。

Istio与服务治理

Istio是一个服务治理平台,治理的是服务间的访问,只要有访问就可以治理,不在乎这个服务是不是所谓的微服务,也不要求跑在其上的代码是微服务化的。单体应用不满足微服务的若干哲学,用Istio治理也是完全可以的。

Martin Fowler对微服务的描述是“微服务是以一组小型服务来开发单个应用程序的方法,每个服务都运行在自己的进程中,服务间采用轻量级通信机制(通常用 HTTP 资源API)。

但是,微服务化也给开发和运维带来很大的挑战,因为微服务化仅仅是一种分而治之的方法,业务本身的规模和复杂度并没有变少,反而变多。

在分布式系统中,网络可靠性、通信安全、网络时延、网络拓扑变化等都成了我们要关注的内容。另外,微服务机制带来了大量的工作,比如服务如何请求目标服务,需要引入服务发现和负载均衡等,以及对跨进程的分布式调用栈进行分布式调用链追踪,等等。总之,简单的事情突然变得复杂了。

这就需要一些工具集来做一些通用的工作,包括服务注册、服务发现、负载均衡等。

Istio不只解决了微服务问题

微服务作为一种架构风格,说到底是一套方法论;与之对应的 Istio 等服务网格则是一种完整的实践,Istio 更是一款设计良好的具有较好集成及可扩展能力的可落地的服务治理工具和平台。

所以,微服务是一套理论,Istio是一种实践。但是,Istio是用来解决问题的,并不是微服务理论的一种落地,在实际项目中拿着微服务的细节列表来硬套 Istio 的功能,比如要求Istio治理的服务必须实现微服务的服务注册的一些细节,就明显不太适当。

从场景来看,Istio管理的对象大部分是微服务化过的,但这不是必需的要求。对于一个或多个大的单体应用,只要存在服务间的访问要进行治理,Istio也适用。实际上,传统行业的用户业务需要在容器化后进行服务治理,Istio是用户非常喜欢的形态,因为不用因为服务治理而修改代码,只需将业务搬到 Istio 上即可,如果需要将业务微服务化,则可以渐进式进行。

从能力来看,Istio对服务的治理不只包含在微服务中强调的负载均衡、熔断、限流这些一般治理能力,还包含诸多其他能力,例如提供可插拔的服务安全、可扩展的控制策略、服务运行可观察性等更广泛的治理能力。在 Istio 中提供的是用户管理运维服务需要的能力,而不是在微服务教科书中定义的能力。

所以,过多地谈论Istio和微服务的关系,倒不如多关注Istio和Kubernetes的结合关系。

Istio与服务网格

服务网格的特点:

◎ 基础设施:服务网格是一种处理服务间通信的基础设施层。

◎ 云原生:服务网格尤其适用于在云原生场景下帮助应用程序在复杂的服务拓扑间可靠地传递请求。

◎ 网络代理:在实际使用中,服务网格一般是通过一组轻量级网络代理来执行治理逻辑的。

◎ 对应用透明:轻量网络代理与应用程序部署在一起,但应用感知不到代理的存在,还是使用原来的方式工作。

当然,正所谓没有免费的午餐,这种形态在服务的访问链路上多引入的两跳也是不容回避的问题。

从forecast服务到recommendation服务的一个访问必须要经过forecast服务的 Sidecar拦截 Outbound流量执行治理动作;再经过 recommendation服务的 Sidecar拦截Inbound流量,执行治理动作。这就引入两个问题:

◎ 增加了两处延迟和可能的故障点;

◎ 多出来的这两跳对于访问性能、整体可靠性及整个系统的复杂度都带来了新的挑战。

网格提供商提供的方案一般是这样解决的:通过保证转发代理的轻量和高性能降低时延影响,尤其是考虑到后端实际使用的应用程序一般比代理更重,叠加代理并不会明显影响应用的访问性能;另外,对于这些高性能的代理,只要消耗足够的资源总能达到期望的性能,特别是云原生场景下服务的弹性特点使得服务实例的弹性扩展变得非常方便,通过扩展实例数量总是能得到期望的访问性能。

Istio是Kubernetes的好帮手

从场景来看,Kubernetes已经提供了非常强大的应用负载的部署、升级、扩容等运行管理能力。Kubernetes 中的 Service 机制也已经可以做服务注册、服务发现和负载均衡,支持通过服务名访问到服务实例。

从微服务的工具集观点来看,Kubernetes本身是支持微服务的架构,在Pod中部署微服务很合适,也已经解决了微服务的互访互通问题,但对服务间访问的管理如服务的熔断、限流、动态路由、调用链追踪等都不在Kubernetes的能力范围内。那么,如何提供一套从底层的负载部署运行到上层的服务访问治理端到端的解决方案?目前,最完美的答案就是在Kubernetes上叠加Istio这个好帮手。

Kubernetes的Service基于每个节点的Kube-proxy从Kube-apiserver上获取Service和Endpoint 的信息,并将对 Service 的请求经过负载均衡转发到对应的 Endpoint 上。但Kubernetes只提供了4层负载均衡能力,无法基于应用层的信息进行负载均衡,更不会提供应用层的流量管理,在服务运行管理上也只提供了基本的探针机制,并不提供服务访问指标和调用链追踪这种应用的服务运行诊断能力。

Istio复用了Kubernetes Service的定义,在实现上进行了更细粒度的控制。Istio的服务发现就是从 Kube-apiserver中获取 Service和 Endpoint,然后将其转换成 Istio服务模型的 Service 和 ServiceInstance,但是其数据面组件不再是 Kube-proxy,而是在每个 Pod 里部署的 Sidecar,也可以将其看作每个服务实例的 Proxy。这样,Proxy 的粒度就更细了,和服务实例的联系也更紧密了,可以做更多更细粒度的服务治理。通过拦截Pod的Inbound流量和Outbound流量,并在Sidecar上解析各种应用层协议,Istio可以提供真正的应用层治理、监控和安全等能力。

Istio和Kubernetes从设计理念、使用体验、系统架构甚至代码风格等小细节来看,关系都非常紧密,甚至有人认为 Istio 就是 Kubernetes团队开发的 Kubernetes可插拔的增强特性。

Kubernetes是Istio的好基座

Istio最大化地利用了Kubernetes这个基础设施,与之叠加在一起形成了一个更强大的用于进行服务运行和治理的基础设施,并提供了更透明的用户体验。

1.数据面

数据面Sidecar运行在Kubernetes的Pod里,作为一个Proxy和业务容器部署在一起。在服务网格的定义中要求应用程序在运行的时候感知不到Sidecar的存在。而基于Kubernetes的一个 Pod 多个容器的优秀设计使得部署运维对用户透明,用户甚至感知不到部署 Sidecar的过程。用户还是用原有的方式创建负载,通过 Istio 的自动注入服务,可以自动给指定的负载注入Proxy。如果在另一种环境下部署和使用Proxy,则不会有这样的便利。

2.统一服务发现

Istio的服务发现机制非常完美地基于Kubernetes的域名访问机制构建而成,省去了再搭一个类似 Eureka 的注册中心的麻烦,更避免了在 Kubernetes 上运行时服务发现数据不一致的问题。尽管 Istio 强调自己的可扩展性的重要性在于适配各种不同的平台,也可以对接其他服务发现机制,但在实际场景下,通过深入分析 Istio 几个版本的代码和设计,便可以发现其重要的能力都是基于Kubernetes进行构建的。

3.基于Kubernetes CRE描述规则

Istio的所有路由规则和控制策略都是通过 Kubernetes CRD实现的,因此各种规则策略对应的数据也被存储在 Kube-apiserver 中,不需要另外一个单独的 APIServer 和后端的配置管理。所以,可以说Istio的APIServer就是Kubernetes的APIServer,数据也自然地被存在了对应Kubernetes的etcd中。

Istio非常巧妙地应用了Kubernetes这个好基座,基于Kubernetes的已有能力来构建自身功能。Kubernetes里已经有的,绝不再自己搞一套,避免了数据不一致和用户使用体验的问题。

Istio不仅数据面Envoy跑在Kubernetes的Pod里,其控制面也运行在Kubernetes集群中,其控制面组件本身存在的形式也是Kubernetes Deployment和Service,基于Kubernetes扩展和构建。

Istio+Kubernetes的方案与将SDK开发的微服务部署在Kubernetes上的方案的比较

总结

Istio、微服务、容器与Kubernetes的关系