总结:服务网格(Service Mesh)

一、介绍

服务网格(Service Mesh)是一个专门处理服务通讯的基础设施层。它的职责是在由云原生应用组成服务的复杂拓扑结构下进行可靠的请求传送。在实践中,它是一组和应用服务部署在一起的轻量级的网络代理,并且对应用服务透明。

服务网格从总体架构上来讲比较简单,不过是一堆紧挨着各项服务的用户代理,外加一组任务管理组件组成。

管理组件被称为控制层或控制平面(control plane),负责与控制平面中的代理通信,下发策略和配置。

代理在服务网格中被称为数据层或数据平面(data plane),直接处理入站和出站数据包,转发、路由、健康检查、负载均衡、认证、鉴权、产生监控数据等。

一个典型的服务网格部署网络结构图如下:

总结:服务网格(Service Mesh)_第1张图片

其中绿色方块为应用服务,蓝色方块为 Sidecar Proxy,应用服务之间通过 Sidecar Proxy 进行通信,整个服务通信形成图中的蓝色网络连线,图中所有蓝色部分就形成了 Service Mesh。

二、服务网格带来了什么变化?

  • 第一,微服务治理与业务逻辑的解耦。服务网格把 SDK 中的大部分能力从应用中剥离出来,拆解为独立进程,以 sidecar 的模式进行部署。服务网格通过将服务通信及相关管控功能从业务程序中分离并下沉到基础设施层,使其和业务系统完全解耦,使开发人员更加专注于业务本身。
  • 第二,异构系统的统一治理。随着新技术的发展和人员更替,在同一家公司中往往会出现不同语言、不同框架的应用和服务,为了能够统一管控这些服务,以往的做法是为每种语言、每种框架都开发一套完整的 SDK,维护成本非常之高,而且给公司的中间件团队带来了很大的挑战。有了服务网格之后,通过将主体的服务治理能力下沉到基础设施,多语言的支持就轻松很多了。只需要提供一个非常轻量级的 SDK,甚至很多情况下都不需要一个单独的 SDK,就可以方便地实现多语言、多协议的统一流量管控、监控等需求。

三、Istio介绍

Istio - 服务网格的典型实现。

Istio 是一个由Google和IBM等公司开源的,功能十分丰富的服务网格具体实现,也是目前业界最为流行的实现。它包括如下功能:

  • 流量管理:提供统一的流量治理功能,包括失败重试、超时、熔断/限流、路由管理、灰度发布、网关等功能。
  • 可观测性:透明化地实现指标监控、日志、链路追踪等功能。
  • 策略控制:实现访问控制系统、遥测捕获、配额管理和计费等。
  • 安全认证:无侵入式地为服务增加认证、鉴权和加密通信的能力。
  • 故障注入:支持随机向服务通信中注入故障(如模拟延时/网络中断),检测服务的可靠性

四、Istio架构

Istio 的架构从逻辑上分成数据平面(Data Plane)和控制平面(Control Plane)。

是否觉得似曾相识?没错,Kubernetes 的架构也具有相似的结构,分为控制节点和计算节点。毫无疑问,这样的设计可以很好地解耦各个功能组件。

  • 数据平面:由一组和业务服务成对出现的 Sidecar 代理(Envoy)构成,它的主要功能是接管服务的进出流量,传递并控制服务和 Mixer 组件的所有网络通信(Mixer 是一个策略和遥测数据的收集器,稍后会介绍)。
  • 控制平面:主要包括了 Pilot、Mixer、Citadel 和 Galley 共 4 个组件,主要功能是通过配置和管理 Sidecar 代理来进行流量控制,并配置 Mixer 去执行策略和收集遥测数据(Telemetry)。

Istio的架构图如下:

总结:服务网格(Service Mesh)_第2张图片

架构补充:

总结:服务网格(Service Mesh)_第3张图片

五、Istio模块介绍

Istio 的核心控件Envoy

从上面的架构图可以看出,Istio 的数据平面就是指代理。Istio 选择 Envoy 作为 Sidecar 代理,Envoy 本质上是一个为面向服务的架构而设计的 7 层代理和通信总线。Envoy 基于 C++ 11 开发而成,性能出色。除了具有强大的网络控制能力外,Envoy 还可以将流量行为和数据提取出来发送给 Mixer 组件,用以进行监控。

Envoy 在网络控制方面的主要功能如下。

  • HTTP 7 层路由
  • 支持 gRPC、HTTP/2
  • 服务发现和动态配置
  • 健康检查
  • 高级负载均衡

我们知道,在Kubernetes环境中,同一个Pod内的不同容器间共享网络栈,这一特性使得Sidecar可以接管进出这些容器的网络流量,这就是Sidecar模式的实现基础。Envoy是目前Istio默认的数据平面,实际上因为Istio灵活的架构,完全可以选择其他兼容的产品作为Sidecar。目前很多服务网格产品都可以作为Istio的数据平面并提供集成。

Pilot

Pilot 是 Istio 实现流量管理的核心组件,它主要的作用是配置和管理 Envoy 代理。比如:可以为代理之间设置特定的流量规则,或者配置超时、重试、熔断这样的弹性能力。Pilot 会将控制流量行为的路由规则转换为 Envoy 的配置,并在运行时将它们广播到 Envoy。另外,Pilot 还能够把服务发现机制抽象出来并转换成 API 分发给 Envoy,使得后者具有服务发现的能力。

简单来说,Pilot 的主要任务有两个。

  • 从平台(如:Kubernetes)获取服务信息,完成服务发现
  • 获取 Istio 的各项配置,转换成 Envoy 代理可读的格式并分发
    • 注意:这块是经典的解耦设计,这样有个好处,即以后如果有其他类型的配置格式,也可以转换为Envoy可读的配置。试想下,如果由Envoy直接读取配置,后期接入其他格式的配置则需要修改Envoy代码,而Pilot的出现,则只要修改Pilot端代码就可以了。Pilot层不涉及到业务逻辑层,而是作为一个平台适配器,保障了其他核心组件配置规则的一致性,从而避免其它代码的反复修改
    • 总结:服务网格(Service Mesh)_第4张图片

Mixer

Mixer 的主要功能是提供策略控制,并从 Envoy 代理收集遥测数据。

每次网络通信时 Envoy 代理都会向 Mixer 发出预检要求,用来检测调用者的合法性。调用之后 Envoy 代理会发送遥测数据供 Mixer 收集。一般情况下 Sidecar 代理可以缓存这些数据,不需要频繁地调用 Mixer。

适配器是 Mixer 的重要组成部分,它本质上是一个插件模型,每个插件叫作适配器。这项特性使得 Mixer 可以接入几乎任意的(只要定义好接口)后端基础设施。比如可以选择接入不同的日志收集器、监控工具和授权工具等;可以在运行时切换不同的适配器或者是打开(关闭)它们;还可以自定义适配器以满足特定需求。适配器极大地提高了 Mixer 的扩展性,它让 Istio 的功能拥有了更多可能性。下图展示了 Mixer 的架构图并展示了它和 Envoy 的交互方式。

总结:服务网格(Service Mesh)_第5张图片

Citadel

Citadel 是与安全相关的组件,主要负责密钥和证书的管理。它可以提供服务间和终端用户的身份认证,还可以加密服务网格中的流量。

Galley

在 2019 年 3 月份发布的 1.1 版本中,Galley 作为一个独立的组件被添加到了架构当中(在此之前的版本中 Galley 并未独立出现),它现在是 Istio 主要的配置管理组件,负责配置的获取、处理和分发。Galley 使用了一种叫作 MCP(Mesh Configuration Protocol,网格配置协议)的协议与其他组件进行通信。

六、Istio之流量管理

微服务应用最大的痛点就是处理服务间的通信,而这一问题的核心其实就是流量管理。首先来看一看传统的微服务应用在没有服务网格介入的情况下,如何完成诸如金丝雀发布这样的动态路由。假设不借助任何现成的第三方框架,一个简单的实现方法是,在服务间添加一个负载均衡(如Nginx)做代理,通过修改配置的权重来分配流量。这种方式将对流量的管理和基础设施(云服务器、虚拟机、实体机等)绑定在了一起,难以维护。

而使用 Istio 就可以轻松地实现各种维度的流量控制。

下图展示了两种不同的金丝雀发布策略(新版本只对少数终端用户可用)。

第一种是根据权重把 5% 的流量路由给新版本;

第二种是根据请求的头信息 User-Agent 把使用 iPhone 的用户流量路由到新版本。

插曲:什么是金丝雀版本?金丝雀canary版本是一种软件技术版本,通过使新版本只对少数终端用户可用,这样可降低向每个人推出新代码和功能的风险。由于用户组的规模较小,新版本的影响相对较小。如果确定bug存在,或者新的功能或新的设计没有被很好地接受,那么很容易回滚。

总结:服务网格(Service Mesh)_第6张图片

Istio 的流量管理是通过 Pilot 和 Envoy 这两个组件实现的,将流量和基础设施进行了解耦。Pilot 负责配置规则,并把规则分发到 Envoy 代理去实施;而 Envoy 按照规则执行各种流量管理的功能,比如动态请求路由,超时、重试和熔断,还可以通过故障注入来测试服务之间的容错能力。下面对这些具体的功能进行逐一介绍。

1、请求路由

Istio 为了控制服务请求,引入了服务版本(Version)的概念,可以通过版本这一标签将服务进行区分。版本的设置是非常灵活的,可以根据服务的迭代编号进行定义(如 v1、v2 版本);也可以根据部署环境进行定义(如 Dev、Staging 和 Production);或者是自定义任何用于区分服务的标记。通过版本标签,Istio 就可以定义灵活的路由规则以控制流量,上面提到的金丝雀发布这类应用场景就很容易实现了。

下图展示了使用服务版本实现路由分配的例子。服务版本定义了版本号(v1.5、v2.0-alpha)和环境(us-prod、us-staging)两种信息。服务 B 包含了 4 个Pod,其中 3 个是部署在生产环境的 v1.5 版本,而 Pod4 是部署在预生产环境的 v2.0-alpha 版本。运维人员根据服务版本指定路由规则,通过 Pilot 同步给 Envoy 代理,使得 99% 的流量流向 v1.5 版本的生产环境,而 1% 的流量进入 v2.0-alpha 版本的预生产环境。

总结:服务网格(Service Mesh)_第7张图片

2、入口网关(Ingress)和出口网关(Egress)

服务间通信是通过 Envoy 代理进行的。同样,我们也可以在整个系统的入口和出口处部署代理,使得所有流入和流出的流量都由代理进行转发,而这两个负责入口和出口的代理就叫作入口网关和出口网关。它们相当于整个微服务应用的边界代理,把守着进入和流出服务网格的流量。下图展示了 Ingress 和 Egress 在请求流中的位置,通过设置 Envoy 代理,出入服务网格的流量也得到了控制。

总结:服务网格(Service Mesh)_第8张图片

3、服务发现和负载均衡

服务发现的前提条件是具有服务注册的能力。目前 Kubernetes 这类容器编排平台也提供了服务注册的能力。Istio 基于平台实现服务发现和负载均衡时,需要通过 Pilot 和 Envoy 协作完成,如下图所示。Pilot 组件会从平台获取服务的注册信息,并提供服务发现的接口,Envoy 获得这些信息并更新到自己的负载均衡池。Envoy 会定期地对池中的实例进行健康检查,剔除离线的实例,保证服务信息的实时性。

总结:服务网格(Service Mesh)_第9张图片

七、Istio之故障处理

Istio 的故障处理都由 Envoy 代理完成。Envoy 提供了一整套现成的故障处理机制,比如超时、重试、限流和熔断等。这些功能都能够以规则的形式进行动态配置,并且执行运行时修改。这使得服务具有更好的容错能力和弹性,并保证服务的稳定性。

八、Istio之故障注入

简单来说,故障注入就是在系统中人为地设置一些故障,来测试系统的稳定性和系统恢复的能力。

比如为某服务设置一个延迟,使其长时间无响应,然后检测调用方是否能处理这种超时问题而自身不受影响(如及时终止对故障发生方的调用,避免自己受到影响且使故障扩展)。

故障注入怎么实现的?也很简单,比如延迟,不是真的去让服务组件故障延迟,而是在获取到服务组件的数据之后,在Envoy端进行延迟。

Isito 支持注入两种类型的故障:延迟和中断

延迟是模拟网络延迟或服务过载的情况;

中断是模拟上游服务崩溃的情况,表现为 HTTP 的错误码和 TCP 连接失败。

九、策略和遥测

  1. 策略

在微服务应用中,除了流量管理以外,常常还需要进行一些额外的控制,比如限流(对调用频率、速率进行限制)、设置白名单和黑名单等。

Istio 中的策略控制是依靠 Mixer 完成的。Envoy 代理在每次网络请求时,都会调用 Mixer 进行预先检查,确定是否满足对应的策略。同时,Mixer 又可以根据这些来自流量的数据,进行指标数据的采集和汇总,这就是遥测功能。

  1. 遥测(Telemetry)

遥测是工业上常用的一种技术,它是指从远程设备中收集数据,并传输到接收设备进行监测。在软件开发中,遥测的含义引申为对各种指标(metric)数据进行收集,并监控、分析这些指标,比如我们经常听到的 BI 数据分析。

Mixer 的一大主要功能就是遥测。前面已经说过,Envoy 代理会发送数据给 Mixer,这就使得 Mixer 具有了数据收集的能力。在对 Mixer 的介绍中读者已经了解到 Mixer 的插件模型,也就是适配器。Mixer 可以接入不同的后端设施作为适配器,来处理收集到的指标数据,比如:日志分析系统、监控系统等。

十、可视化

在微服务应用越来越复杂的情况下,对整个系统的状态进行监控和追踪变得尤为重要。试想如果一个包含上百个服务的系统发生了故障却无法准确定位问题的根源,或者系统压力已经到了承受的临界值而运维人员却浑然不知,这是多么可怕的事情。没有完备的、可观察的监控系统就无法保障系统的稳定性。

Istio 可以很方便地和各种监控、追踪工具集成,以便我们以可视化的方式(网页)直观地查看整个系统的运行状态。比如:可以集成 Prometheus 来进行指标数据的收集,然后将收集的数据放在 Grafana 监控工具中展示;还可以集成 Jaeger 作为追踪系统,帮助我们对请求的调用链进行跟踪,在故障发生时分析出现问题的根源;或者将请求日志记录到 Kibana 系统,以图表的方式进行数据分析。

以上提到的这些可视化工具都会在集成到 Istio 中得到详细的介绍。

十一、VirtualService路由规则配置

virtualService是istio最主要最复杂的核心配置,主要负责配置服务的调用规则,分发规则等等,在详细介绍vs功能之前,可以先查看以下的简化配置内容

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
    - reviews
  http:
  - match:
    - headers:
        end-user:
          exact: jason
    route:
    - destination:
        host: reviews
        subset: v2
  - route:
    - destination:
        host: reviews
        subset: v1
  • metadata_name: vs的名称
  • spec_hosts:对应服务的service名称
  • spec_http_match:路由规则
    上面表达式的内容解说过来为:对reviews服务的访问请求中,如果请求头的end-user的值为jason,则将流量路由到reviews服务的v2版本上,其他流量路由在v1版

vs配置中的关键配置项

  1. hosts:表示流量发送的目标(可以理解为拦截目标,也可以理解为配置的路由规则归属哪一个Sidecar),在k8s中hosts需要配置为服务的service域名,同namesapce下可以配置 短域名因为可以跨namespace配置路由规则,所以这里是不便于管理的,如果重新开发istio配置管理dashboard可以考虑为域名分配增加权限

  2. http: 是一个类似httpRoute的路由集合,用于处理http的流量,是istio最丰富的的流量规则

  3. tls:是一个tlsRoute类型的路由集合,用于处理非终结的tls和https流量

  4. tcp:是一个tcpRoute类型的路由集合,用于处理tcp流量,应用于所有非http和tls端口的流量

  5. exportTo:是istio在1.1版本后的新增特性,用于控制VS跨namespace的可见性。可以控制在一个命名空间下定义的vs是否可以被其他命名空间的Sidecar和Gateway使用。不填写代表全局可见,".“代表仅当前namespace可见,”* "代表所有namespace可见。

HttpRoute

在正常使用时,http协议的路由应用场景最多,主要介绍一下http路由的使用场景和使用方法
在这里插入图片描述
如上图,httproute可以通过请求中的内容为条件,对请求进行重定向、重写、重试、故障注入、流量复制等操作
我们把这些步骤拆分一下,主要分为匹配规则,重定向,重写,重试,故障注入,流量复制这几个方面来详述。

HTTPRoute的匹配规则

简述:匹配规则是分发流量的重要条件,关键字段是match字段,在match字段下就是对请求路由的匹配方式。
在这里插入图片描述

  • uri、scheme、method、authority:这4个字段都是StringMatch类型,请求规则中都支持exact(完全匹配),prefix(前缀匹配)、regex(正则匹配)三种匹配方式
  • headers:匹配请求中的header,是一个map类型,所以匹配时以k-v的形式比对,对每一个header的值都可以使用exact,prefix、regex三种匹配方式。

例:

- match: 
    - headers: 
        end-user: 
            exact: jason
      uri:
        prefix: "/testPipeline"

以上规则中包含了1和2的使用方式,代表匹配请求头中的end-user的值为jason且uri以/testPipeline开头的请求。

注意,条件或怎么写?如下所示:

- match: 
    - headers: 
        end-user: 
            exact: jason
    - uri:
        prefix: "/testPipeline"
  • port:表示请求的端口,在使用时大部分的服务都只开放了一个端口,在这种场景下可以不用指定端口(port在实际使用中使用率会小些)
  • sourceLabels:表示请求来源服务的标签,在k8s中这个标签就是指pod的标签。
    例:
http:
  - match:
    - sourceLabels:
        app: cicdfront
        version: v1.0.10
    route:
    - destination:
        host: cicdapi
        subset: v1.0.10
  - route:
    - destination:
        host: cicdapi
        subset: v1.0.9

当请求服务来源为cicdfront且其pod版本为v1.0.10时会将流量转发到cicdapi的v1.0.10上,其他的请求会发送到cicdapi的v1.0.9版本上

HttpRoute的路由目标

简述:路由目标代表请求流量发送到的目标服务,关键字段是route,在match(匹配规则)下时常代表匹配规则后的发送请求的目标服务。
当请求完成匹配规则后,我们需要对匹配到的请求进行转发,我们还是以开始的配置举例(稍微改动一下)。

http:
  - match:
    - headers:
        end-user:
          exact: jason
    route:
    - destination:
        host: reviews
        subset: v2
     weight: 30
    - destination:
        host: reviews
        subset: v3
     weight: 70
  - route:
    - destination:
        host: reviews
        subset: v1

通过上节的匹配规则我们可以理解match中的匹配规则为请求头中的end-user的值为jason。当匹配这一条件时route路由生效,将请求的30%发送到reviews服务的v2版本上,另外70%发送到reviews服务的v3版本上。对未能匹配的请求路由到v1版本上。
这一转发需要搭配istio的另一个重要配置DR(DestinationRule)使用,DR中通过标签定义不同的pod服务。通过subset子集来完成请求的调用,这里按reviews服务的v1 v2两个pod理解就好。

  • destination中的host与http中的host一致,在k8s中也是指向的service的域名,可以省略部分内容做短域名(在同namespace下的时候)。subset代表对应的dr子集。
  • weight:除了destination之外的另一个重要属性主要用于流量分配的比例,在一个route下多个dr下流量权重之和必须为100

HTTPRedirect重定向

简述:istio可以人工注入一些不可见的重定向规则,自定义的重定向规则在redirect关键字下
理解了istio的vs工作模式那么我们接下来继续看istio的重定向功能。

比较常见的使用场景:网站系统的网站地址发生了变化(并非服务器变化,只是访问地址的请求后缀变化),要求使用之前的访问地址也能够进入网站,不影响旧用户的操作。这种情况下就很适合使用istio的重定向功能

  • uri:替换url中的path部分
  • authority:替换url中的authority部分
    例:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: cicdapi
spec:
  hosts:
    - cicdapi
  http:
    - match:
      - uri:
        prefix: /pipeline
      redirect:
        uri: /cicd/pipeline
        authority: newcicd

以上的请求对cicdapi服务的/pipeline请求都会被重定向到newcicd服务的/cicd/pipeline上

HTTPRewrite重写

简述:istio可以在请求发送给目标服务之前对请求信息进行改写,这个改写过程是对客户端及服务端都不可见的。重写与重定向很像。
关键字:rewrite

  1. uri: 重写url中的path部分
  2. authority: 重写url中的authority部分
    例:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: cicdapi
spec:
  hosts:
    - cicdapi
  http:
    - match:
      - uri:
        prefix: /pipeline
      rewrite:
        uri: /cicd/pipeline

HTTPRerty重试

简述:很多时候http请求发生异常,重试都是解决异常的最直接,最简单的办法,尤其是环境比较复杂的情况下,可以提高总体的服务质量,但是这个重试逻辑如果放在客户端进行调度就过于不规范,不便于管理。istio可以支持这种重试的自动调度。
关键字:retry

  1. attempts:必填字段,定义重试的次数
  2. perTryTimeout:每次重试的超时时间,单位可以是毫秒(ms),秒(s),分钟(m)和小时(h)
  3. retryOn: 重试的条件,可以是多个条件以逗号分隔。可用条件有以下内容
    (1)5xx:在上游服务返回5xx的返回码,或在没有响应的时候进行重试
    (2)gateway-error:类似5xx异常,只对502,503,504的路由异常进行重试
    (3)connect-failure:在连接上游服务失败时重试
    (4)retriable-4xx:在上游服务返回4xx返回码时进行重试(这里可能不包括部分返回码,如404,405
    (5)refused-stream:在上游服务使用REFUSED_STREAM错误码重置时重试
    (6)cancelled:在gRPC应答的Header中状态码是cancelled时重试
    (7)deadline-exceeded:在gRPC应答的Header中的状态码是deadline-exceeded时重试
    (8)internal:在gRPC应答的Header中的状态码是internal时重试
    (9)resource-exhausted:在gRPC应答的Header中的状态码是resource-exhausted时重试
    (10)unavailable:在gRPC应答的Header中的状态码是unavailable时重试
    例:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: cicdapi
spec:
  hosts:
    - cicdapi
  http:
    - route:
      - destination:
          host: cicdapi
     retries:
       attempts: 5
       perTryTimeout: 3s
       retryOn: 5xx,connect-failure

Mirror流量复制

简述:流量复制是指在流量需要发送到某个服务时,将这个请求流量复制一份到一个指定的服务上,如下图。可以将生产系统的流量复制到一个需要更新的新版本服务上,这样完全不会对生产系统产生影响,这里只复制了一份流量,数据面代理只需要住原来的流量就可以了。
关键字:mirror
图片

例:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: portal-web
spec:
  hosts:
    - portal-web
  http:
    - route:
      - destination:
          host: portal-web
          subset: v1.0.15
      mirror:
        host: portal-web
        subset: v1.0.16

HttpFaultInjection故障注入

简述:除了转发重试这些常用的http请求操作,istio还支持故障注入。主要用于测试时主动模拟一些异常场景,比如跨服务请求超时,访问中发生错误等情况。

这个作用主要是观察微服务中,某个服务处故障时,整体服务的健康状况,观察是否会出现级联影响的情况。
在istio中故障注入主要分为两种

  1. 延迟故障注入
    延迟故障注入用来模拟超时的场景,模拟网络负载等原因导致的请求失败
    配置参数如下:
    (1)fixedDelay:必选字段,表示延迟的时间,单位可以是毫秒,秒,分钟,小时。要求时间必须大于1毫秒
    (2)percentage:选填字段,配置故障发生的比例,通过这个配置可以配置故障发生的比例(无单位,支持小数,表示百分比。如果不填默认为100,注入所有请求)。
    例:
……
- route:
      - destination:
          host: portal-web
          subset: v1.0.15
- fault:
    delay:
       percentage:
         value: 1.5
       fixedDelay: 10s

表示对portal-web服务的请求的百分之1.5会被注入10s的延迟

  1. 请求中止故障注入
    请求中止故障注入,主要是为了模拟服务端故障的情况,可以注入指定的返回码和返回信息
    配置参数如下:
    (1)httpStatus:是一个必选字段,表示中止的HTTP状态码
    (2)percentage:配置的中止故障作用在多少比例的请求上,配置方式与延迟故障的一致。
    例:
……
- route:
      - destination:
          host: portal-web
          subset: v1.0.15
- fault:
    delay:
       percentage:
         value: 1.5
       httpStatus: 500

对portal-web服务的请求的百分之1.5会被模拟返回500的异常。


其实当了解了vs的大部分功能之后,我们可以看到vs的作用其实与k8s的service的作用基本是一致的,只是vs是用来修饰service的服务,可以调整、组合、拼接service,将多个service拼装成一个大的,富有规则的service。

十二、DestinationRule目标规则

在我们刚刚查看VirtualService时候经常能看到这样一段配置

- route:
      - destination:
          host: portal-web
          subset: v1.0.15

之前说这段配置指的是将流量发送给portal-web的v1.0.15的版本,这样说是为了方便理解。实际上这种说法是不严谨的,这段配置真实代表的含义是将请求转发给portal-web服务的destinationRule的v1.0.15的子集
DestinationRule配置样例:

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: cicdpai
spec:
  host: cicdapi
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
  - name: v3
    labels:
      version: v3

DestinationRule规则定义

destinationRule经常与virtualService一起使用dr是配合vs一起使用的,但是vs并不要求一定需要使用dr,如果不使用dr,vs会直接使用service来负载调用对应的pod),virtualService用来修饰满足什么条件后被哪个后端处理。而destinationRule描述的是这个请求到达某个后端后该怎么去处理。
简述:vs设置服务的访问规则,具体请求服务时的规则由dr来决定。
关键属性:
(1)host:必选字段,表示规则的使用对象,对应的也是k8s中的service。域名解析方式与之前的host配置一致。
(2)trafficPolicy:规则的内容定义,包括负载均衡,连接池策略,异常点检查等内容。
(3)exportTo:Istio 1.1版本后新增的特性,用于控制DestinationRule跨命名空间的可见性,这样就能控制在一个命名空间下定义的资源对象是否可以被其他命名空间下的Sidecar执行。如果不做赋值代表全命名空间都可见。支持“.” 代表当前命名空间可见。"*" 代表全命名空间可见。
(4)subsets:代表一个服务的子集,一般代表一个服务的版本,与vs结合使用。每个子集都是通过label来匹配对应的pod,在istio的使用要求中建议用户为每个pod分配app、version两个标签。所以subset一般以version来划分,但这并不是硬性限制。

1.负载均衡设置

简述:当subset中可以匹配到多个pod时可以通过istio自身的负载均衡策略将请求分配。

  1. ROUND_ROBIN:轮循算法,如果设置了dr但没有为subset设置负载策略,那么会默认使用这个策略
  2. LEAST_CONN:最少连接算法,算法实现的是从两个随机选择的后端服务中选择一个链接数最少的链接
  3. RANDOM:完全随机策略,从现有的健康可用的后端服务中随机抽取一个地址
  4. PASSTHROUGH:直接转发到客户端链接的目标地址,不做转发(这样会有k8s的service进行负载)

2.连接池设置

简述:通过连接池管理可以配置阈值来放置一个服务的失败影响到整个应用。istio的连接池可以配置tcp流量、http流量治理

  1. tcp连接池配置(TCPSetting):
    (1)maxConnections:表示为上有服务的所有实例的最大连接数,默认为1024.对于HTTP只适用于HTTP/1.1因为HTTP/2对每个主机都使用单个连接。
    (2)connectTimeout:TCP连接超时时间。
    (3)tcpKeeplive:是Istio1.1版本后新增的特性,定期给对端发送一个keepalive的探测包,判断连接是否可用。包含三个属性–probes(标识有多少次探测没有反应就判断连接断开,默认使用操作系统的默认配置,linux默认为9),time(标识发送探测前连接空闲了多少时间,也是用操作系统的默认配置,linux默认为2小时),interval(探测间隔,也是用操作系统的默认配置,linux默认为75秒)。
  2. http连接池配置(HTTPSetting):
    (1)http1MaxPendingRequests:最大等待HTTP请求数,默认值为1024,只适用于HTTP/1.1,因为HTTP/2协议的请求在到来时会立即复用连接,不会再连接池等待
    (2)http2MaxRequests:最大请求数,默认1024。只适用于HTTP/2服务,因为HTTP/1.1适用最大连接数配置maxConnections即可。
    (3)maxRequestsPerConnection:每个连接的最大请求数。如果不配置则不作限制
    (4)maxRetries:最大重试次数,默认为3,表示服务可以执行的最大重试次数。如果调用后端因网络抖动导致调用失败,可能会带来业务损失,一般建议配置重试,若重试成功则可以正常配置返回数据,只不过比原来响应的时间稍慢一点。但重试次数过多会对性能产生影响,尽量不要对消耗大的服务进行重试。
    (5)idleTimeout:空闲超时,定义在多长时间内没有活动请求则关闭连接。

3.异常实例检测设置

简述:异常点检查就是定期考察被访问的服务实例的工作情况,如果连续出现访问异常,则将服务实例标记为异常并进行隔离,在一段时间内不为其分配流量,过一段时间被移除的实例会被解除移除,尝试请求,如果访问失败会进行更长实际胺的隔离,这也是istio的熔断功能。
参数配置:

  1. consecutiveErrors:实例被驱逐前的连续错误次数,默认为5,对于http服务返回502,503,504的返回码会认为服务异常。
  2. interval:驱逐检查的时间间隔(驱逐检测的统计时间),默认为10秒,要求大于1毫秒,单位可以是时、分、毫秒
  3. baseEjectionTime:最小驱逐时间。一个服务被驱逐的时间等于驱逐次数乘以最小驱逐时间。所以被驱逐的实例再被再次驱逐时会变得越来越长。时间默认为30秒,要求大于1毫秒,单位可以是时、分、毫秒。
  4. maxEjectionPercent:服务的可驱逐故障实例的最大比例,默认为10%。官方不建议配置过高,过分的驱逐会影响服务的服务能力
  5. minHealthPercent:最小健康比例,是istio 1.1版本后新增的特性,当负载的实例中,如果健康的实例数量低于这个比例,istio会进入恐慌模式,异常检查功能会被禁用,所有的服务不论是否是故障实例都可以接受请求。

例:

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
 name: cicdapi
 namespace: paas
spec:
 host: cicdapi
 trafficPolicy:
   connectionPool:
     tcp:
       maxConnections: 80
       connectTimeout: 25ms
     http:
       http2MaxRequest: 800
       maxRequestsPerConnection: 10
   outlierDetection:
     consecutiveErrors: 5
     interval: 4m
     baseEjectionTime: 10m
     maxEjectionPercent: 30

检查4分钟内cicdapi服务的异常情况,连续出现5次连接异常的服务实例会被隔离10分钟,被隔离的服务数量不能超过30%。达到十分钟后实例会重新接受请求,如果依然不能正常工作会被隔离20分钟

4.端口策略

简述:当我们熟悉以上的连接池配置后,实际端口配置也没有什么特殊的地方,实际上就是为了某些端口配置一些特殊规则,比如最大连接数等

例:

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
 name: cicdapi
 namespace: paas
spec:
 host: cicdapi
 trafficPolicy:
   connectionPool:
     tcp:
       maxConnections: 80
   portLevelSettings:
   - port: 
       number: 8081
     connectionPool:
       tcp:
         maxConnections: 100

cicd服务的最大连接数为80,但8081端口单独配置了最大连接数为100

5.服务子集

简述:subset主要作用就是通过label标签配置真实的后端服务。virtualService中通过制定subset的name来引用对应的服务。
name:必选字段,subset的名字,通过virtualService引用subset的时候就是通过name来引用的
labels:服务标签,通过标签来引用真实的后端服务,最常用的标签为version标签
trafficPolicy:应用到这个subset的流量策略

例:

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: cicdapi
  namespace: paas
spec:
  host: cicdapi
  subset: 
  - name: v2
    labels:
      version: v2
  trafficPolicy:
    connectionPool:
      tcp:
        maxConnections: 80

dr的作用主要就是配置目标服务的匹配方式和负载均衡、熔断的服务治理方式。

十三、Gateway服务网关

之前的配置不论是vs还是dr的配置都是针对服务间的访问做的样例,没有针对过外部请求访问容器服务的样例。这种请求都需要通过istio的服务网关来配置。
样例:

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: cicdfront-gateway
spec:
  selector:
    istio: ingressgateway # use istio default controller
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "cicdfront.com"
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: cicd-front
spec:
  hosts:
  - frontend
  - cicdfront.com
  gateways:
  - cicdfront-gateway
  - mesh
  http:
  - route:
    - destination:
        host: cicd-front
        port:
          number: 8080

Gateway规则定义

Gateway一般需要与virtualService结合使用,Gateway定义了服务从外面怎么访问,virtualService定义了匹配到内部服务怎么流转。
关键配置:
selector:必选字段,表示Gateway负载,为入口处的Envoy运行的pod标签
server:必选字段,表示开放的服务列表

后端服务Server

简述:server定义了服务的访问入口

  1. port:必选字段,描述了服务在哪个端口对外开放,是对外监听端口。
  2. hosts:必选字段,为Gateway发布的服务地址,是一个域名,用来匹配virtualService的hosts,会匹配到设置了同样hosts的vs。

例:

servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "cicdfront.com"

十四、ServiceEntry

ServiceEntry是用作外部服务配置。

简述:将网格外的服务加入网络中,像网格内的服务一样管理,实际上就是将不归属istio自动注入的服务加入到istio的服务发现。
配置示例

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: cicdfront-entry
spec:
  hosts:
  - www.cicddb.com
  ports:
  - number: 80
    name: http
    protocol: HTTP
  resolution: DNS
  location: MESH_EXTERNAL

ServiceEntry规则定义

重要参数:

  1. hosts:必选字段,表示ServiceEntry相关的主机名,可以是一个DNS域名,可以使用前缀模糊匹配
  2. addresses:表示与服务关联的虚拟IP地址。
  3. port:表示与外部服务关联的端口。
  4. location:设置服务时在网格内还是网格外,支持以下两种模式
    (1)MESH_EXTERNAL:表示在网格外部,通过api访问的外部服务。
    (2)MESH_INTERNAL:表示在网格内部,一些不能直接注册到服务网格注册中心的服务。
  5. resolution: 表示服务的发现模式,将服务名解析到一个后端的IP上。可以设置NONE、STATIC、DNS三种模式
    (1)NONE:用于连接的目标地址已经是一个明确的IP场景是使用。
    (2)STATIC:用在已经使用endpoint设置了服务示例的地址场景中, 也不需要解析。
    (3)DNS:表示用查询环境中的DNS进行解析,前提是没有在hosts中使用通配符。
  6. subjectAltNames: 表示这个服务负载的SAN列表
  7. endpoints:表示与网格服务关联的网络地址,可以是一个IP,可以是一个主机名。endpoints通过很多字段一同生成
    (1)address: 必选字段,表示网络后端的服务地址
    (2)ports:端口列表
    (3)labels:后端的标签
    (4)locality:后端的locality,用于亲和性路由
    (5)weight:表示负载均衡的权重。

十五、总结

  • 我们在正常使用中,多使用的一般只有virtualService,destinationRule、Gateway这三种功能。vs负责配置访问规则、dr负责配置目标实例和负载规则,Gateway负责配置入口规则。配置好这三种配置就可以满足我们大部分的使用场景。

但在使用中会发现这几种问题

  1. istio基本所有的功能配置时都要求一个必填字段hosts,在k8s集群中 ,这个hosts是我们服务的长短域名,也就是service的名称。所以在很大程度来讲,istio都是基于service在工作。但是istio没有图形界面提供功能配置,不论是vs,dr,gw都是需要通过yaml配置的。这种配置就不能限制用户的一些误操作,比如对一个服务配置误配置了两个vs,那么哪个会是有效的vs?对一个服务配置了两个dr,那么哪个会是有效的dr?前面提过istio在1.1版本之后新增了exportTo属性,代表当前配置能否支持跨namespace,默认都是允许跨namespace生效的,这样会不会出现误引用的情况?

所以在使用时还是建议封装istio的yaml拼装功能,通过页面进行控制,防止误配置yaml。

  1. istio会进行服务间的流量治理,实现方式是通过iptables进行流量拦截,这样使用时为了让入口服务也能被istio治理就必须使用istio的入口网关Gateway。这样平台使用时就不能直接为用户提供route的方式访问平台。需要使用gateway进行包装才行。但并不是所有服务都需要进行包装,只有需要在集群外直接访问的服务需要进行这个包装。(大部分都是前台服务才需要进行这个步骤:浏览器 --> cicd-front --> cicd-api,这种情况下就需要为cicdfront生成入口网关,用户需要通过入口网关访问cicdfront才能治理这部分流量

  2. 集群内不能直接访问集群外的url

参考:

Istio介绍

istio功能介绍

istio流量管理:非侵入式流量治理

你可能感兴趣的:(微服务,mesh,微服务)