Argo Rollouts TrafficRouting结合Istio进行Canary流量管理基础

发布时间 2023-12-18 09:48:27作者: 小吉猫

Argo Rollouts TrafficRouting概述

流量治理技术实现如下:
1. 按百分比进行流量管理(即 5% 的流量应流向新版本,其余流量流向稳定版本)
2. 基于标头的路由(即将带有特定标头的请求发送到新版本)
3. 镜像流量,其中所有流量都被复制并并行发送到新版本(但响应被忽略)

TrafficRouting 配置

apiVersion: argoproj.io/v1alpha1
kind: Rollout
spec:
  ...
  strategy:
    canary:
      ...
      trafficRouting:
        alb: <Object>
        ambassador: <Object>
        apisix: <Object>
        appMesh: <Object>
        nginx: <Object>
        plugins: <Object>
        smi: <Object>
        traefik: <Object>       
        managedRoutes:               # 管理路由列表
          - name: priority-route-1
          - name: priority-route-2
          - name: priority-route-3
          - name: set-header-1       # 标头路由
          - name: mirror-route       # 镜像路由
        istio: <Object>
      steps:
      - setCanaryScale:              # 设定Canary扩容期间Pod扩增与流量扩增的对应关系    
          weight: 25                 # 明确设定Canary RS的规模为该处指定的比例,但不改变先前设定的流量比例;
      - setMirrorRoute:              # 镜像路由
          name: mirror-route         # 镜像路由的名称。
          percentage: 35             # 要镜像的匹配流量的百分比是多少
          match:                     #  标头路由的匹配规则,如果缺少此规则,则相当于删除该路由。
            - method:
                exact: GET
              path:
                prefix: /
      - setWeight: 20                # 设定Canary版本ReplicSet激活的Pod比例,以及调度至Canary版本的流量比例;
      - setHeaderRoute:              # 标头路由
          name: "set-header-1"       # 标头路由的名称。
          match:                     # 标头匹配规则是 headerName、headerValue 对的数组。
          - headerName: Custom-Header1 # 要匹配的标头名称
            headerValue:
              exact: Mozilla
          - headerName: Custom-Header2 # or Custom-Header2 has a prefix Mozilla
            headerValue:
              prefix: Mozilla
          - headerName: Custom-Header3 # or Custom-Header3 value match regex: Mozilla(.*)
            headerValue:
              regex: Mozilla(.*)  

基于host进行流量分割

配置说明

基于host进行流量分割:
1. 在两个主机名或 Kubernetes 服务之间进行分割:canaryService和stableService。
2. 每个Service代表着一个Host
3. 分别为Canary和Stable的Pod添加rollouts-pod-template-hash标签,其值为相应的RS模板的hash值;
4. 动态调整VS上route中Canary Service和Stable Service的weight进行流量迁移

VirtualService 配置

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: rollout-vsvc
spec:
  gateways:
  - istio-rollout-gateway
  hosts:
  - istio-rollout.dev.argoproj.io
  http:
  - name: primary        # referenced in canary.trafficRouting.istio.virtualService.routes
    route:
    - destination:
        host: stable-svc # referenced in canary.stableService
      weight: 100
    - destination:
        host: canary-svc # referenced in canary.canaryService
      weight: 0

Service 配置

apiVersion: v1
kind: Service
metadata:
  name: canary-svc
spec:
  ports:
  - port: 80
    targetPort: http
    protocol: TCP
    name: http
  selector:
    app: rollouts-demo
    # This selector will be updated with the pod-template-hash of the canary ReplicaSet. e.g.:
    # rollouts-pod-template-hash: 7bf84f9696
---
apiVersion: v1
kind: Service
metadata:
  name: stable-svc
spec:
  ports:
  - port: 80
    targetPort: http
    protocol: TCP
    name: http
  selector:
    app: rollouts-demo
    # This selector will be updated with the pod-template-hash of the stable ReplicaSet. e.g.:
    # rollouts-pod-template-hash: 123746c88d

Rollout 配置

 

apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: rollout-example
spec:
  ...
  strategy:
    canary:
      canaryService: canary-svc  # required
      stableService: stable-svc  # required
      trafficRouting:
        istio:
          virtualService:
            name: rollout-vsvc   # required
            routes:
            - primary            # optional if there is a single route in VirtualService, required otherwise
      steps:
      - setWeight: 5
      - pause:
          duration: 10m

基于subset进行流量分割

基于subset进行流量分割:
1. 在两个 Istio DestinationRule 子集之间进行分割:canarySubsetName和stableSubsetName,共用同一个Service。
2. 需要通过DestinationRule将Service的后端的分别隶属于Canary和Stable的Pod划分到不同的subset
3. Pod上的子集划分依赖于一个动态变动的标签进行:canary rollouts-pod-template-hash 和 stable rollouts-pod-template-hash。
4. 分别为Canary和Stable对应的subset上的Pod设定rollouts-pod-template-hash,其值为相应的RS模板的hash值
5. 动态调整VS上route中Canary subset和Stable subset的weight进行流量迁移

VirtualService 配置

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: rollout-vsvc
spec:
  gateways:
  - istio-rollout-gateway
  hosts:
  - istio-rollout.dev.argoproj.io
  http:
  - name: primary       # referenced in canary.trafficRouting.istio.virtualService.routes
    route:
    - destination:
        host: rollout-example
        subset: stable  # referenced in canary.trafficRouting.istio.destinationRule.stableSubsetName
      weight: 100
    - destination:
        host: rollout-example
        subset: canary  # referenced in canary.trafficRouting.istio.destinationRule.canarySubsetName
      weight: 0

DestinationRule 配置 

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: rollout-destrule
spec:
  host: rollout-example
  subsets:
  - name: canary   # referenced in canary.trafficRouting.istio.destinationRule.canarySubsetName
    labels:        # labels will be injected with canary rollouts-pod-template-hash value
      app: rollout-example
  - name: stable   # referenced in canary.trafficRouting.istio.destinationRule.stableSubsetName
    labels:        # labels will be injected with stable rollouts-pod-template-hash value
      app: rollout-example

Service 配置

apiVersion: v1
kind: Service
metadata:
  name: rollout-example
spec:
  ports:
  - port: 80
    targetPort: http
    protocol: TCP
    name: http
  selector:
    app: rollout-example

Rollout 配置

apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: rollout-example
spec:
  ...
  strategy:
    canary:
      trafficRouting:
        istio:
          virtualService:
            name: rollout-vsvc        # required
            routes:
            - primary                 # optional if there is a single route in VirtualService, required otherwise
          destinationRule:
            name: rollout-destrule    # required
            canarySubsetName: canary  # required
            stableSubsetName: stable  # required
      steps:
      - setWeight: 5
      - pause:
          duration: 10m

基于TCP进行流量分割

VirtualService 配置

VirtualService 必须包含 TCP 路由以及 Rollout 中引用的匹配端口。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: rollout-vsvc
spec:
  gateways:
    - istio-rollout-gateway
  hosts:
    - istio-rollout.dev.argoproj.io
  tcp:
    - match:
        - port: 3000
      route:
        - destination:
            host: stable-svc # referenced in canary.stableService
          weight: 100
        - destination:
            host: canary-svc # referenced in canary.canaryService
          weight: 0

Rollout 配置

apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: rollout-example
spec:
  ...
  strategy:
    canary:
      canaryService: canary-svc  # required
      stableService: stable-svc  # required
      trafficRouting:
        istio:
          virtualService:
            name: rollout-vsvc   # required
            tcpRoutes:
              # Below fields are optional but if defined, they should match exactly with at least one of the TCP route match rules in your VirtualService
              - port: 3000 # Only required if you want to match any rule in your VirtualService which contains this port
      steps:
      - setWeight: 5
      - pause:
          duration: 10m

与 GitOps 集成

Argo CD 与 Argo Rollouts 一起使用时,因Argo Rollouts 会动态调整vs会导致权重的瞬时摆动。解决办法如下:

Application 忽略 VirtualService 中的差异 

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: guestbook
spec:
  ignoreDifferences:
  - group: networking.istio.io
    kind: VirtualService
    jsonPointers:
    - /spec/http/0

配置 Application 仅应用 OutOfSync 资源 

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: guestbook
spec:
  syncPolicy:
    syncOptions:
    - ApplyOutOfSyncOnly=true
默认情况下,当 Argo CD 同步application时,它会针对 git 中作为application一部分的所有资源运行 kubectl apply。 ApplyOutOfSyncOnly=true 同步选项指示 Argo CD 跳过应用它已认为已同步的资源,而仅应用不同步的资源。当与ignoreDifferences 功能结合使用时,此选项提供了一种管理Argo CD 和Argo Rollouts 之间VirtualService 所需状态冲突的方法。

参考文档

https://argoproj.github.io/argo-rollouts/features/traffic-management/istio/