Istio实战——流量管理

时间:2022-07-22
本文章向大家介绍Istio实战——流量管理,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

流量管理

通过配置路由调整服务之间的流量,支持AB测试,金丝雀测试和流量百分比分发,支持断路器,超时和重试。

流量管理 的API 资源包括:

  • virtual service 虚拟服务
  • Destination rules
  • gateway
  • service entries
  • sidecars

1.1 virtual service

virtual service 和 Destination rules 是Istio 流量路由功能的关键构件。它基于istio平台的连接和发现,通过virtual service配置如何将请求路由到 Istio 服务网格中的微服务。

如果没有它,默认使用Envoy的轮循模型在每个服务的负载平衡池中分配流量,即轮流向每个池成员发送请求。这种分发方式,缺少一定灵活性,比如无法实现AB测试的百分比流量分发。

VS,使得请求和工作负载强分离。并处于二者之间的中间地位,实现请求到后端的流量控制。

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService #api的资源类型
metadata:
  name: reviews #虚拟服务的名称
spec:
  hosts: # 虚拟服务的主机
  - reviews
  http: # HTTP 流量路由规则的有序列表,支持http1.1 http2,grpc
  - match:  # 匹配条件
    - headers: #匹配指定header字段值的请求量,支持前缀匹配,精确匹配和正则表达式匹配
        end-user:
          exact: jason
    route: # 路由规则
    - destination: # 目的地的主机必须是 Istio 服务注册中心中的真实目的地
        host: reviews
        subset: v2
    - uri: # 基于uri的匹配请求
        prefix: /reviews #前缀匹配
    route: # 匹配的uri请求转发目的地
    - destination:
        host: reviews
  - route: # 默认转发
    - destination:
        host: reviews
        subset: v3

基于百分比的分发

spec:
  hosts:
  - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v1
      weight: 75 # reviews:v1承载75%的流量
    - destination:
        host: reviews
        subset: v2
      weight: 25 # reviews:v2承载25%的流量

路由规则按从上到下的顺序进行计算,逐个匹配,第一个匹配则终止。如果没有匹配规则,则转发到默认规则上,否则丢弃。

VS支持http,tls,tcp的流量控制。同时通过exportto配置支持跨命名空间边界的虚拟服务的可见性。如果没有指定名称空间,则默认情况下将虚拟服务导出到所有名称空间。目前只支持当前和所有。可以配置指定应用这些路由的网关和边车的名称。

一个配置示例(只做示例,配置不一定合理):

---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: reviews-route
spec:
  hosts:
  - reviews.prod.svc.cluster.local
  http: #http/grpc流量
  - timeout: 5s # Envoy等待服务的答复的时间,默认15s
  - name: reviews-v2-routes
    match:
    - sourceLabels:
        env: prod
    - headers:
        end-user:
          exact: jason
    - uri:
        prefix: "/wpcatalog"
    - uri:
        exact: "/consumercatalog"
    - ignoreUriCase: false
    - gateways:
      - test.com
    rewrite: # 重写uri
      uri: "/newcatalog"
    redirect: # 重定向url
      uri: "/v1/bookRatings"
      authority: newratings.default.svc.cluster.local
    route:
    - destination:
        host: reviews
        subset: v2
    retries: # Envoy 连接服务的重试, 重试之间的间隔(25ms +),由istio自动调整,防止淹没服务
      attempts: 3 # 尝试最大次数
      perTryTimeout: 2s #每次重试的超时时间
      retryOn: gateway-error,connect-failure,refused-stream
    corsPolicy: #跨域策略
      allowOrigin:
      - example.com
      allowMethods:
      - POST
      - GET
      allowCredentials: false
      allowHeaders:
      - X-Foo-Bar
      exposeHeaders:
      - Token
      maxAge: 24h
    fault: # 故障注入
      abort: # 中止崩溃失败故障
        percentage:
          value: 0.1
        httpStatus: 400
      delay: #延时故障
        percentage: # 每1000个对评级服务的请求中的1个引入5秒延迟
          value: 0.1
        fixedDelay: 5s
  - name: reviews-v1-route
    route:
    - destination:
        host: reviews.prod.svc.cluster.local
        subset: v2
      weight: 25
    - destination:
        host: reviews.prod.svc.cluster.local
        subset: v1
      weight: 751
  tcp: # tcp流量
  - match: #端口匹配
    - port: 27017
    route:
    - destination:
        host: mongo.backup.svc.cluster.local
        port:
          number: 5555
  tls: #https流量
  - match:
    - port: 443
      sniHosts:
      - login.bookinfo.com
    route:
    - destination:
        host: login.prod.svc.cluster.local
  - match:
    - port: 443
      sniHosts:
      - reviews.bookinfo.com
    route:
    - destination:
        host: reviews.prod.svc.cluster.local

其中涉及超时,重试,故障注入,http,tcp,tls流量分发配置。

Crd 的资源定义文件:istio/manifests/charts/base/crds/crd-all.gen.yaml,官方有更详细的http流量配置说明,以及VS API资源。

1.2 Destination rules

虚拟服务看作是如何将流量路由到给定目的地,然后使用目的地规则来配置该目的地的流量发生的情况。它定义了在路由发生后应用于服务的流量的策略。这些规则指定了负载平衡的配置、 sidecar 的连接池大小和异常检测设置,以检测并驱逐负载平衡池中不健康的主机。

支持配置负载均衡,基于哈希的一致性负载平衡,连接池,断路器,连接设置,tls证书设置

负载均衡策略包括:随机,加权,最少请求。

一个配置示例(只做示例,配置不一定合理):

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule # k8s API资源
metadata:
  name: bookinfo-ratings
spec:
  host: ratings.prod.svc.cluster.local
  trafficPolicy: # 流量策略,包括:负载平衡策略、连接池大小、异常检测
    loadBalancer: # 默认LB策略
      simple: LEAST_CONN # ROUND_ROBIN-循环,LEAST_CONN-最小连接,RANDOM-随机,PASSTHROUGH-只连
    portLevelSettings: # 指定端口上的LB
    - port:
        number: 80 # 80端口流量采用最小连接LB
      loadBalancer:
        simple: LEAST_CONN
    - port:
        number: 9080 # 9080端口流量采用轮询LB
      loadBalancer:
        localityLbSetting: #局部LB
           distribute:
             - from: us-west/zone1/* #流量来源
               to:
                 "us-west/zone1/*": 80 # 分担80%
                 "us-west/zone2/*": 20 # 分担20%
             - from: us-west/zone2/*
               to:
                 "us-west/zone1/*": 20
                 "us-west/zone2/*": 80
           failover: #故障转移或分发
             - from: us-east
               to: eu-west
             - from: us-west
               to: us-east
        consistentHash: #散列LB,支持header,cookie,ip,urlquery,哈希环
          httpCookie:
            name: user
            ttl: 0s
    tls: # 客户端配置
      mode: MUTUAL #DISABLE - 不用tls,SIMPLE,MUTUAL-手动设置证书,ISTIO_MUTUAL-istio生成
      # mode=ISTIO_MUTUAL时,下面字段必须为空
      clientCertificate: /etc/certs/myclientcert.pem
      privateKey: /etc/certs/client_private_key.pem
      caCertificates: /etc/certs/rootcacerts.pem
      # 当设定tls时,有些证书是针对二级域名的,那么此时上面的host字段可以设置成 host: "*.foo.com"
    connectionPool: # 配置连接池
    	tcp: # tcp 连接池
        maxConnections: 100 # 最大连接数
        connectTimeout: 30ms # 连接超时时间
        tcpKeepalive:
          time: 7200s
          interval: 75s
      http: # http 连接池
        http2MaxRequests: 1000
        maxRequestsPerConnection: 10
    outlierDetection: #异常检测
      consecutiveErrors: 7
      interval: 5m #检测间隔每5分钟
      baseEjectionTime: 15m # 它设置了每5分钟扫描一次1000个并发,网关错误超过7次,则驱逐15分钟。
      # 网关错误指:HTTP的502、503或504,tcp的连接超时和连接错误/失败
      maxEjectionPercent: 20 # 负载平衡池中可以弹出的上游服务的最大主机百分比。默认值为10% 
      minHealthPercent: 10 # 当负载平衡池中健康主机的百分比低于这个阈值时,异常检测将被禁用,默认0
  subsets: # 定义命名子集,设置指定版本特定的策略
  - name: testversion
    labels:
      version: v3
    trafficPolicy:
      loadBalancer:
        simple: ROUND_ROBIN
        

更多配置参考这里

1.3 Gateway

网关描述了一个负载均衡器,该负载均衡器在网格的边缘接收传入或传出的 HTTP/TCP 连接。也就是网关管理的是网格进出的流量。它应用于在网格边缘运行的独立的Envoy代理,而不是随着服务部署sidecar的 Envoy代理。后者只是服务的流量代理,而不是整个网格的。Istio 的网关资源只允许您配置第4-6层的负载平衡属性,比如要公开的端口、 TLS 设置等等。通常的使用方式是将一个VS(virtual service)绑定到网关(vs中有一Gateway配置项)。

一个配置示例(只做示例,配置不一定合理):

apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: my-gateway
  namespace: some-config-namespace
spec:
  selector:
    app: my-gateway-controller
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - uk.bookinfo.com
    - eu.bookinfo.com
    tls:
      httpsRedirect: true # sends 301 redirect for http requests
  - port:
      number: 443
      name: https-443
      protocol: HTTPS
    hosts: #以下host发到443端口
    - uk.bookinfo.com
    - eu.bookinfo.com
    tls:
      mode: SIMPLE # enables HTTPS on this port
      serverCertificate: /etc/certs/servercert.pem
      privateKey: /etc/certs/privatekey.pem
  - port:
      number: 9443
      name: https-9443
      protocol: HTTPS
    hosts:
    - "bookinfo-namespace/*.bookinfo.com"
    tls:
      mode: SIMPLE # enables HTTPS on this port
      credentialName: bookinfo-secret # fetches certs from Kubernetes secret
  - port:
      number: 9080
      name: http-wildcard
      protocol: HTTP
    hosts:
    - "*"
  - port:
      number: 2379 # to expose internal service via external port 2379
      name: mongo
      protocol: MONGO # 必须是以下之一:HTTP | HTTPS | GRPC | HTTP2 | MONGO | TCP | TLS
    hosts:
    - "*"

更多网格细节参考文档

1.4 Service entries

使用一个服务条目向 Istio 内部维护的服务注册中心添加一个条目。添加服务条目后,Envoy代理可以向服务发送流量,就好像它是您网格中的服务一样。通过配置服务条目,您可以管理运行在网格之外的服务的流量.一般不需要为 mesh 服务使用的每个外部服务添加服务条目。默认情况下,Istio 配置使者代理来传送请求到未知服务。如果想以更细粒度的方式控制外部服务的流量,考虑使用Service entries,然后配置虚拟服务和目的地规则,就像为网格中的任何其他服务配置流量一样。

apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
  name: external-svc-dns
spec:
  hosts: #访问的host
  - foo.bar.com
  location: MESH_EXTERNAL #位置在网格外
  ports: #服务的端口和协议
  - number: 80
    name: http
    protocol: HTTP
  resolution: DNS #解析的方式DNS,意思在下面endpoints进行LB
  endpoints:
  - address: us.foo.bar.com
    ports:
      https: 8080
  - address: uk.foo.bar.com
    ports:
      https: 9080
  - address: in.foo.bar.com
    ports:
      https: 7080
--- #还有一种就是静态IP解析,当然也可以不指定
  resolution: STATIC
    endpoints:
    - address: 2.2.2.2
    - address: 3.3.3.3

1.5 Sidecars

Istio 配置每个特使代理来接受其相关工作负载的所有端口上的流量,并在转发流量时达到网格中的每个工作负载。但是通过sidecars可以实现

  • 对特使代理接受的一组端口和协议进行微调
  • 限制特使代理可以访问的服务集

用于 配置应用于特定命名空间中的所有工作负载,或者使用 workloadSelector 选择特定的工作负载

apiVersion: networking.istio.io/v1alpha3
kind: Sidecar
metadata:
  name: default
  namespace: bookinfo
spec:
  egress: # bookinfo 名称空间中的所有服务配置为只能到达同一名称空间和 Istio 控制平面中运行的服务
  - hosts: 
    - "./*"
    - "istio-system/*"

总结

本文主要涉及istio的流量管理的如何使用,不涉及其具体原理的分析。原理后面再谈。