第三部分 Istio流量规则配置

规则配置

Istio 提供了一个简单的配置模型,用来控制 API 调用以及应用部署内多个服务之间的四层通信。运维人员可以使用这个模型来配置服务级别的属性,这些属性可以是熔断、超时或重试,以及一些普通的流量管理任务,比如,金丝雀发布、A/B测试、使用流量百分比控制,从而完成应用的逐步发布等。

Istio 中包含有四种流量管理配置资源,分别是VirtualServiceDestinationRuleServiceEntry以及 Gateway

  • VirtualService,在Istio服务中定义路由规则,控制路由如何路由到服务上。
  • DestinationRule,VirtualService路由生效后,配置应用与请求策略
  • ServiceEntry,是通常用于在 Istio 服务之外启用对服务的请求。
  • GateWay,HTTP/TCP 流量配置负载均衡器,比如,启用应用程序的入口流量。

例如,将reviews服务接收到的流量 100% 地发送到v1版本,规则如下

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
  - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v1

以上配置意思是,发送到 reviews 服务(在 hosts 字段中标识)的流量应该被路由到 reviews 服务实例的v1 子集中。路由中的 subset 制定了一个预定义的子集名称,子集的定义来自于目标规则配置:子集指定了一个或多个特定版本的实例标签。如,在 Kubernetes 中部署 Istio 时,“version: v1” 表示只有包含 “version: v1” 标签版本的 pod 才会接收流量。

DestinationRule中,你可以添加其他策略,例如定义使用随机的负载均衡模式:

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: reviews
spec:
  host: reviews
  trafficPolicy:
    loadBalancer:
      simple: RANDOM
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2

可以使用kubectl 命令配置规则。

 

Virtual Service

VirtualService 定义了控制在Istio服务中如何路由服务请求的规则。例如:VirtualService可以把请求路由到不同版本,甚至可以路由到一个完全不同于请求要求的服务器上去。路由可以用很多条件进行判断,比如,请求的源和目的地址、HTTP路径和Header以及各个服务版本的权重等

  • 规则的目标描述

路由规则对应着一或多个用VirtualService配置指定的请求目的主机。这些主机可以是也可以不是实际的目标负载,甚至可以不是同一网格内可路由的服务。例如要给到reviews服务的请求定义路由规则,可以使用内部的名称reviews,也可以用域名bookinfo.comVirtualService可以定义这样的hosts字段:

hosts: 
  - reviews 
  - bookinfo.com

Hosts 字段用显示或者隐式的方式定义了一或多个完全限定名(FQDN)。上面的reviews,会隐式的扩展成为特定的 FQDN,例如在 Kubernetes 环境中,全名会从VirtualService所在的集群和命名空间中继承而来,在默认的命名空间为,reviews.default.svc.cluster.local

 

  • 在服务之间分拆流量

每个路由规则都需要对一或多个有权重的后端进行甄别并调用合适的后端。每个后端都对应一个特定版本的目标服务,服务的版本是依赖标签来区分的。如果一个服务版包含多个注册实例,那么会根据为该服务定义的负载均衡策略进行路由,默认的策略为round-robin

例如下面的规则会把 25% reviews服务流量分配给v2标签;其余的 75% 流量分配给v1

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
    - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v1
      weight: 75
    - destination:
        host: reviews
        subset: v2
      weight: 25
  • 超时和重试

默认情况下,HTTP 请求的超时设置为 15 ,可以使用路由规则来覆盖这个限制:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ratings
spec:
  hosts:
    - ratings
  http:
  - route:
    - destination:
        host: ratings
        subset: v1
    timeout: 10s

还可以用路由规则来指定某些 http 请求的重试次数。下面的代码可以用来设置最大的重试次数,或者在规定时间内一直重试,时间长度同样可以进行覆盖:
 

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ratings
spec:
  hosts:
    - ratings
  http:
  - route:
    - destination:
        host: ratings
        subset: v1
    retries:
      attempts: 3
      perTryTimeout: 2s

注意请求的重试和超时还可以针对每个请求分别设置请求超时任务中展示了超时控制的相关示例。

  • 错误注入

在根据路由规则向选中目标转发 http 请求的时候,可以向其中注入一个或多个错误。错误可以延迟,也可以中断。

下面的例子在目标为ratings:v1服务的流量中,对其中的 10% 注入 5 秒钟的延迟。

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ratings
spec:
  hosts:
  - ratings
  http:
  - fault:
      delay:
        percent: 10
        fixedDelay: 5s
    route:
    - destination:
        host: ratings
        subset: v1

可以使用其他类型的故障,终止、提前终止请求。例如,模拟失败。接下来,在目标为ratings:v1服务的流量中,对其中的 10% 注入 HTTP 400 错误。
 

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ratings
spec:
  hosts:
  - ratings
  http:
  - fault:
      abort:
        percent: 10
        httpStatus: 400
    route:
    - destination:
        host: ratings
        subset: v1

有时会把延迟和中断同时使用。例如下面的规则对从reviews:v2ratings:v1的流量生效,会让所有的请求延迟 5 秒钟,接下来中断 10%的请求。

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ratings
spec:
  hosts:
  - ratings
  http:
  - match:
    - sourceLabels:
        app: reviews
        version: v2
    fault:
      delay:
        fixedDelay: 5s
      abort:
        percent: 10
        httpStatus: 400
    route:
    - destination:
        host: ratings
        subset: v1

可以参考错误注入任务,进行这方面的实际体验。
 

  • 条件规则

可以选择让规则只对符合某些要求的请求生效:

使用工作负载 label 限制特定客户端工作负载

例如,规则可以指示它仅适用于实现reviews服务的工作负载实例(pod)的调用:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ratings
spec:
  hosts:
  - ratings
  http:
  - match:
      sourceLabels:
        app: reviews
    ...

sourceLabels的值取决于服务的实现。例如,在 Kubernetes 中,它可能与相应 Kubernetes 服务的Pod选择器中的Label相同。以上示例还可以进一步细化为仅适用于reviews服务版本v2负载均衡实例的调用:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ratings
spec:
  hosts:
  - ratings
  http:
  - match:
    - sourceLabels:
        app: reviews
        version: v2
    ...

 

如果规则中指定了多个标头,则所有相应的标头必须匹配才能应用规则。根据 HTTP Header 选择规则。下面的规则只会对包含了 end-user 标头的来源请求,且值为jason的请求生效:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
    - reviews
  http:
  - match:
    - headers:
        end-user:
          exact: jason
    ...


 

根据请求URI选择规则。例如,如果 URI 路径以 /api/v1 开头,则以下规则仅适用于请求:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: productpage
spec:
  hosts:
    - productpage
  http:
  - match:
    - uri:
        prefix: /api/v1
    ...
  • 多重匹配条件

可以同时设置多个匹配条件。在这种情况下,根据嵌套,应用AND或OR语义。

如果多个条件嵌套在单个匹配子句中,则条件为 AND。例如,以下规则仅适用于客户端工作负载为reviews:v2且请求中包含jason的自定义end-user标头:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ratings
spec:
  hosts:
  - ratings
  http:
  - match:
    - sourceLabels:
        app: reviews
        version: v2
      headers:
        end-user:
          exact: jason
    ...

如果客户端工作负载是reviews:v2,或者请求中包含jason的自定义end-user标头,则适用此规则。相反,如果条件出现在单独的匹配子句中,则只应用其中一个条件(OR 语义):

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ratings
spec:
  hosts:
  - ratings
  http:
  - match:
    - sourceLabels:
        app: reviews
        version: v2
    - headers:
        end-user:
          exact: jason
    ...


 

  • 优先级

当对同一目标有多个规则时,会按照在VirtualService中的顺序进行应用,换句话说,列表中的第一条规则具有最高优先级。

例如下面的 VirtualService 包含了两个规则,所有对 reviews 服务发起的请求,如果 Header 包含Foo=bar,就会被路由到v2实例,而其他请求则会发送给v1

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
  - reviews
  http:
  - match:
    - headers:
        Foo:
          exact: bar
    route:
    - destination:
        host: reviews
        subset: v2
  - route:
    - destination:
        host: reviews
        subset: v1

注意,基于 Header 的规则具有更高优先级。如果降低它的优先级,那么这一规则就无法生效了,这是因为那些没有限制的权重规则会首先被执行,也就是说所有请求即使包含了符合条件的Foo头,也都会被路由到v1。流量特征被判断为符合一条规则的条件的时候,就会结束规则的选择过程,这就是在存在多条规则时,需要慎重考虑优先级问题的原因。
 

DestinationRule

  • 目标规则

当请求被VirtualService路由之后,DestinationRule配置的一系列策略就生效了。主要包含熔断、负载均衡以及TLS等配置内容。DestinationRule还定义了对应目标主机的可路由subset。VirtualService在向特定服务版本发送请求时会用到这些子集。下面是reviews服务的DestinationRule配置策略以及子集:

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: reviews
spec:
  host: reviews
  trafficPolicy:
    loadBalancer:
      simple: RANDOM
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
    trafficPolicy:
      loadBalancer:
        simple: ROUND_ROBIN
  - name: v3
    labels:
      version: v3

注意单个的DestinationRule配置中可以包含多条策略,比如,defalut和v2。

  • 熔断器

可以用一系列的规则或标准,例如连接数和请求数限制定义简单的熔断器。例如下面的DestinationRulereviews服务的v1版本设置了100连接的限制:

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: reviews
spec:
  host: reviews
  subsets:
  - name: v1
    labels:
      version: v1
    trafficPolicy:
      connectionPool:
        tcp:
          maxConnections: 100
  • 规则评估

和路由规则相似,DestinationRule中定义的策略也是和特定的host相关联的,如果指定了subset,那么具体生效的subset的决策是由路由规则来决定的。

规则评估的第一步,是确认VirtualService中所请求的主机相对应的路由规则。这一步骤决定了将请求发往目标服务的哪一个subset(特定版本)。下一步,被选中的subset如果定义了策略,就会开始是否生效的评估。

注意:这一算法需要留心是,为特定subset定义的策略,只有在该subset被显式的路由时候才能生效。如下面的配置,只为review服务定义了规则(没有对应的VirtualService路由规则)。

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: reviews
spec:
  host: reviews
  subsets:
  - name: v1
    labels:
      version: v1
    trafficPolicy:
      connectionPool:
        tcp:
          maxConnections: 100

既然没有为reviews服务定义路由规则,那么就会使用缺省的round-robin策略,偶尔会请求到v1实例,如果只有一个v1实例,那么所有请求都会发送给它。然而上面的策略是永远不会生效的,这是因为,缺省路由是在更底层完成的任务,策略引擎无法获知最终目的,也无法为请求选择匹配的subset策略。

有两种方法来解决这个问题。第一种,可以把路由策略提高一级,要求他对所有版本生效:

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: reviews
spec:
  host: reviews
  trafficPolicy:
    connectionPool:
      tcp:
        maxConnections: 100
  subsets:
  - name: v1
    labels:
      version: v1

第二种(推荐),为服务定义路由规则,例如给reviews:v1添加一个简单的路由规则:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
  - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v1

虽然 Istio 在没有定义任何规则的情况下,能将所有来源的流量发送给所有版本的目标服务。然而一旦需要对版本有所区别,就需要制定规则了。从一开始就给每个服务设置缺省规则,是 Istio 推荐的最佳实践。

Service Entry

Istio 内部会维护一个服务注册表,可以通过Service Entry向其中加入额外的条目。通常这个对象用来启用对 Istio 服务之外的服务发送请求。例如下面的ServiceEntry可以用来允许外部对*.foo.com域名上的服务主机的调用。

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: foo-ext-svc
spec:
  hosts:
  - *.foo.com
  ports:
  - number: 80
    name: http
    protocol: HTTP
  - number: 443
    name: https
    protocol: HTTPS

ServiceEntry中使用hosts字段来指定目标,字段值可以是一个完全限定名,也可以是个通配符域名。其中包含的白名单,包含一或多个允许网格中服务访问的服务。

ServiceEntry的配置不仅限于外部服务,它有两种类型:服务内部和服务外部。服务内部,用于显式的将服务加入Istio网络,可以用来把服务作为Istio扩展的一部分加入不受管理的基础设置中,如加入到基于 Kubernetes 的服务网中的虚拟机。服务外部用于表达Istio外的服务。双向 TLS 认证被禁用,策略实现需要在客户端执行,而不像内部服务请求那样在服务端执行。

只要ServiceEntry涉及到了匹配hosts的服务,就可以和VirtualService以及DestinationRule配合工作。例如下面的规则可以和上面的ServiceEntry同时使用,在访问bar.foo.com的外部服务时,设置一个 10 秒钟的超时。

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: bar-foo-ext-svc
spec:
  hosts:
    - bar.foo.com
  http:
  - route:
    - destination:
        host: bar.foo.com
    timeout: 10s

流量的重定向和转发、定义重试和超时以及错误注入策略都支持外部目标。然而由于外部服务没有多版本的概念,因此权重(基于版本)路由就无法实现了。

Gateway

Gateway为 HTTP/TCP 流量配置了一个负载均衡,用于启用一个服务的入口流量。和 Kubernetes Ingress 不同,Istio Gateway只配置四层到六层的功能(例如开放端口或者 TLS 配置)。绑定一个VirtualService到 Gateway 上,用户就可以使用标准的 Istio 规则来控制进入的 HTTP 和 TCP 流量。

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: bookinfo-gateway
spec:
  servers:
  - port:
      number: 443
      name: https
      protocol: HTTPS
    hosts:
    - bookinfo.com
    tls:
      mode: SIMPLE
      serverCertificate: /tmp/tls.crt
      privateKey: /tmp/tls.key

要为Gateway配置对应的路由,必须为定义一个同样hosts定义的VirtualService,其中用gateways字段来绑定到定义好的Gateway上:
 

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: bookinfo
spec:
  hosts:
    - bookinfo.com
  gateways:
  - bookinfo-gateway # <---- 绑定到 Gateway
  http:
  - match:
    - uri:
        prefix: /reviews
    route:
    ...

Ingress 任务中有完整的 Ingress Gateway 例子。虽然主要用于管理入口(Ingress)流量,Gateway还可以用在纯粹的内部服务之间或者出口(Egress)场景下使用。不管处于什么位置,所有的网关都可以以同样的方式进行配置和控制

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值