Istio实现金丝雀发布

222 阅读3分钟

创建catalog服务的v1版本

yaml文件如下

# catalog.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: catalog
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: catalog
  name: catalog
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 3000
  selector:
    app: catalog
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: catalog
    version: v1
  name: catalog
spec:
  replicas: 1
  selector:
    matchLabels:
      app: catalog
      version: v1
  template:
    metadata:
      labels:
        app: catalog
        version: v1
    spec: 
      serviceAccountName: catalog
      containers:
      - env:
        - name: KUBERNETES_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        image: istioinaction/catalog:latest
        imagePullPolicy: IfNotPresent
        name: catalog
        ports:
        - containerPort: 3000
          name: http
          protocol: TCP
        securityContext:
          privileged: false

应用yaml文件

[root@node1 catalog]# kubectl apply -f catalog.yaml 
serviceaccount/catalog created
service/catalog created
deployment.apps/catalog created

查看Pod

[root@node1 catalog]# kubectl get pod 
NAME                          READY   STATUS      RESTARTS   AGE
catalog-77fdb4997c-xdk5d      1/1     Running     0          81s

向集群外公开catalog服务

创建Gateway

# catalog-gateway.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: catalog-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "catalog.istioinaction.io"

应用yaml文件

[root@node1 catalog]# kubectl apply -f catalog-gateway.yaml 
gateway.networking.istio.io/catalog-gateway created

创建VirtualService

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: catalog-vs-from-gw
spec:
  hosts:
  - "catalog.istioinaction.io"
  gateways:
  - catalog-gateway
  http:
  - route:
    - destination:
        host: catalog

应用yaml文件

[root@node1 catalog]# kubectl apply -f catalog-vs.yaml 
virtualservice.networking.istio.io/catalog-vs-from-gw created

测试服务

编辑发起请求的客户端的/etc/hosts文件,添加catalog.istioinaction.io的解析

➜  code curl http://catalog.istioinaction.io/items

创建catalog服务V2版本

---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: catalog
    version: v2
  name: catalog-v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: catalog
      version: v2
  template:
    metadata:
      labels:
        app: catalog
        version: v2
    spec:
      containers:
      - env:
        - name: KUBERNETES_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: SHOW_IMAGE
          value: "true"
        image: istioinaction/catalog:latest
        imagePullPolicy: IfNotPresent
        name: catalog
        ports:
        - containerPort: 3000
          name: http
          protocol: TCP
        securityContext:
          privileged: false

应用yaml文件

[root@node1 catalog]# kubectl apply -f catalog-deployment-v2.yaml 
deployment.apps/catalog-v2 created

查看Pod

[root@node1 catalog]# kubectl get pods
NAME                          READY   STATUS      RESTARTS      AGE
catalog-77fdb4997c-xdk5d      1/1     Running     1 (10m ago)   45m
catalog-v2-846f658874-qzzjt   1/1     Running     0             76s

将所有流量路由到V1版本

创建一个DestinationRule,将不同版本指定为subnet,这样Istio就可以区分服务的不同版本了

# catalog-dest-rule.yaml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: catalog
spec:
  host: catalog
  subsets:
  - name: version-v1
    labels:
      version: v1
  - name: version-v2
    labels:
      version: v2

应用yaml文件

[root@node1 catalog]# kubectl apply -f catalog-dest-rule.yaml 
destinationrule.networking.istio.io/catalog created

首先将所有流量路由到V1版本

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: catalog-vs-from-gw
spec:
  hosts:
  - "catalog.istioinaction.io"
  gateways:
  - catalog-gateway
  http:
  - route:
    - destination:
        host: catalog # 此处对应创建的DestinationRule
        subset: version-v1  # 指定子集

应用yaml文件

[root@node1 catalog]# kubectl apply -f catalog-vs-v1.yaml 
virtualservice.networking.istio.io/catalog-vs-from-gw configured

测试

for i in {1..10};do curl http://catalog.istioinaction.io/items -H "Host: catalog.istioinaction.io"; printf "\n\n"; done

将特定请求路由到V2

将包含HTTP头x-istio-cohort:internal的任何流量路由到catalog服务的v2版本

在Istio VirtualService资源中指定这个请求路由

# catalog-vs-v2-request.yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: catalog-vs-from-gw
spec:
  hosts:
  - "catalog.istioinaction.io"
  gateways:
  - catalog-gateway
  http:
  - match:  # 匹配到指定的HTTP头部路由到V2
    - headers:
        x-istio-cohort:
          exact: "internal"
    route:
    - destination:
        host: catalog
        subset: version-v2
  - route:
    - destination:
        host: catalog
        subset: version-v1

应用yaml文件

[root@node1 catalog]# kubectl apply -f catalog-vs-v2-request.yaml 
virtualservice.networking.istio.io/catalog-vs-from-gw configured

请求测试

curl http://catalog.istioinaction.io/items -H "Host: catalog.istioinaction.io" -H "x-istio-cohort: internal"

v2版本返回的数据比v1版本多这个字段

image.png