Istio
中定义了一个简单的配置模型,可以很方便地进行规则的配置。在示例练习前,需要先了解一下与规则配置相关的重要概念和基本的配置方法Istio
中定义了4种针对流量管理的配置资源定义路由规则,控制请求如何被路由到服务
VirtualService
VirtualService
的主要功能是定义路由规则,使请求(流量)可以依据这些规则被分发到对应的服务。路由的方式也有很多种,可以根据请求的源或目标地址路由,也可以根据路径、头信息,或者服务版本进行路由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次,每次的超时时间为2sfault
关键字来设置故障注入。在下面的例子中我们注入了一个延迟故障,使得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
,则它具有最高优先级DestinationRule
DestionationRule
通过和VirtualService
成对出现的。它的功能是当VirtualService
的路由生效后,配置一些策略并应用到请求中。另外,subset
和标签的对应关系也被定义在DestinationRule
中DestinationRule
的配置,除定义了VirtualService
中要使用的两个subset
外,还设置以随机的方式对reviews
服务进行负载均衡Circuit Breaker
),它是一种服务降级处理的方式。当某个服务出现故障后,为了不影响下游服务而对其设置断流操作。我们可以在DestinationRule
中方便地实现这个功能。下面例子设置对reviews
服务的最大连接只能有100个,如果超过这个数字就会断流subset
定义了策略,但没有定义对应的VirtualService
,则该策略并不会执行。在这种情况下,Istio
会以默认的方式(轮询)将请求改善给目标服务的全部版本。因此官方推荐的方式是给每个服务都定义路由规则,避免这种情况发生ServiceEntry
ServiceEntry
。它也是一种配置资源,用来给服务网格内的服务提供外部URL
的能力。Istio
中的服务发现功能主要是依靠服务注册表实现的,ServiceEntry
能够在注册表中添加外部服务,使得内部服务可以访问这些被添加的URL
。因此,通过ServiceEntry
就可以实现访问外部服务的能力。下面的例子展示了如何配置一个外部的URL
“*.foo.com
”,使得网格内部的服务可以通过HTTP
协议的80端口来访问它Gateway
ServiceEntry
相反,外部请求想要访问网格内的服务就要用到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
版本上DestinationRule
VirtualService
设置路由,将流量指向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
中实现