Istio中定义了一个简单的配置模型,可以很方便地进行规则的配置。在示例练习前,需要先了解一下与规则配置相关的重要概念和基本的配置方法Istio中定义了4种针对流量管理的配置资源定义路由规则,控制请求如何被路由到服务VirtualServiceVirtualService的主要功能是定义路由规则,使请求(流量)可以依据这些规则被分发到对应的服务。路由的方式也有很多种,可以根据请求的源或目标地址路由,也可以根据路径、头信息,或者服务版本进行路由VirtualService中的目标主机定义使用hosts关键字。除了定义域名外,也可以直接定义可路由的服务。比如下面的配置定义了两个目标主机:reviews服务和bookinfo.com域名
Istio中服务版本依靠标签进行区分,可以定义不同种类的标签(如版本号、平台),对流量以不同的维度进行灵活的分配。拆分流量使用weight关键字来设置。如下面的配置,把75%的流量分配给v1版本的reviews服务,25%的流量分配给v2版本
subset(子集)关键字。subset其实就是特定版本的标签,它和标签的映射关系定义在DestionationRule里。比如在subset中设置标签为"version:v1",代表只有附带这个标签的Pod才能接受流量。Istio强制要求Pod设置带有version的标签,以此来实现流量控制和指标收集等功能v1、v2两个标签
timeout关键字可以设置请求的超时时间,比如下面的例子,对访问ratings服务的请求设置10s超时

retries关键字设置重试。下面的设置表示最多重试3次,每次的超时时间为2s
fault关键字来设置故障注入。在下面的例子中我们注入了一个延迟故障,使得ratings服务10%的响应会出现5s的延迟。除了延迟,还可以设置终止或者返回HTTP故障码match关键字实现的。比如下面的例子,对特定的URL进行匹配

字段 | 类型 | 描述 |
|---|---|---|
uri | [StringMatch] | 大小写敏感 |
scheme | [StringMatch] | 大小写敏感 |
method | [StringMatch] | 大小写敏感 |
authority | [StringMatch] | 大小写敏感 |
headers | map<string,[StringMatch]> | Header的键必须是小写的,使用连字符作为分隔符,比如x-request-id。Header的匹配同样是大小写敏感的 |
port | uint32 | 指定主机上的端口 |
sourceLabels | map<string,[StringMatch]> | 用一个或多个标签选择工作负载 |
gateways | string[] | 规则所涉及的Gateway的名称列表 |
VirtualService中的路由配置规则是有优先级的。如果在配置中定义了多条规则,则按照顺序优先匹配第一条,但是Header条件除外。如果匹配规则中设置了Header,则它具有最高优先级DestinationRuleDestionationRule通过和VirtualService成对出现的。它的功能是当VirtualService的路由生效后,配置一些策略并应用到请求中。另外,subset和标签的对应关系也被定义在DestinationRule中DestinationRule的配置,除定义了VirtualService中要使用的两个subset外,还设置以随机的方式对reviews服务进行负载均衡
Circuit Breaker),它是一种服务降级处理的方式。当某个服务出现故障后,为了不影响下游服务而对其设置断流操作。我们可以在DestinationRule中方便地实现这个功能。下面例子设置对reviews服务的最大连接只能有100个,如果超过这个数字就会断流

subset定义了策略,但没有定义对应的VirtualService,则该策略并不会执行。在这种情况下,Istio会以默认的方式(轮询)将请求改善给目标服务的全部版本。因此官方推荐的方式是给每个服务都定义路由规则,避免这种情况发生ServiceEntryServiceEntry。它也是一种配置资源,用来给服务网格内的服务提供外部URL的能力。Istio中的服务发现功能主要是依靠服务注册表实现的,ServiceEntry能够在注册表中添加外部服务,使得内部服务可以访问这些被添加的URL。因此,通过ServiceEntry就可以实现访问外部服务的能力。下面的例子展示了如何配置一个外部的URL“*.foo.com”,使得网格内部的服务可以通过HTTP协议的80端口来访问它
GatewayServiceEntry相反,外部请求想要访问网格内的服务就要用到Gateway。Gateway为进入网格的请求配置了一个负载均衡器,把VirtualService绑定到Gateway,这样就可以设置规则来控制进入的流量。比如下面的例子,为从外部进入Bookinfo网站的HTTPS流量配置了一个Gateway

VirtualService并与网关绑定起来。下面的例子在hosts中对上面定义的名为bookinfo-gateway的Gateway进行了绑定

Istio中的流量控制主要是由这4个配置资源共同协作完成的。首先鸪请求的主机(host)在VirtualService中是否有路由规则,如果有,则将请求发往对应的subset。接下来,如果发现当前subset在DestinationRule中定义了策略,则执行此策略。同时,还可以设置Gateway负责负载均衡以及为服务定义出口A/B测试Blue-Green Deployment)
Bookinfo应用中reviews服务模拟蓝绿部署。reviews服务有3个版本,v1是线上正在运行版本,v2是我们要更新上线的版本。需要做的就是制定 路由规则,将流量转移到v2版本上DestinationRuleVirtualService设置路由,将流量指向v1版本VirtualService,将流量切换到v2版本DestinationRule





VirtualService设置路由,将流量指向v1版本
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: productpage
spec:
hosts:
- productpage
http:
- route:
- destination:
host: productpage
subset: v1
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- route:
- destination:
host: ratings
subset: v1
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: details
spec:
hosts:
- details
http:
- route:
- destination:
host: details
subset: v1
http://localhost/productpage,看到评分部分没有星标显示的就是v1版本
VirtualService,将流量切换到v2版本v1版本),接下来编写VirtualService,将所有流量切换到reviews的v2版本上(绿色部署)。需要将reviews服务目标子集subset设置成v2即可apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v2
istioctl replace -f virtual-service-reviews-v2.yaml
v2版本上
Canary Release)
ID尾号、公司内部用户或者地理位置等)

Bug很难在开发环境中被发现,只有在线上环境中才能暴露出来,因此能利用真实环境和数据测试是发现疑难杂症的重要手段。另外,当发现问题时也可以很安全地回滚,并控制受影响的范围。它的缺点是需要在同一时间点管理多个版本(通常是两个 ,也可以同时部署更多版本)。另一个案例是,当发布的是客户端版本(如手机的App)时,就很难控制终端用户去更新版本,此时如果不同的客户端版本和后端进行通信,则需要进行向后兼容A/B测试一起使用,只不过侧重点不同。金丝雀发布的最终目的是发布新版本并完全替代旧版本,而A/B测试的主要目的是收集数据,比较两个版本的优劣reviews服务的v2是老版本,现在要发布v3版本。在完全切换到新版本前,通过金丝雀发布先将10%的流量转移到v3版本。和蓝绿部署不同 ,我们并不是把全部流量一下全切换到新版本,而是需要在配置中通过设置权重来实现流量转移VirtualService中设置两个版本的权重。为reviews服务增加到v3的目标节点,同时用weight标记分别设置v2为90,v3为10,即90%的流量指向v2老版本,10%的流量用来测试v3新版本apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
weight: 90
- destination:
host: reviews
subset: v3
weight: 10
istioctl replace -f reviews-v3-10.yaml
v3版本
A/B发布(分割测试或桶测试)
A/B测试在本质上和金丝雀的配置没有区别,都是进行流量转移 。我们使用另一种策略来演示。假设我们的目标是给登录用户和非登录用户展示不同的页面,使用match来匹配不同的用户
istioctl replace -f login-abtest.yaml
v3版本,而退出登录则只能看到没有星标的版本Istio里设置A/B测试非常方便,并且支持多种维度度。当然,A/B测试的最终目的是收集各项指标的数据,并根据数据做出决策Bookinfo中的reviews服务会调用ratings服务来进行评分显示(星标),我们给ratings服务设置一个7s的延迟,同时在reviews服务中设置1s超时,使得超过1s后停止对ratings服务的调用。超时使用timeout标记来配置istioctl replace -f samples/bookinfo/networking/virutlal-service-all-v1.yaml
reviews服务切换为v2版本,使得它可以调用ratings服务

ratings服务中加入2s的延迟
Bookinfo页面,可以看到正常显示星标,但页面需要加载2s左右。最后,为reviews:v2服务的请求加入1s的请求超时

reviews服务调用ratings时有2s的延迟,使得服务无法在1s限制内返回,这就触发了超时。在Istio中,服务默认的超时时间是15sIP和端口
httpbin作为后端服务kubectl apply if samples/httpbin/httpbin.yaml
DestinationRule,为httpbin服务创建熔断器

上游主机的连接池配置httpbin服务的客户端,来测试熔断机制。我们使用Istio官方推荐的负载测试工具Fortio,它能够以并发的方式发送HTTP请求来模拟多用户调用kubectl apply -f <(istioctl kube-inject -f samples/httpbin/sample-client/fortio-deploy.yaml)>


Fortio的Pod,然后进入它的终端来调用httpbin服务。服务返回了状态码200,调用成功

maxConnections)和最大请求数(http1MaxPendingRequests)指定为1,即如果有一个并发请求,就会触发熔断。下面利用3个并发操作来发送30个请求进行测试


istio-proxy的统计信息来进一步查看熔断的情况

upstreamrqpending_overflow的值 是9,说明有9次请求被熔断了Istio中可以通过定义DestinationRule方便地实现熔断Istio可以非常方便地实现各种流量控制。Istio的流量管理功能主要是依靠Pilot组件和Envoy代理协作完成的。流量管理的规则配置由4个配置资源完成VirtualService定义路由规则DestinationRule在路由生效后定义对于请求的策略ServiceEntry提供了网格内服务可以访问外界服务的能力Gateway可以让外部服务调用网格内服务A/B测试Istio可以很轻松地实现这些策略。分布式系统的弹性和应对故障的能力非常重要,决定了系统的稳定性和可用性。超时、重试以及熔断等功能都可以很容易地在Istio中实现