VirtualService是Istio流量治理的一个核心配置,可以说是Istio流量治理中最重要、最复杂的规则,本节详细讲解其定义和用法。
在理解VirtualService的完整功能之前,先看如下简单示例:
Istio的配置都是通过Kubernetes的CRD方式表达的,与传统的键值对配置相比,语法描述性更强。因此,我们很容易理解以上规则的意思:对于 forecast服务的访问,如果在请求的Header中location取值是north,则将该请求转发到服务的v2版本上,将其他请求都转发到服务的v1版本上。
VirtualService定义了对特定目标服务的一组流量规则。如其名字所示,VirtualService在形式上表示一个虚拟服务,将满足条件的流量都转发到对应的服务后端,这个服务后端可以是一个服务,也可以是在DestinationRule中定义的服务的子集。
VirtualService是在Istio V1alpha3版本的API中引入的新路由定义。不同于V1alpha1版本中RouteRule使用一组零散的流量规则的组合,并通过优先级表达规则的覆盖关系,VirtualService描述了一个具体的服务对象,在该服务对象内包含了对流量的各种处理,其主体是一个服务而不是一组规则,更易于理解。
VirtualService中的一些术语如下。
◎ Service:服务,参照2.2.1节Istio服务模型中的概念。
◎ Service Version:服务版本,参照2.2.2节Istio服务模型中的概念。
◎ Source:发起调用的服务。
◎ Host:服务调用方连接和调用目标服务时使用的地址,是 Istio的几个配置中非常重要的一个概念,后面会有多个地方用到,值得注意。
通过 VirtualService 的配置,应用在访问目标服务时,只需要指定目标服务的地址即可,不需要额外指定其他目标资源的信息。在实际请求中到底将流量路由到哪种特征的后端上,则基于在VirtualService中配置的路由规则执行。
如图3-27所示是VirtualService的完整规则定义,可以看出其结构很复杂,本节后续将逐级展开介绍。
先看下VirtualService第1级的定义,如图3-28所示,可以很清楚地看到,除了hosts、gateways等通用字段,规则的主体是http、tcp和tls,都是复合字段,分别对应HTTPRoute、TCPRoute和TLSRoute,表示Istio支持的HTTP、TCP和TLS协议的流量规则。
非复合字段hosts和gateways是每种协议都要用到的公共字段,体现了VirtualService的设计思想。
(1) hosts:是一个重要的必选字段,表示流量发送的目标。可以将其理解为VirtualService定义的路由规则的标识,用于匹配访问地址,可以是一个DNS名称或IP地址。DNS 名称可以使用通配符前缀,也可以只使用短域名,也就是说若不用全限定域名FQDN,则一般的运行平台都会把短域名解析成FQDN。
图3-27 VirtualService的完整规则定义
对于Kubernetes平台来说,在hosts中一般都是Service的短域名。如forecast这种短域名在 Kubernetes 平台上对应的完整域名是“forecast.weather.svc.cluster.local”,其中weather 是 forecast 服务部署的命名空间。而在 Istio 中,这种短域名的解析基于VirtualService 这个规则所在的命名空间,例如在本节的示例中,hosts 的全域名是“forecast.default.svc.cluster.local”,这与我们的一般理解不同。建议在规则中明确写完整域名,就像在写代码时建议明确对变量赋初始值,而不要依赖语言本身的默认值,这样不但代码可读,而且可以避免在某些情况下默认值与期望值不一致导致的潜在问题,这种问题一般不好定位。
注意:VirtualService 的 hosts 的短域名解析到的完整域名时,补齐的 Namespace 是VirtualService的Namespace,而不是Service的Namespace。
图3-28 VirtualService第1级的规则定义
hosts一般建议用字母的域名而不是一个IP地址。IP地址等多用在以Gateway方式发布一个服务的场景,这时hosts匹配Gateway的外部访问地址,当没有做外部域名解析时,可以是外部的IP地址。3.4节将讲解如何将VirtualService和Gateway配合使用。
(2)gateways:表示应用这些流量规则的 Gateway。VirtualService 描述的规则可以作用到网格里的 Sidecar 和入口处的 Gateway,表示将路由规则应用于网格内的访问还是网格外经过Gateway的访问。其使用方式有点绕,需要注意以下场景。
◎ 场景1:服务只是在网格内访问的,这是最主要的场景。gateways字段可以省略,实际上在VirtualService的定义中都不会出现这个字段。一切都很正常,定义的规则作用到网格内的Sidecar。
◎ 场景2:服务只是在网格外访问的。配置要关联的Gateway,表示对应Gateway进来的流量执行在这个VirtualService上定义的流量规则。
◎ 场景3:在服务网格内和网格外都需要访问。这里要给这个数组字段至少写两个元素,一个是外部访问的Gateway,另一个是保留关键字“mesh”。使用中的常见问题是忘了配置“mesh”这个常量而导致错误。我们很容易认为场景 3是场景 1和场景2的叠加,只需在内部访问的基础上添加一个可用于外部访问的Gateway。
注意:在 VirtualService 中定义的服务需要同时网格外部访问和内部访问时,gateways 字段要包含两个元素:一个是匹配发布成外部访问的Gateway名,另外一个是“mesh”这个关键字。
(3)http:是一个与 HTTPRoute 类似的路由集合,用于处理 HTTP 的流量,是 Istio中内容最丰富的一种流量规则。
(4)tls:是一个 TLSRoute 类型的路由集合,用于处理非终结的 TLS 和 HTTPS 的流量。
(5)tcp:是一个TCPRoute类型的路由集合,用于处理TCP的流量,应用于所有其他非 HTTP和 TLS端口的流量。如果在 VirtualService中对 HTTPS和 TLS没有定义对应的TLSRoute,则所有流量都会被当成TCP流量来处理,都会走到TCP路由集合上。
以上3个字段在定义上都是数组,可以定义多个元素;在使用上都是一个有序列表,在应用时请求匹配的第1个规则生效。
注意:VirtualService中的路由规则是一个数组,在应用时匹配的第1个规则生效就跳出,不会检查后面的规则。
(6) exportTo:是 Istio 1.1 在 VirtualService 上增加的一个重要字段,用于控制VirtualService 跨命名空间的可见性,这样就可以控制在一个命名空间下定义的VirtualService是否可以被其他命名空间下的Sidecar和Gateway使用了。如果未赋值,则默认全局可见。“.”表示仅应用到当前命名空间,“*”表示应用到所有命名空间。在Istio 1.1中只支持“.”和“*”这两种配置。
HTTP是当前最通用、内容最丰富的协议,控制也最多,是Istio上支持最完整的一种协议。通过它除了可以根据协议的内容进行路由,还可以进行其他操作。
VirtualService中的http是一个HTTPRoute类型的路由集合,用于处理HTTP的流量。
◎ 服务的端口协议是HTTP、HTTP2、GRPC,即在服务的端口名中包含http-、http2-、grpc-等。
◎ Gateway的端口协议是HTTP、HTTP2、GRPC,或者Gateway是终结TLS,即Gateway外部是HTTPS,但内部还是HTTP。
◎ ServiceEntry的端口协议是HTTP、HTTP2、GRPC。
本节看看如何描述HTTPRoute的流量路由规则,配置示例参见3.2.1节VirtualService的配置示例。
1.HTTPRoute规则解析
HTTPRoute的规则定义如图3-29所示。
图3-29 HTTPRoute规则定义
HTTPRoute 规则的功能是:满足 HTTPMatchRequest 条件的流量都被路由到HTTPRouteDestination,执行重定向(HTTPRedirect)、重写(HTTPRewrite)、重试(HTTPRetry)、故障注入(HTTPFaultInjection)、跨站(CorsPolicy)策略等。HTTP 不仅可以做路由匹配,还可以做一些写操作来修改请求本身,如图 3-30 所示,对用户来说非常灵活。
图3-30 HTTPRoute规则
2.HTTP匹配规则(HTTPMatchRequest)
在HTTPRoute中最重要的字段是条件字段match,为一个HTTPMatchRequest类型的数组,表示HTTP请求满足的条件,支持将HTTP属性如uri、scheme、method、authority、port 等作为条件来匹配请求。一个 URI 的完整格式是:URI=scheme:[//authority]path [?query][#fragment],如图3-31所示。
图3-31 URI的完整格式
Authority的定义与 Host的定义容易混淆,都是类似于“weather.com”这样的服务主机名,两者有什么差别呢?
实际上,Authority的标准定义是:“authority=[userinfo@]host[:port]”,如图3-32所示。
图3-32 Authority的标准定义
下面讲讲Authority标准定义中的字段。
(1)uri、scheme、method、authority:4个字段都是StringMatch类型,在匹配请求时都支持exact、prefix和regex三种模式的匹配,分别表示完全匹配输入的字符串,前缀方式匹配和正则表达式匹配。
(2)headers:匹配请求中的Header,是一个Map类型。Map的Key是字符串类型,Value 仍然是 StringMatch 类型。即对于每一个 Header 的值,都可以使用精确、前缀和正则三种方式进行匹配。如下所示为自定义headers中source的取值为“north”,并且uri以“/advertisement”开头的请求:
(3)port:表示请求的服务端口。大部分服务只开放了一个端口,这也是在微服务实践中推荐的做法,在这种场景下可以不用指定port。
(4)sourceLabels:是一个 map 类型的键值对,表示请求来源的负载匹配标签。这在很多时候非常有用,可以对一组服务都打一个相同的标签,然后使用sourceLabels字段对这些服务实施相同的流量规则。在Kubernetes平台上,这里的Label就是Pod上的标签。
如下表示请求来源是frontend服务的v2版本的负载:
(5)gateways:表示规则应用的Gateway名称,语义同VirtualService上面的gateways定义,是一个更细的Match条件,会覆盖在VirtualService上配置的gateways。
注意:在HTTPRoute的匹配条件中,每个HTTPMatchRequest中的诸多属性都是“与”逻辑,几个元素间的关系是“或”逻辑。
需要注意的是,在VirtualService中match字段都是数组类型。HTTPMatchRequest中的诸多属性如uri、headers、method等是“与”逻辑,而数组中几个元素间的关系是“或”逻辑。
在下面的示例中,match包含两个HTTPMatchRequest元素,其条件的语义是:headers中的source取值为“north”,并且uri以“/advertisement”开头的请求,或者uri以“/forecast”开头的请求。
3.HTTP路由目标(HTTPRouteDestination)
HTTPRoute上的route字段是一个HTTPRouteDestination类型的数组,表示满足条件的流量目标。在3.2.1节forecast服务的VirtualService例子中,在http规则上定义了两个HTTPRoute类型的元素,每个HTTPRoute都有一个route字段表示两个请求路由,差别是第1个路由有个match的匹配条件,第2个路由没有匹配条件,只有路由目标。满足匹配条件的流量走到v2版本的目标,剩下所有的流量走v1版本,这也是在灰度发布实践中根据条件从原有流量中切一部分流量给灰度版本的惯用做法。
本节通过HTTPRouteDestination的定义了解怎样描述这个路由目标:
在HTTPRouteDestination中主要有三个字段:destination(请求目标)、weight(权重)和headers(HTTP头操作),destination和weight是必选字段。
1)destination
核心字段 destination 表示请求的目标。在 VirtualService 上执行一组规则,最终的流量要被送到这个目标上。这个字段是一个Destination类型的结构,通过host、subset和port三个属性来描述。
host 是 Destination 的必选字段,表示在 Istio 中注册的服务名,不但包括网格内的服务,也包括通过ServiceEntry方式注册的外部服务。在Kubernetes平台上如果用到短域名,Istio 就会根据规则的命名空间解析服务名,而不是根据 Service 的命名空间来解析。所以在使用上建议写全域名,这和VirtualService上的hosts用法类似。
还是以本节的配置示例来说明:
如果在这个 VirtualService 上没有写 namespace,则后端地址会是 forecast.default.svc.cluster.local。建议通过如下方式写服务的全名,即不管规则在哪个命名空间下,后端地址总是明确的:
与host配合来表示流量路由后端的是另一个重要字段subset,它表示在host上定义的一个子集。例如,在灰度发布中将版本定义为subset,配置路由策略会将流量转发到不同版本的subset上。
2)weight
除了 destination,HTTPRouteDestination 上的另一个必选字段是 weight,表示流量分配的比例,在一个route下多个destination的weight总和要求是100。
在下面的示例中,从原有的v1版本中切分20%的流量到v2版本,这也是灰度发布常用的一种流量策略,即不区分内容,平等地从总流量中切出一部分流量给新版本:
如果一个route只有一个destination,那么可以不用配置weight,默认就是100。如下所示为将全部流量都转到这一个destination上:
3)headers
在Istio 1.0中,HTTPRoute和TCPRoute共用一个Destination的定义DestinationWeight,其结构与Istio 1.1中的RouteDestination基本类似,包括destination和weight两个字段。但 HTTPRouteDestination 在普通的 RouteDestination 上多出来一个 HTTP 特有的字段headers。
headers 字段提供了对 HTTP Header 的一种操作机制,可以修改一次 HTTP 请求中Request或者Response的值,包含request和response两个字段。
◎ request:表示在发请求给目标地址时修改Request的Header。
◎ response:表示在返回应答时修改Response的Header。
对应的类型都是HeaderOperations类型,使用set、add、remove字段来定义对Header的操作。
◎ set:使用map上的Key和Value覆盖Request或者Response中对应的Header。
◎ add:追加map上的Key和Value到原有Header。
◎ remove:删除在列表中指定的Header。
以上分别介绍了 HTTP 请求匹配条件的定义和 HTTP 目标路由的定义,这也是HTTPRoute的主要功能。Istio对于HTTP除了可以做流量的路由,还可以做适当的其他操作,很多原来需要在代码里进行的 HTTP 操作,在使用 Istio 后通过这些配置都可以达到同样的效果,下面分别进行讲解。
4.HTTP重定向(HTTPRedirect)
我们通过 HTTPRedirect 可以发送一个301重定向的应答给服务调用方,简单讲就是从一个 URL到另外一个 URL的永久重定向。如图 3-33所示,用户输入一个 URL,通过HTTPRedirect 可以将其跳转到另一个 URL。比较常见的场景:有一个在线网站,网址变了,通过这样的重定向,可以在用户输入老地址时跳转到新地址。
图3-33 HTTP重定向
HTTPRedirect包括两个重要的字段来表示重定向的目标。
◎ uri:替换URL中的Path部分。
◎ authority:替换URL中的Authority部分。
需要注意的是,这里使用HTTPRedirect的uri的配置会替换原请求中的完整Path,而不是匹配条件上的 uri 部分。如下所示,对 forecast 服务所有前缀是“/advertisement”的请求都会被重定向到new-forecast的“/recommendation/activity”地址:
5.HTTP重写(HTTPRewrite)
我们通过HTTP重写可以在将请求转发给目标服务前修改HTTP请求中指定部分的内容,流程如图 3-34 所示。不同于重定向对用户可见,比如浏览器地址栏里的地址会变成重定向的地址,HTTP重写对最终用户是不可见的,因为是在服务端进行的。
图3-34 HTTP重写的流程
和重定向 HTTPRedirect的配置类似,重写 HTTPRewrite 也包括 uri 和 authority 这两个字段。
◎ uri:重写URL中的Path部分。
◎ authority:重写URL中的Authority部分。
和HTTPRedirect规则稍有不同,HTTPRedirect的uri只能替换全部Path,HTTPRewrite的 uri 是可以重写前缀的,即如果原来的匹配条件是前缀匹配,则修改后也只修改匹配到的前缀。
如下所示,前缀匹配“/advertisement”的请求,其请求 uri 中的这部分前缀会被“/recommendation/activity”替换:
6.HTTP重试(HTTPRetry)
如图3-35所示,HTTP重试是解决很多请求异常最直接、简单的办法,尤其是在工作环境比较复杂的场景下,可提高总体的服务质量。但重试使用不当也会有问题,最糟糕的情况是重试一直不成功,反而增加了总的延迟和性能开销。所以,据系统运行环境、服务自身特点,配置适当的重试规则显得尤为重要。
图3-35 HTTP重试
HTTPRetry可以定义请求失败时的重试策略。重试策略包括重试次数、超时、重试条件等,这里分别描述相应的三个字段。
◎ attempts:必选字段,定义重试的次数。
◎ perTryTimeout:每次重试的超时时间,单位可以是毫秒(ms)、秒(s)、分钟(m)和小时(h)。
◎ retryOn:进行重试的条件,可以是多个条件,以逗号分隔。
其中,重试条件retryOn的取值包括以下几种。
◎ 5xx:在上游服务返回5xx应答码,或者在没有返回时重试。
◎ gateway-error:类似5xx异常,只对502、503和504应答码进行重试。
◎ connect-failure:在连接上游服务失败时重试。
◎ retriable-4xx:在上游服务返回可重试的4xx应答码时执行重试。
◎ refused-stream:在上游服务使用REFUSED_STREAM错误码重置时执行重试。
◎ cancelled:在gRPC应答的Header中状态码是cancelled时执行重试。
◎ deadline-exceeded:在gRPC应答的Header中状态码是deadline-exceeded时执行重试。
◎ internal:在gRPC应答的Header中状态码是internal时执行重试。
◎ resource-exhausted:在gRPC应答的Header中状态码是resource-exhausted时执行重试。
◎ unavailable:在gRPC应答的Header中状态码是unavailable时执行重试。
如下示例为 forecast 服务配置了一个重试策略,在“5xx,connect-failure”条件下进行最多5次重试,每次重试的超时时间是3秒:
7.HTTP流量镜像(Mirror)
HTTP 流量镜像指的是在将流量转发到原目标地址的同时将流量给另外一个目标地址镜像一份。如图 3-36 所示,把生产系统中宝贵的实际流量镜像一份到另外一个系统上,完全不会对生产系统产生影响,这里只镜像了一份流量,数据面代理只需关注原来转发的流量就可以,不用等待镜像目标地址的返回。
图3-36 HTTP流量镜像
只要使用VirtualService进行如下配置即可实现图3-36中的流量镜像效果:
8.HTTP故障注入(HTTPFaultInjection)
除了支持Redirect、Rewrite、Retry等HTTP请求的常用操作,在HTTPRoute上还支持故障注入。
在场景上,与其说是HTTP支持 Istio的故障注入功能,倒不如说是 Istio的故障注入功能支持HTTP。在Istio中为了支持非侵入的故障注入,要构造一定的业务故障,最好在HTTP这个通用的应用协议上有所支持。
实现上,在 HTTP 上做故障注入和 Redirect、Rewrite、Retry 没有太多差别,都是修改HTTP请求或者应答的内容。需要注意,在使用故障输入时不能启用超时和重试。
HTTPFaultInjection通过delay和abort两个字段配置延时和中止两种故障,分别表示Proxy延迟转发HTTP请求和中止HTTP请求。
1)延迟故障注入
HTTPFaultInjection中的延迟故障使用HTTPFaultInjection.Delay类型描述延时故障,表示在发送请求前进行一段延时,模拟网络、远端服务负载等各种原因导致的失败,主要有如下两个字段。
◎ fixedDelay:一个必选字段,表示延迟时间,单位可以是毫秒、秒、分钟和小时,要求时间必须大于1毫秒。
◎ percentage:配置的延迟故障作用在多少比例的请求上,通过这种方式可以只让部分请求发生故障。
如下所示为让forecast服务的v2版本上百分之1.5的请求产生10秒的延迟:
2)请求中止故障注入
HTTPFaultInjection使用 HTTPFaultInjection.Abort描述中止故障,模拟服务端异常,给调用的客户端返回预先定义的错误状态码,主要有如下两个字段。
◎ httpStatus:是一个必选字段,表示中止的HTTP 状态码。
◎ percentage:配置的中止故障作用在多少比例的请求上,通过这种方式可以只让部分请求发生故障,用法同延迟故障。
如下所示为在刚才的例子中增加中止故障注入,让forecast服务v2版本上百分之1.5的请求返回“500”状态码:
9.HTTP跨域资源共享(CorsPolicy)
如图 3-37 所示,当一个资源向该资源所在服务器的不同的域发起请求时,就会产生一个跨域的HTTP请求。出于安全原因,浏览器会限制从脚本发起的跨域HTTP请求。通过跨域资源共享CORS(Cross Origin Resource Sharing)机制可允许Web应用服务器进行跨域访问控制,使跨域数据传输安全进行。在实现上是在HTTP Header中追加一些额外的信息来通知浏览器准许以上访问。
在VirtualService中可以对满足条件的请求配置跨域资源共享。
◎ allowOrigin:允许跨域资源共享的源的列表,在内容被序列化后,被添加到Access-Control-Allow-Origin的Header上。当使用通配符“*”时表示允许所有。
◎ allowMethods:允许访问资源的HTTP方法列表,内容被序列化到Access-Control-Allow-Methods的Header上。
◎ allowHeaders:请求资源的HTTP Header列表,内容被序列化到Access-Control-Allow-Headers的Header上。
图3-37 HTTP跨域资源共享
◎ exposeHeaders:浏览器允许访问的 HTTP Header 的白名单,内容被序列化到Access-Control-Expose-Headers的Header上。
◎ maxAge:请求缓存的时长,被转化为Access-Control-Max-Age的Header。
◎ allowCredentials:是否允许服务调用方使用凭据发起实际请求,被转化为Access-Control-Allow-Credentials的Header。
我们给forecast服务配置跨域策略,允许源自news.com的GET方法的请求的访问:
在 VirtualService 中,tls 是一种 TLSRoute 类型的路由集合,用于处理非终结的 TLS和HTTPS的流量,使用SNI(Server Name Indication,客户端在TLS握手阶段建立连接使用的服务Hostname)做路由选择。TLSRoute被应用于以下场景中。
◎ 服务的端口协议是HTTPS和TLS。即在服务的端口名中包含https-、tls-等。
◎ Gateway的端口是非终结的 HTTPS和 TLS。参照 3.4.3节 Gateway应用中终结和非终结的HTTPS服务的使用。
◎ ServiceEntry的端口是HTTPS和TLS。
1.TLSRoute配置示例
简单配置如下:
在以上示例中,可以通过HTTPS方式从外面访问weather应用内部的两个HTTPS服务frontend和recommendation,访问目标端口是443并且SNI是“frontend.weather.com”的请求会被转发到 frontend 服务上,访问目标端口是 443 并且 SNI 是“recommendation.weather.com”的请求会被转发到recommendation服务上。
2.TLSRoute规则解析
TLSRoute的规则定义如图3-38所示。
图3-38 TLSRoute的规则定义
可以看出,TLSRoute的规则定义比HTTPRoute要简单很多,规则逻辑也是将满足一定条件的流量转发到对应的后端。在以上规则定义中,匹配条件是 TLSMatchAttributes,路由规则目标是RouteDestination。
3.TLS匹配规则(TLSMatchAttributes)
在 TLSRoute中,match字段是一个 TLSMatchAttributes类型的数组,表示 TLS的匹配条件。下面主要从以下几方面来描述一个TLS服务的请求特征。
◎ sniHosts:一个重要的属性,为必选字段,用来匹配TLS请求的SNI。SNI的值必须是VirtualService的hosts的子集。
◎ destinationSubnets:目标IP地址匹配的IP子网。
◎ port:访问的目标端口。
◎ sourceLabels:是一个map类型的键值对,匹配来源负载的标签。
◎ gateways:表示规则适用的Gateway名字。覆盖VirtualService上的gateways定义。和 HTTPMatchRequest中gateways的意思相同。
可以看到,sniHosts 和 destinationSubnets 属性是 TLS 特有的,port、sourceLabels 和gateways属性同HTTP的条件定义。一般的用法是匹配port和sniHosts,配置如下:
4.四层路由目标RouteDestination
TLS 的路由目标通过 RouteDestination 来描述转发的目的地址,这是一个四层路由转发地址,包含两个必选属性destination和weight。
◎ destination:表示满足条件的流量的目标。
◎ weight:表示切分的流量比例。
RouteDestination 上的这两个字段在使用上有较多注意点。用法和约束同 3.2.3 节中HTTPRouteDestination的对应字段,参见对应描述和配置示例。
所有不满足以上HTTP和TLS条件的流量都会应用本节要介绍的TCP流量规则。
1.TLSRoute配置示例
如下所示是一个简单的TCP路由规则,将来自forecast服务23003端口的流量转发到inner-forecast服务的3003端口:
2.TCPRoute规则解析
与HTTP和TLS类似,如图3-39所示,TCPRoute的规则描述的也是将满足一定条件的流量转发到对应的目标后端,其目标后端的定义和 TLS 相同,也是四层的RouteDestination。本节重点关注TCP特有的4层匹配规则L4MatchAttributes。
图3-39 TCPRoute的规则定义
3.四层匹配规则L4MatchAttributes
在 TCPRoute 中,match 字段也是一个数组,元素类型是 L4MatchAttributes,支持以下匹配属性。
◎ destinationSubnets:目标IP地址匹配的IP子网。
◎ port:访问的目标端口。
◎ sourceLabels:源工作负载标签。
◎ gateways:Gateway的名称。
这几个参数和TLSMatchAttributes对应字段的意义相同,如下所示为基于端口和源工作负载标签描述TCP流量的典型示例:
VirtualService在http、tls和tcp这三个字段上分别定义了应用于HTTP、TLS和TCP三种协议的路由规则。从规则构成上都是先定义一组匹配条件,然后对满足条件的流量执行对应的操作。因为协议的内容不同,路由规则匹配的条件不同,所以可执行的操作也不同。如表3-3所示对比了三种路由规则,从各个维度来看,HTTP路由规则的内容最丰富,TCP路由规则的内容最少,这也符合协议分层的设计。
表3-3 HTTP、TLS、TCP路由规则的对比
下面结合几个典型的使用场景来看看VirtualService的综合用法。
1.多个服务的组合
VirtualService是一个广义的Service,在如下配置中可以将一个weather应用的多个服务组装成一个大的虚拟服务。根据访问路径的不同,对 weather服务的访问会被转发到不同的内部服务上:
如图 3-40 所示,假设 frontend 服务访问“weather.com”服务,则根据不同的路径,流量会被分发到不同的后端服务上。当然,对于内部服务间的访问,更常规的用法是直接使用服务名。
图3-40 组合服务示例
2.路由规则的优先级
我们可以对一个VirtualService配置 N 个路由,不同于V1alpha1版本中多个路由规则(RouteRule)要对规则设置优先级,在VirtualService中通过路由的顺序即可明确表达规则。例如,在下面的配置中,以“/weather/data/”开头的流量被转发到v3版本;以“/weather/”开头的其他流量被转发到v2版本;其他流量被转发到v1版本:
以上三条路由规则随便调整顺序,都会导致另一个规则在理论上不会有流量。例如,调整v2和v3的顺序,则匹配“/weather/”的所有流量都被路由到v2版本,在v3版本上永远不会有流量。在路由规则执行时,只要有一个匹配,规则执行就会跳出,类似代码中的switch分支,碰到一个匹配的case就break,不会再尝试下面的条件。这也是在设计流量规则时需要注意的。
3.复杂条件路由
灰度发布等分流规则一般有两种用法:一种是基于请求的内容切分流量,另一种是按比例切分流量。实际上,根据需要也可以结合使用这两种用法,如下所示是一个稍微综合的用法:
这里的http路由包含两个HTTPRoute,只有第1个包含match条件,根据优先级路由列表的顺序优先级原则,满足第 1个 route中 match条件的流量走第 1个路由,剩下的流量都走第2个路由。
在第1个路由的match条件数组中包含两个HTTPMatchRequest条件:第1个条件检查请求的 uri和 headers;第 2个条件检查请求的 uri。根据请求的组合规则,第 1 个条件的两个属性是“与”逻辑,第1个条件和第2个条件之间是“或”逻辑。
第1个Route包含两个路由目标,分别对应20%和80%的流量。
所以,整个复杂条件表达的路由规则如图3-41所示。
对于forecast服务的请求,当请求的cookie满足“^(.*?;)?(local=north)(;.*)?”表达式,并且 uri 匹配“/weather”,或者请求的 uri 匹配“/data”时,流量走 v2 和 v3 版本,其中v2版本的流量占20%,v3版本占80%;其他流量都走forecast服务的v1版本。
图3-41 整个复杂条件表达的路由规则
4.特定版本间的访问规则
之前在介绍流量的匹配条件时提到一个通用字段 sourceLabels,该通用字段可以用于过滤访问来源。如下配置就很有意思,只对 frontend 服务的 v2 版本到 forecast 服务的 v1版本的请求设置20秒的延迟:
其效果如图3-42所示。
图3-42 在特定版本间配置延迟的效果
以上只是典型的应用,掌握了规则的定义和语法,便可以自由配置需要的业务功能,非常方便和灵活。