使用Istio可以根据权重和HTTP header配置动态请求路由,根据权重和HTTP header将请求路由到同一个微服务的不同版本。

前面我们部署的Bookinfo示例应用由4个独立的微服务组成。

BookInfo Application with Istio

其中对于reviews Service部署了从v1到v3三个不同的版本。

1kubectl get pod  -l app=reviews
2NAME                          READY     STATUS    RESTARTS   AGE
3reviews-v1-fdbf674bb-zwbft    2/2       Running   0          1d
4reviews-v2-5bdc5877d6-dfgl2   2/2       Running   0          1d
5reviews-v3-dd846cc78-g9w9s    2/2       Running   0          1d

默认情况下请求被随机负载到这三个不同版本的实例上,我们可以多次刷新http://192.168.61.12/productpage,该页面上的Book Reviews内容区的随机会出现“红色的五颗小星星”、“黑色的五颗小星星”、“没有小星星”,分别对应v3、v2、v1。这是因为我们并没有指定缺省的路由版本,istio以round robin的形式将请求路由到所有可用的版本上。

bookinfo-reviews-v3 bookinfo-reviews-v2 bookinfo-reviews-v1

1.将请求路由到固定版本的服务上

通过Virtual Service并指定默认的微服务版本,可以仅仅将请求路由到指定的版本。执行下面的命令将所有的请求路由到review service的v1版本:

1cd istio-1.0.0
2kubectl create -f samples/bookinfo/networking/destination-rule-all.yaml
3kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml

samples/bookinfo/networking/virtual-service-all-v1.yaml的内容如下:

 1apiVersion: networking.istio.io/v1alpha3
 2kind: VirtualService
 3metadata:
 4  name: productpage
 5spec:
 6  hosts:
 7  - productpage
 8  http:
 9  - route:
10    - destination:
11        host: productpage
12        subset: v1
13---
14apiVersion: networking.istio.io/v1alpha3
15kind: VirtualService
16metadata:
17  name: reviews
18spec:
19  hosts:
20  - reviews
21  http:
22  - route:
23    - destination:
24        host: reviews
25        subset: v1
26---
27apiVersion: networking.istio.io/v1alpha3
28kind: VirtualService
29metadata:
30  name: ratings
31spec:
32  hosts:
33  - ratings
34  http:
35  - route:
36    - destination:
37        host: ratings
38        subset: v1
39---
40apiVersion: networking.istio.io/v1alpha3
41kind: VirtualService
42metadata:
43  name: details
44spec:
45  hosts:
46  - details
47  http:
48  - route:
49    - destination:
50        host: details
51        subset: v1
52---

使用kubectl查看一下virtualservices:

 1kubectl get virtualservices
 2NAME          AGE
 3bookinfo      1d
 4details       19s
 5productpage   19s
 6ratings       19s
 7reviews       19s
 8
 9kubectl get destinationrules
10NAME          AGE
11details       52s
12productpage   52s
13ratings       52s
14reviews       52s

由于配置信息是以异步的形式分发到代理的,所以创建好上面这些VirtualService后需要等待数秒后再去访问http://192.168.61.12/productpage。此时无论我们刷新多少次,Book Reviews内容区都不会再有星星出现。

bookinfo-reviews-v1

这是因为我们通过配置istio将所有到reviews Service的请求都路由到了v1版本的实例上。

2.基于用户标识进行请求路由

下面我们尝试将来自指定用户的请求路由到指定版本的服务上。这里将来自用户名为jason的请求路由到reivews Service的v2版本上。 需要注意的是istio并不会与我们微服务中的业务逻辑耦合,因此istio代理并不知道具体是哪个一个用户在访问服务。 这里实际上是将productpage service到reviews service的请求上加上了一个end-user的请求头,通过判断请求头实现的。

执行下面的命令:

1kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml

查看一下virtual-service-reviews-test-v2.yaml的内容:

 1apiVersion: networking.istio.io/v1alpha3
 2kind: VirtualService
 3metadata:
 4  name: reviews
 5spec:
 6  hosts:
 7    - reviews
 8  http:
 9  - match:
10    - headers:
11        end-user:
12          exact: jason
13    route:
14    - destination:
15        host: reviews
16        subset: v2
17  - route:
18    - destination:
19        host: reviews
20        subset: v1

可以看到加入了header end-userjason的路由规则,当请求头里的end-user=jason时,请求会被路由到reviews服务的v2版本的实例上,其他情况下都被路由到v1版本的实例上。测试以jason用户名登录,密码为空即可,登录后再访问http://192.168.61.12/productpage,多次刷新页面, Book Reviews内容区都将是黑色的小星星。 而以其他用户名或是不登录的情况访问都将不会看到小星星。

在完成了前面的两个实验后,使用kubectl delete -f samples/bookinfo/networking/virtual-service-all-v1.yaml完成清理工作,便于我们后边进一步的实验。

3.总结

已经体验了istio在对配置请求路由方面的管理微服务间流量的魔力,实际上为了实现这些魔力,Istio对部署在Kubernetes上的Pod和Service有一些基本的要求:

  • Service的端口必须正确命名:命名的规范是<protocol>[-<suffix>],其中suffix后缀部分可以省略。如在bookinfo示例中的reviews Service:

     1apiVersion: v1
     2kind: Service
     3metadata:
     4  name: reviews
     5  labels:
     6    app: reviews
     7spec:
     8  ports:
     9  - port: 9080
    10    name: http
    11  selector:
    12    app: reviews
    

    name为http,表示这是一个http服务,这样才可以使用istio的7层路由功能,才可以使用http header。port命名支持的protocol包含:httphttp2grpcmongoredis,istio可以通过这些协议的内容来实现不同的路由功能。如果对Kubernetes Service Port的命名没有指定protocol的前缀,则Istio将认为该端口是普通的TCP流量。

  • Service的关联:Pod必须被关联到Kubernetes服务上。如果一个Pod关联到多个Service上,则这些Service不能在同一端口上使用不同的协议,例如HTTP和TCP

  • Deployment应该带有app和version的Label:在使用Kubernetes的Deployment部署Pod的时候,应该显示的为Deployment加上app及version标签。app标签会在分布式追踪的过程中被用来加入上下文信息,istio还会用app和versio标签来给遥测metrics加入上下文数据

参考