【玩转服务网格】如何使用网格进行灰度发布

102 阅读4分钟

本文的目的:指定请求header中特定kv的路由到V2版本。

首先明确两个istio中的概念。

  • VirtualService:配置路由规则,控制请求流量如何分发到服务上。
  • DestinationRule:路由生效后,配置请求和应用的策略集。

为了更好的呈现操作过程和步骤,实验中的yaml文件放在最后一节中

部署服务

kubectl create ns canary
kubectl label ns canary istio-injection=enabled
kubectl apply -f canary.yaml -n canary
kubectl apply -f toolbox.yaml -n canary
  • 查看pod信息
xxx@xxx-virtual-machine:~/istio/101-master/module12/istio/5.canary$ kubectl get pod -n canary
NAME                       READY   STATUS    RESTARTS   AGE
canary-5d48fc54d5-7wc5d    2/2     Running   0          9m37s
toolbox-78555898fb-ntsc4   2/2     Running   0          9m36s

进到客户端toolbox容器中

image.png

部署新版本服务

两个版本的label一个是v1,一个v2.

kubectl apply -f canary-v2.yaml -n canary

查看版本部署情况

xxx@xxx-virtual-machine:~$ kubectl get pod -n canary --show-labels -l app=canary -o wide
NAME                         READY   STATUS    RESTARTS   AGE     IP            NODE       NOMINATED NODE   READINESS GATES   LABELS
canary-5d48fc54d5-7wc5d      2/2     Running   0          5h48m   172.17.0.11   minikube   <none>           <none>            app=canary,pod-template-hash=5d48fc54d5,security.istio.io/tlsMode=istio,service.istio.io/canonical-name=canary,service.istio.io/canonical-revision=v1,version=v1
canary-v2-599c5bc865-lvdl4   2/2     Running   0          3m31s   172.17.0.13   minikube   <none>           <none>            app=canary,pod-template-hash=599c5bc865,security.istio.io/tlsMode=istio,service.istio.io/canonical-name=canary,service.istio.io/canonical-revision=v2,version=v2

查看service信息

xxx@xxx-virtual-machine:~$ kubectl get svc -n canary -o wide
NAME     TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE     SELECTOR
canary   ClusterIP   10.99.158.15   <none>        80/TCP    5h47m   app=canary
xxx@xxx-virtual-machine:~$ kubectl get ep -n canary -o wide
NAME     ENDPOINTS                       AGE
canary   172.17.0.11:80,172.17.0.13:80   5h47m

配置istio规则

service也可以进行灰度发布的流量控制,但是属于粗粒度的,比如上述service中有两个pod,则流量就会有50%的到新版本中。这样就不够灵活。 为了解决上述痛点,

  • istio引入了DestinationRule(简称DR)对service代理的不同label的pod进行分组管理定义(即为subsets,同时还可以定义负载均衡策略);
  • 然后引入了VirtualService(简称VS)对DestinationRule中定义的分组进行流量管理。定义哪些特征的流量路由到DR中定义的哪个subset中,流入的流量比例是多少。

DR和VS中都有一个必填字段:hosts,代表对应的service信息。

k apply -f istio-specs.yaml -n canary

该demo中配置了请求header中有user是jesse的就会路由到DR中定义的v2 subset中。 当然也可以使用weight进行精确比例路由进行分组,此处不再演示。

image.png

还可以使用上一篇# 【玩转服务网格】初试Istio中提到的istioctl检查路由规则是否已经下发到客户端toolbox的sidecar中。 istioctl pc route -n canary toolbox-78555898fb-ntsc4 -ojson找到domains为canary的route内容,可以看到确实已经完成下发。 image.png 进一步查看下cluster是canary的endpoint信息。

xxx@xxx-virtual-machine:~/istio/101-master/module12/istio/6.fault-inject$ istioctl pc ep -n canary toolbox-78555898fb-ntsc4 | grep canary
172.17.0.11:80                                          HEALTHY     OK                outbound|80|v1|canary.canary.svc.cluster.local
172.17.0.11:80                                          HEALTHY     OK                outbound|80||canary.canary.svc.cluster.local
172.17.0.13:80                                          HEALTHY     OK                outbound|80|v2|canary.canary.svc.cluster.local
172.17.0.13:80                                          HEALTHY     OK                outbound|80||canary.canary.svc.cluster.local

进入客户端toolbox中,进行模拟请求

curl canary/hello -H "user: jesse"

image.png

其他的路由匹配方式

  • uri、scheme、method、authority:4个字段都是StringMatch类型,在匹配请求时都支持exact、prefix和regex三种模式的匹配,分别表示完全匹配输入的字符串,前缀方式匹配和正则表达式匹配。

  • headers:匹配请求中的Header,是一个Map类型。Map的Key是字符串类型,Value 仍然是 StringMatch 类型。即对于每一个 Header 的值,都可以使用精确、前缀和正则三种方式进行匹配。如下所示为自定义headers中source的取值为“north”,并且uri以“/advertisement”开头的请求:

- match:
 - headers:
     source:
       exact: north
   uri:
     prefix: "/advertisement/"
  • port:表示请求的服务端口。大部分服务只开放了一个端口,这也是在微服务实践中推荐的做法,在这种场景下可以不用指定port。

  • sourceLabels:是一个 map 类型的键值对,表示请求来源的负载匹配标签。这在很多时候非常有用,可以对一组服务都打一个相同的标签,然后使用sourceLabels字段对这些服务实施相同的流量规则。在Kubernetes平台上,这里的Label就是Pod上的标签。

http:
- match:
 - sourceLables:
     app: frontend
     version: v2
  • gateways:表示规则应用的Gateway名称,语义同VirtualService上面的gateways定义,是一个更细的Match条件,会覆盖在VirtualService上配置的gateways。

文章中用到的yaml

  • toolbox.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: toolbox
spec:
  replicas: 1
  selector:
    matchLabels:
      app: toolbox
  template:
    metadata:
      labels:
        app: toolbox
        access: "true"
    spec:
      containers:
        - name: toolbox
          image: centos
          command:
            - tail
            - -f
            - /dev/null
  • canary.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: canary
spec:
  replicas: 1
  selector:
    matchLabels:
      app: canary
  template:
    metadata:
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "80"
      labels:
        app: canary
        version: v1
    spec:
      containers:
        - name: canary
          imagePullPolicy: Always
          image: cncamp/httpserver:v1.0-metrics
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: canary
spec:
  ports:
    - name: http
      port: 80
      protocol: TCP
      targetPort: 80
  selector:
    app: canary
  • canary-v2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: canary-v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: canary
  template:
    metadata:
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "80"
      labels:
        app: canary
        version: v2
    spec:
      containers:
        - name: canary
          imagePullPolicy: Always
          image: cncamp/httpserver:v2.0-metrics
          ports:
            - containerPort: 80
  • istio-specs.yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: canary
spec:
  hosts:
    - canary
  http:
    - match:
        - headers:
            user:
              exact: jesse
      route:
        - destination:
            host: canary
            subset: v2
    - route:
      - destination:
          host: canary
          subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: canary
spec:
  host: canary
  trafficPolicy:
    loadBalancer:
      simple: RANDOM
  subsets:
    - name: v1
      labels:
        version: v1
    - name: v2
      labels:
        version: v2
      trafficPolicy:
        loadBalancer:
          simple: ROUND_ROBIN