Istio 基本概念
官方定义:它是一个完全开源的服务网格,作为透明的一层接入到现有的分布式 应用中。它也是一个平台,可以与任何日志、遥测和策略系统进行集成。Istio 多样化的特性让你能够成功且高效地运行微服务架构,并提供保护、连接和监控微服务的统一方法。
从官方定义中,抽出几个核心的要点:
- Istio 仍然是服务网格产品
- Istio 拥有服务网格的基本特性,即对应用层是透明的
- Istio 是为微服务架构而服务的
- Istio 核心功能,可以连接、控制、保护、观测微服务系统
Istio是Google、IBM和Lyft联合推出的开源微服务Service Mesh框架,Istio 有个重要的特性,就是它被称为第二代 Service Mesh,在原有的数据平面的基础上,增加了控制平面,为现代的 Service Mesh 的产品定义一个新的形态。
为什么要使用 Istio ?
Istio 主要有两大优势:
- 轻松构建服务网格
- 对应用代码透明,应用代码无需更改
Istio 核心功能
其实 Istio 的核心功能就是 Service Mesh 的核心功能,主要有四个方面
-
流量控制
这也是作为一个Service Mesh产品最重要的功能,主要包括:- 路由:我们经常听到像灰度发布、蓝绿部署、AB测试,这些都可以把它归纳到路由这一点上。
- 流量转移
- 弹性:对网络增加一些弹性的能力,比如说超时、重试、熔断等机制
- 测试:Istio 提供一些调试网格的特性,比如说故障注入、流量镜像等功能
-
安全
Istio 对授权和认证两个方面提供一些安全机制 -
可观察性
在这一点Istio是按照比较经典的可观测性的三方面提供的功能,分别是指标、日志、分布式追踪 -
策略
Istio 在最新的 1.5 版本中,把这个功能去掉了,原因是废弃了负责功能的一个模块 Mixer ,它把一些功能转移到 Envoy 里面,后续策略相关的功能应该也会逐渐发布出来
Istio 会称为下一个 Kubernetes 吗?
Istio 的出现实际上重新定义了微服务的开发方式,让你可以轻松的在你的微服务架构中植入 Service Mesh 技术,另外它可以大幅的降低微服务应用开发门槛,让你只关注业务本身,第三点它用了统一的运维和开发方式来简化微服务的开发流程。
对于 Google 和 IBM 公司来说,Istio 它是一个战略性的产品,从这张图上,可以看到在容器层面 Google 已经有 Kubernetes ,在通讯层面有 gRPC这样的协议,而微服务层面,Google 打算用 Istio 来占领市场,这三个方面组成 Google 的云原生战略。
Istio 重大架构变更
架构1.0版本
这个版本架构包括两部分内容
-
数据平面
数据平面就是 Envoy 这些 Sidecar 代理的一个集合 -
控制平面
控制平面主要包括三个组件:-
Pilot:简单的理解为配置分发的组件,会把运维人员配置的路由信息转变成数据平面可以识别的配置项,然后分发给所有的Sidecar代理
-
Citadel:负责安全相关的功能,比如说授权认证等
-
Mixer:主要有两部分功能,
- 一个是遥测,也就是从数据平面进行指标数据的收集
- 另外一部分功能就是设置一些策略,比如限流、黑白名单等。Mixer 这个组件实际上内部是一个插件模型,可以扩展不同的后端基础设施,并添加到这个模型中。为 Istio 架构带来了很大的扩展性,但是这个组件存在一下两个主要问题:
- 第一个是性能,它需要和数据平面进行两次通讯,而这个组件又是单独部署的,是一个进程外的组件,所以每次请求都需要和进程外进行通讯,降低了请求效率。
- 第二个问题是 Mixer的插件模型虽然带来了足够好的扩展性,但是也产生了耦合,比如要添加新插件或者升级已有的插件,不得不去重新部署 Mixer
-
由于 1.0版本 Mixer 组件的两点问题,Istio 发布了 1.1版本
架构 1.1 版本
这个版本的架构主旋律就是解耦,主要做了两个变化:
-
第一个变化,主要是为 Mixer 增加一个进程外的 Adapter 这样概念,也就是把原来集成在组件内部的插件变成一个进程外的适配器,这样在适配器增加或者修改的时候无需对Mixer组件本身进行修改
-
第二个变化,增加了 Galley 这样一个组件,这个组件是 Istio 的配置验证、提取处理和分发的组件,本来这些功能是由 Pilot 组件完成的,但是导致 Pilot 和底层的平台(比如说 Kubernetes)有了耦合,所以增加 Galley 组件分担 Pilot 的功能,让 Pilot 能从底层平台中隔离出来
架构 1.1 版本问题
第一个问题就是性能,1.1版本架构对 Mixer 组件进行了重构,将原来的插件模型拆分成独立的进程外运行的适配器,这样更加重了组件的性能问题,原本已经需要和数据平面的 Sidecar 代理进行多次的通讯了,而此时又需要和这些Adapter再次进行远程交互,性能只会变得更加糟糕。
第二个问题是易用性也不好,这些组件都要单独部署,都有自己单独的进程运行,在安装、维护、升级都带来了复杂性
架构 1.5 版本
1.5版本最重要的一点就是重建了控制平面,将原本的那些组件全部整个一个叫 Istiod 的单体模型,另外它还废弃了 Mixer 组件
从这个图中可以看见 Istio 架构比之前简单很多,当然这个版本除了做减法,也增加了一些新的特性,修复BUG,提升性能。
Istio 流量控制
流量控制,顾名思义就是对流量请求进行控制和管理,Istio提供的流量控制能力非常强大,除了最基本的服务发现、负载均衡之外,还有以下四种功能:
- 路由、流量转移,我们知道的蓝绿部署,灰度发布都是由它演变的
- 可以用API网关对流量进出进行管理
- 提供网络弹性能力,比如超时重试以及熔断
- 支持对网络流量进行调试,比如说引入故障注入和流量镜像功能
Istio 的流量控制能力主要由“虚拟服务、目标规则、网关、服务入口、Sidecar” 这些资源实现。
虚拟服务(Virtual Service)
虚拟服务是实现路由功能的重要组件,它主要的功能是把请求的流量路由到指定的目标地址,它可以做到把请求地址和真实的工作负载进行解耦,本质上讲,它实际就是一组路由规则。
这张图上展示了一个虚拟服务,它里面定义了两个不同的路由规则,规则1会把请求指向目标地址A,规则2会把请求指向目标地址B,虚拟服务一般会和目标规则成对出现。它提供了非常丰富的路由匹配规则,比如说可以针对Endpoint, 针对 Url,针对 Header 这样不同粒度的路由进行匹配。
目标规则(Destination Rule)
目标规则定义了虚拟服务里面配置的具体的目标地址,在它的配置中是以子集存在的,也就是每一个子集里会配置一个对应的目标地址。
上图中上半部分是虚拟服务,而下边虚线框内表示的是具体的目标规则。在目标地址A中定义了两个子集(A1,A2),目标地址B中定义了另外两个子集(B1,B2)。除了定义这些子集,它还可以对负载均衡策略进行修改,默认情况下,是以轮询的方式进行负载均衡的。可以在这里配置使用随机、权重、最少请求数等方式进行负载均衡。
网关(Gateway)
虚拟服务和目标地址两个组件主要是用来管理网格内部流量,而网关是用来管理网格以外的流量。 Istio 内部定义的 Gateway 存在于整个网格的边界,用来管理进出网格的流量。
上面这张图中有两个网关,其中负责管理入流量的网关叫 Ingress(左边),管理出流量的网关叫 Egress(右边),Egress 网关并不是必选项,可以不用它,内部服务的流量可以直接指向外部服务。
为什么要用网关呢? 我们可以用网关来管理网格外部的流量,比如说为进出的流量增加负载均衡的能力,增加超时重试的能力。
Istio 内部预定义了两个网关,分别是 Ingress Gateway 和 Egress Gateway。也可以自己实现自定义的 Gateway 。
服务入口(Service Entry)
服务入口和前面几个资源又不同,前面几个资源主要是面向流量的。而这个资源面向的是服务,它主要的功能是把外部的服务注册到网格内。这样就可以像管理网格内部的服务一样去管理外部服务。
主要功能有三点:
- 首先它可以为外部的目标转发请求
- 第二它可以添加超时重试这些策略
- 第三就是可以扩展网格
举一个例子,假设你的服务部署在不同的集群中,那么可以通过定义服务入口的方式把这几个不同的集群集中起来,共同用同一个网格进行管理
Sidecar
Sidecar 和前面几个资源又不同,Sidecar是对流量进行一个全局的控制,而前几个资源主要是做一些细微度的控制。
Sidecar 主要有以下两个功能:
-
调整 Envoy 代理接管的端口和协议,默认情况下 Envoy 是接管所有发送到服务的请求的,而通过 Sidecar 可以调整接管流量的范围。比如说上面图上左边显示的只去监听来自于端口9080的 HTTP 协议。
-
限制 Envoy 代理可访问的服务,默认情况下 Envoy 是可以访问整个网格内的所有的服务,假设可以像图中右边所示,让它只访问服务A而切断它对服务B的访问权限
Istio 提供网格的弹性能力和测试能力
常见的弹性能力:
- 超时
- 重试
- 熔断
常见的测试能力
-
故障注入,也就是说它可以故意的给服务植入一些故障,主要有两个:一个是增加服务的延迟,另外一个是让服务直接中断,通过这样的方式可以模拟服务出现问题时,整个应用是如何处理的
-
流量镜像,开发都知道,很难在本地的开发环境中去模拟线上环境,经常出现在本地测试没有问题,部署到线上就会出现问题,这是因为环境不同以及流量不同,而流量镜像这个功能可以完全的把生产环境的流量,镜像一份然后发送到你的镜像服务中,这样就可以在镜像服务中来调试线上环境了。
Istio 服务可观察性
服务可观察性是近两年题出的一个比较新的概念,云原生基金会也是在18年的时候才把可观察性作为自己蓝图中的一个板块,可观察性并不等于监控,它们还是有很大的区别的。
监控指的是从运维人员的角度去审视系统的行为、状态,它是一个被动方式,是从系统之外去探究系统的运行状态。
而可观察性是指从开发人员的角度主动的去探究系统的运行情况,对于开发人员来说,需要考虑把哪些系统的指标暴露出去,以前主要是通过日志查看系统运行情况。
因此可观察性可以说是一种理念上的创新,一般情况把可观察性分为指标、日志收集和分布式追踪
指标(Metrics)
它指的是以聚合数据的方式来监控和理解系统行为。
举个例子,我们可以在系统运行过程中在一些时间点上做一些记录,然后把这些生成的数据统一起来,最后就能以一个趋势图的方式来展示系统在这段时间中运行的状态。
Istio 中的指标分类:
-
代理级别的指标(Proxy-level)
顾名思义就是用来收集 Sidecar 代理上的一些数据,Sidecar 代理会接管所有来自于服务的请求,因此有很多丰富的数据供我们收集,除此之外,可以指定让某一个或者某几个 Sidecar 进行指标的收集(针对性的调试)举个例子,上图中第一个指标是当前集群中来自上游服务的总的请求数,第二个的指标是上游服务的完成请求数量,第三个是SSL连接出错的数量。
-
服务级别的指标(Service-level)
主要是用来收集服务本身的一些信息,用于监控服务通信
主要是根据服务的四个最基本的监控需求(延迟、流量、错误、饱和)来进行收集的
默认情况下,这些指标数据会导出到 Prometheus(可自定义和更改)
服务级别的指标不一定必须输出,可以根据情况进行开启或者关闭下图举个例子
-
控制平面指标(Control plane) 可以通过收集控制平面指标来监控 Istio 本身的运行状况,这样就可以了解到整个网格的健康情况。
图中显示的是 Istio 官方文档提供的一些控制平面指标
访问日志
指标是通过聚合的数据来监测应用运行情况,而日志指的是通过系统产生的事件来监测应用。
Istio 里面提供了访问日志,包括非常完整的远数据信息,比如说请求来源以及目标地址。同时还可以对日志产生的位置进行设置(可以保存在本地,也可以直接导入远程的三方工具里面)
一般来说日志内容主要包括两部分
一部分是应用本身的日志,就是开发时自己输出的一些Log;另外一方面还可以查看 Envoy 产生的信息,它会对请求产生的数据进行一个详细的记录,查看的方式是直接通过 kubectl 的logs命令对 Envoy 的 Container 进行查看:$ kubectl logs -l app=demo -c istio-proxy
分布式追踪(Distributed tracing)
分布式追踪通过追踪请求来了解服务之间的调用关系,服务追踪主要用于问题的排查以及性能分析方面
在左边图中是没有使用分布式追踪的应用,当第一个节点出现问题时候,你不知道具体问题出现在哪个服务中,因为没有办法去追踪它,只能通过不停的尝试来发现问题所在。
而在右边图中使用了分布式追踪的一个系统,一旦你第一个节点出现问题,可以通过分布式追踪系统很快的发现在调用链上哪个节点出现问题。
这幅图是分布式追踪的案例,可以从左边这部分看到整个服务的调用关系,以及整个服务执行完需要的时间,每一个调用耗费多少时间都非常清楚,一旦某个节点出现问题,可以很容易发现它的异常情况。
Istio 的安全架构
Istio 中的安全主要分为 认证 和 授权 两大部分,绝大部分功能都是由 Istiod 这个控制平面(Control plane)来实现的
看一下这幅图,在 Istiod 中 CA(Certificate Authority ) 主要是用来负责证书的管理,认证策略和授权策略都会被存储在对应的模块中,由API Server 将这些策略变成配置,下发到对应的数据平面中。当一个终端用户调用网格内的服务的时候,它可以使用 JWT 方式进行认证。而网格内服务与服务之间(例如 ServiceA 和 ServiceB)可以使用双向 TLS 进行认证
认证
Istio 中的认证主要包括两种,一种是对等认证,一种是请求认证。另外认证策略会被保存在配置存储中,然后下发给数据平面。
看一下上图,管理员(Administrators)配置了两种策略,一种是针对 Foo 这个 Namespace, 它的目标是全体服务,而另一种策略是针对 Bar 这个Namespace, 它的目标是 Workload X,这些策略会被转变成具体的配置信息,然后由 Istiod 下发给具体的 Sidecar 代理,值得一提的是,Istio 在认证中提供了一种兼容模式,即可以加密和不加密的方式同时进行请求的传输,这样为了我们进行安全设置方面的调试带来了很大的便利性,比如说当想要增加 mTLS 这样的认证策略的时候,可以先用纯文本方式测试服务之间的连通性,然后再把这个策略加上去。
Istio 中的认证主要包括两种,
-
对等认证,也就是平时所说的传输身份认证,它主要的功能用于服务与服务之间的身份认证,目前 Istio 支持以 mTLS(Mutual TLS) 这样的方式进行认证
-
请求认证,也就是通常所说的终端用户认证,它主要用于给终端用户访问我们的服务进行认证的,目前 Istio 支持的是 JWT(JSON Web Token)认证方式
认证策略配置
配置认证策略,对于不同的认证方式,需要建立对应的 CRD,比如说要配置一个对等认证, 就需要构建一个 PeerAuthentication 这样一个 CRD。
同时需要指定生效范围,认证配置的生效范围主要由三点,
第一点在全网格内生效;
第二点在当前命名空间生效,比如下面例子中,指定在 foo 这个命名空间生效;
另外还可以进一步指定具体工作负载(服务),比如下面例子,在当前配置中,指定了一个选择器,这样的话配置就会只针对标签为 reviews 这样的服务来生效。
具体的策略是 mtls 指定,它的模式是 STRICT (严格模式),也可以改成兼容模式
策略改变:一旦策略发生更新,Istio 几乎会实时的将这些策略推送到具体的数据平面中,但是 Istio 不能保证同时更新所有的数据平面,那么这个时候就需要注意避免策略更新的中断,一般情况下推荐两种方式:
如果是对等认证,需要设置 MTLS 时最好使用兼容模式,等调试完成后,再使用严格模式。
如果时身份认证,可以把新旧两个JWT同时配置进策略当中,当请求全部迁移到新的JWT里面,再把旧的删除就可以了
授权
授权级别和认证类型也分为三个级别,分别时针对网格,针对命名空间,以及服务本身进行授权,它的工作方式和认证也很类似。
我们看下面这张图,当管理员增加一个授权策略的时候,API server 会把策略转换成对应的配置,然后下发给对应的数据平面的 Sidecar ,每个 Sidecar 会运行一个授权引擎,该引擎在运行的时候进行授权请求,如果请求到达代理时,授权引擎根据当前的策略,评估请求的上下文,并返回授权结果。
授权在默认情况下无需显式的启动,默认就是启动状态
授权策略配置
配置授权策略需要通过创建一个 AuthorizationPolicy 的CRD 来实现,这个CRD主要有以下组成部分:
-
选择器(Selector),跟认证的配置类型,是为了用来指定授权级别的。
-
行为(Action),也就是 action 也可以配置允许或者拒绝两种行为
-
规则列表(Rules),规则列表里面包含三部分内容
-
来源(from)
-
具体操作(to)
-
具体匹配条件(when)
-
如下图,当前授权策略是指容许下面两个来源的请求访问 http 服务并且需要让它们带有下面配置的 JWT Token
授权策略的设置方式也很多,首先可以对范围进行设置,主要是通过 metadata里面的namespace字段,以及 selector 字段,来指定具体的服务。而值的匹配,也支持精确匹配、模糊匹配、前缀和后缀匹配,比如下面的例子就是 paths: ["/test/*","*/info"] 就是后缀以及前缀方式匹配
另外还可以设置全部允许和全部拒绝这样的策略,下面这个例子显示了全部容许,设置方式很简单,只要在 rules 设置一个空 就可以了
还可以添加自定义条件,比如说这个例子添加一个 request.headers 这样的条件,当 headers 的值包括 v1 或者是 v2的时候,匹配条件就会生效