Todos os produtos
Search
Central de documentação

Alibaba Cloud Service Mesh:Use traffic labels to implement an end-to-end canary release

Última atualização: Sep 25, 2026

As liberações canário padrão encaminham o tráfego para diferentes versões de um único serviço com base em proporções de peso. Isso funciona para serviços isolados, mas falha quando uma requisição abrange vários serviços em uma cadeia de chamadas. Por exemplo, se o tráfego canário chega ao Serviço A, mas o sistema o encaminha aleatoriamente para a versão base do Serviço B, os resultados dos testes tornam-se não confiáveis.

As liberações canário de ponta a ponta resolvem esse problema ao adicionar tags ao tráfego de entrada no gateway e propagar essa tag por toda a cadeia de chamadas. Cada serviço lê a tag e encaminha a requisição para a versão correspondente, para que o tráfego canário flua exclusivamente pelas versões canário e o tráfego base permaneça nas versões base.

O Service Mesh (ASM) implementa isso por meio de duas capacidades:

  • Rotulagem de tráfego: uma CustomResourceDefinition (CRD) TrafficLabel que extrai rótulos dos cabeçalhos de requisição e os associa aos fluxos de tráfego

  • Roteamento baseado em rótulos: regras do VirtualService que encaminham o tráfego para subconjuntos correspondentes ao valor do rótulo

Como funciona

O diagrama a seguir mostra a cadeia de chamadas usada neste tutorial. O Serviço A (mocka) recebe o tráfego de entrada e chama o Serviço B (mockb):

Application service call chain

Ambos os serviços têm duas versões implantadas: base e canary. Sem rótulos de tráfego, o balanceamento de carga round-robin distribui as requisições entre as versões.

Após configurar os rótulos de tráfego, o sistema:

  1. Lê o cabeçalho my-asm-prefer-tag das requisições recebidas no gateway para classificar o tráfego como version-base ou version-canary.

  2. Encaminha a requisição para a versão correspondente do Serviço A.

  3. Propaga a tag para o Serviço B por meio do cabeçalho my-trace-id, para que o Serviço B também encaminhe para a versão correspondente.

Nota

As suas aplicações devem propagar o cabeçalho HTTP nas chamadas de serviço. Os serviços de exemplo neste tutorial já incluem essa lógica. Para as suas próprias aplicações, implemente a propagação do cabeçalho utilizado na rotulagem de tráfego. Consulte src/mock-abc/go/main.go no código de exemplo para obter uma implementação de referência.

Pré-requisitos

Antes de iniciar, certifique-se de ter:

Arquivos de configuração de exemplo

Baixe os arquivos de configuração de exemplo usados neste tutorial. O pacote contém os seguintes arquivos:

Arquivo

Finalidade

application-base.yaml

Implanta as versões base do Serviço A (mocka) e do Serviço B (mockb)

application-canary.yaml

Implanta as versões canário de ambos os serviços

routing.yaml

Define o Gateway, os DestinationRules e os VirtualServices para o roteamento inicial

trafficlabel.yaml

Configura as CRDs TrafficLabel para a rotulagem de tráfego

vs-tf-mockb.yaml

Aplica o roteamento baseado em rótulos ao Serviço B

vs-tf-mocka.yaml

Aplica o roteamento baseado em rótulos ao Serviço A no gateway

vs-tf-mocka-90-10.yaml

Adiciona distribuição baseada em peso (90% base, 10% baseada em rótulos) ao Serviço A

application-base.yaml -- Implantações da versão base

apiVersion: v1
kind: Service
metadata:
  name: mocka
  labels:
    app: mocka
    service: mocka
spec:
  ports:
  - port: 8000
    name: http
  selector:
    app: mocka
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mocka-base
  labels:
    app: mocka
    version: base
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mocka
      version: base
  template:
    metadata:
      labels:
        app: mocka
        version: base
    spec:
      containers:
      - name: default
        image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/go-http-sample:tracing
        imagePullPolicy: Always
        env:
        - name: version
          value: base
        - name: app
          value: mocka
        - name: upstream_url
          value: "http://mockb:8000/"
        ports:
        - containerPort: 8000
---
apiVersion: v1
kind: Service
metadata:
  name: mockb
  labels:
    app: mockb
    service: mockb
spec:
  ports:
  - port: 8000
    name: http
  selector:
    app: mockb
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mockb-base
  labels:
    app: mockb
    version: base
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mockb
      version: base
  template:
    metadata:
      labels:
        app: mockb
        version: base
    spec:
      containers:
      - name: default
        image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/go-http-sample:tracing
        imagePullPolicy: Always
        env:
        - name: version
          value: base
        - name: app
          value: mockb
        ports:
        - containerPort: 8000

application-canary.yaml -- Implantações da versão canário

apiVersion: v1
kind: Service
metadata:
  name: mocka
  labels:
    app: mocka
    service: mocka
spec:
  ports:
  - port: 8000
    name: http
  selector:
    app: mocka
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mocka-canary
  labels:
    app: mocka
    version: canary
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mocka
      version: canary
  template:
    metadata:
      labels:
        app: mocka
        version: canary
    spec:
      containers:
      - name: default
        image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/go-http-sample:tracing
        imagePullPolicy: Always
        env:
        - name: version
          value: canary
        - name: app
          value: mocka
        - name: upstream_url
          value: "http://mockb:8000/"
        ports:
        - containerPort: 8000
---
apiVersion: v1
kind: Service
metadata:
  name: mockb
  labels:
    app: mockb
    service: mockb
spec:
  ports:
  - port: 8000
    name: http
  selector:
    app: mockb
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mockb-canary
  labels:
    app: mockb
    version: canary
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mockb
      version: canary
  template:
    metadata:
      labels:
        app: mockb
        version: canary
    spec:
      containers:
      - name: default
        image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/go-http-sample:tracing
        imagePullPolicy: Always
        env:
        - name: version
          value: canary
        - name: app
          value: mockb
        ports:
        - containerPort: 8000

Etapa 1: Implantar os serviços de exemplo

  1. Ative a injeção automática de proxy sidecar para o namespace de destino (default neste exemplo). Consulte Ative a injeção automática de proxy sidecar.

  2. Conecte-se ao cluster do Container Service for Kubernetes (ACK) com o kubectl e implante os serviços de exemplo:

    kubectl apply -n default -f application-base.yaml
    kubectl apply -n default -f application-canary.yaml

Etapa 2: Configure as regras de roteamento iniciais

Configure o Gateway, os DestinationRules e os VirtualServices para estabelecer o roteamento básico sem rótulos de tráfego.

  1. Crie um arquivo chamado routing.yaml com o seguinte conteúdo:

    Conteúdo de routing.yaml

    apiVersion: networking.istio.io/v1beta1
    kind: Gateway
    metadata:
      name: simple-gateway
    spec:
      selector:
        istio: ingressgateway
      servers:
        - hosts:
            - "*"
          port:
            name: http
            number: 80
            protocol: HTTP
    ---
    apiVersion: networking.istio.io/v1beta1
    kind: DestinationRule
    metadata:
      name: dr-mocka
    spec:
      host: mocka
      trafficPolicy:
        loadBalancer:
          simple: ROUND_ROBIN
      subsets:
        - labels:
            version: base
          name: version-base
        - labels:
            version: canary
          name: version-canary
    ---
    apiVersion: networking.istio.io/v1beta1
    kind: DestinationRule
    metadata:
      name: dr-mockb
    spec:
      host: mockb
      trafficPolicy:
        loadBalancer:
          simple: ROUND_ROBIN
      subsets:
        - labels:
            version: base
          name: version-base
        - labels:
            version: canary
          name: version-canary
    ---
    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: vs-gateway-mocka
    spec:
      gateways:
      - simple-gateway
      hosts:
        - "*"
      http:
      - route:
          - destination:
              host: mocka
    ---
    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: vs-mockb
    spec:
      hosts:
        - mockb
      http:
        - route:
            - destination:
                host: mockb

    Esta configuração:

    • Cria um Gateway (simple-gateway) que aceita todo o tráfego HTTP na porta 80

    • Define DestinationRules para ambos os serviços com os subconjuntos version-base e version-canary

    • Cria VirtualServices que encaminham o tráfego sem lógica baseada em rótulos

  2. Conecte-se à instância do ASM com o kubectl e aplique as regras de roteamento:

    kubectl apply -n default -f routing.yaml
  3. Verifique se ambas as versões do serviço estão acessíveis.

    1. Obtenha o endereço IP público do gateway de entrada no console do ASM. Consulte Obtenha o endereço IP do gateway de entrada do ASM.

    2. Defina o IP do gateway como uma variável de ambiente. Substitua <gateway-ip> pelo endereço IP real:

      export ASM_GATEWAY_IP=<gateway-ip>
    3. Envie requisições de teste:

      for i in {1..200};  do curl   -H'my-asm-prefer-tag: version-base'  -H'my-trace-id: x000'$i  http://${ASM_GATEWAY_IP}/; echo; sleep 1; done;

    Saída esperada -- o sistema distribui o tráfego aleatoriamente entre todas as versões de ambos os serviços:

    -> mocka(version: canary, ip: 172.17.0.129)-> mockb(version: base, ip: 172.17.0.70)
    -> mocka(version: base, ip: 172.17.0.132)-> mockb(version: base, ip: 172.17.0.70)
    -> mocka(version: base, ip: 172.17.0.132)-> mockb(version: canary, ip: 172.17.0.54)
    -> mocka(version: canary, ip: 172.17.0.129)-> mockb(version: canary, ip: 172.17.0.54)

    Neste ponto, o cabeçalho my-asm-prefer-tag não surte efeito no roteamento. As requisições seguem o balanceamento de carga round-robin independentemente do valor do cabeçalho.

Etapa 3: Configure os rótulos de tráfego

Crie recursos TrafficLabel para extrair rótulos de roteamento dos cabeçalhos de requisição. O ASM usa esses rótulos para determinar se o tráfego é version-base ou version-canary. Para saber mais sobre a rotulagem de tráfego, consulte Rotule o tráfego.

  1. Crie um arquivo chamado trafficlabel.yaml com o seguinte conteúdo:

    Conteúdo de trafficlabel.yaml

    apiVersion: istio.alibabacloud.com/v1
    kind: TrafficLabel
    metadata:
      name: trafficlabel-ns
      namespace: default
    spec:
      rules:
      - labels:
        - name: asm-labels-sample
          valueFrom:
          - $getExternalInboundRequestHeader(my-asm-prefer-tag, my-trace-id)
    ---
    apiVersion: istio.alibabacloud.com/v1
    kind: TrafficLabel
    metadata:
      name: ingressgateway
      namespace: istio-system
    spec:
      rules:
      - labels:
        - name: asm-labels-sample
          valueFrom:
          - $getInboundRequestHeader(my-asm-prefer-tag)
      workloadSelector:
        labels:
          istio: ingressgateway

    Esta configuração define dois recursos TrafficLabel:

    Recurso

    Escopo

    Comportamento

    trafficlabel-ns

    Todos os serviços no namespace default (mocka, mockb)

    Usa $getExternalInboundRequestHeader para extrair a tag de versão do cabeçalho my-asm-prefer-tag. O segundo parâmetro, my-trace-id, especifica o cabeçalho de rastreamento que a aplicação deve propagar entre os serviços.

    ingressgateway

    Apenas o gateway de entrada (namespace istio-system)

    Lê a tag de versão do cabeçalho my-asm-prefer-tag da requisição de entrada do cliente.

    Nota

    Este exemplo usa os nomes de cabeçalho my-asm-prefer-tag e my-trace-id. Substitua-os por cabeçalhos que correspondam à sua aplicação.

  2. Conecte-se à instância do ASM com o kubectl e aplique os rótulos de tráfego:

    kubectl apply -f trafficlabel.yaml

Etapa 4: Aplique o roteamento baseado em rótulos e verifique

Esta etapa verifica progressivamente a liberação canário de ponta a ponta em três fases:

  1. Roteamento de salto único -- Aplique o roteamento baseado em rótulos ao Serviço B e confirme se a tag de tráfego encaminha corretamente as requisições para a versão correspondente

  2. Roteamento de cadeia completa -- Aplique o roteamento baseado em rótulos ao Serviço A no gateway para que o tráfego canário flua pelas versões canário de todos os serviços de ponta a ponta

  3. Roteamento ponderado -- Combine a distribuição baseada em peso com o roteamento baseado em rótulos para controlar o percentual da liberação canário

Verifique o roteamento baseado em rótulos para o Serviço B

Aplique primeiro o roteamento baseado em rótulos ao Serviço B. Isso verifica se a tag de tráfego do Serviço A encaminha corretamente as requisições para a versão correspondente do Serviço B.

Service provider side canary release verification

  1. Crie um arquivo chamado vs-tf-mockb.yaml com o seguinte conteúdo:

    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: vs-mockb
    spec:
      hosts:
        - mockb
      http:
        - route:
            - destination:
                host: mockb
                subset: $asm-labels-sample

    O subconjunto $asm-labels-sample resolve dinamicamente para o valor do rótulo de tráfego -- seja version-base ou version-canary.

  2. Aplique a regra de roteamento:

    kubectl apply -n default -f vs-tf-mockb.yaml
  3. Envie tráfego canário e verifique se o Serviço B o recebe na versão canário:

    for i in {1..200}; do curl -H'my-asm-prefer-tag: version-canary' -H'my-trace-id: x000'$i http://${ASM_GATEWAY_IP}/; echo; sleep 1; done;

    Saída esperada -- o Serviço A ainda recebe tráfego aleatório, mas o Serviço B encaminha consistentemente para a versão canário:

    -> mocka(version: canary, ip: 172.17.0.129)-> mockb(version: canary, ip: 172.17.0.54)
    -> mocka(version: base, ip: 172.17.0.132)-> mockb(version: canary, ip: 172.17.0.54)
    -> mocka(version: base, ip: 172.17.0.132)-> mockb(version: canary, ip: 172.17.0.54)
  4. Envie tráfego base e verifique se o Serviço B o recebe na versão base:

    for i in {1..200}; do curl -H'my-asm-prefer-tag: version-base' -H'my-trace-id: x000'$i http://${ASM_GATEWAY_IP}/; echo; sleep 1; done;

    Saída esperada -- o Serviço B encaminha consistentemente para a versão base:

    -> mocka(version: canary, ip: 172.17.0.129)-> mockb(version: base, ip: 172.17.0.70)
    -> mocka(version: base, ip: 172.17.0.132)-> mockb(version: base, ip: 172.17.0.70)
    -> mocka(version: base, ip: 172.17.0.132)-> mockb(version: base, ip: 172.17.0.70)

O roteamento do Serviço B agora funciona conforme o esperado. O Serviço A ainda recebe tráfego aleatoriamente porque você ainda não aplicou nenhuma regra de roteamento baseada em rótulos ao gateway.

Verifique o roteamento canário de ponta a ponta

Aplique o roteamento baseado em rótulos ao Serviço A no nível do gateway para que toda a cadeia de chamadas respeite o rótulo de tráfego.

End-to-end canary release verification

  1. Crie um arquivo chamado vs-tf-mocka.yaml com o seguinte conteúdo:

    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: vs-gateway-mocka
    spec:
      gateways:
      - simple-gateway
      hosts:
        - "*"
      http:
      - route:
          - destination:
              host: mocka
              subset: $asm-labels-sample
  2. Aplique a regra de roteamento ao gateway de entrada:

    kubectl apply -n default -f vs-tf-mocka.yaml
  3. Envie tráfego canário e verifique se ambos os serviços encaminham para as versões canário:

    for i in {1..200}; do curl -H'my-asm-prefer-tag: version-canary' -H'my-trace-id: x000'$i http://${ASM_GATEWAY_IP}/; echo; sleep 1; done;

    Saída esperada -- todo o tráfego flui pelas versões canário de ponta a ponta:

    -> mocka(version: canary, ip: 172.17.0.69)-> mockb(version: canary, ip: 172.17.0.130)
    -> mocka(version: canary, ip: 172.17.0.69)-> mockb(version: canary, ip: 172.17.0.130)
    -> mocka(version: canary, ip: 172.17.0.69)-> mockb(version: canary, ip: 172.17.0.130)
  4. Envie tráfego base e verifique se ambos os serviços encaminham para as versões base:

    for i in {1..200}; do curl -H'my-asm-prefer-tag: version-base' -H'my-trace-id: x000'$i http://${ASM_GATEWAY_IP}/; echo; sleep 1; done;

    Saída esperada -- todo o tráfego flui pelas versões base de ponta a ponta:

    -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: base, ip: 172.17.0.93)
    -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: base, ip: 172.17.0.93)
    -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: base, ip: 172.17.0.93)

O roteamento canário de ponta a ponta agora está ativo. O tráfego canário atinge consistentemente as versões canário de todos os serviços, e o tráfego base permanece nas versões base.

Verifique a distribuição ponderada de tráfego com rótulos

Em produção, você geralmente começa encaminhando uma pequena porcentagem de tráfego para a versão canário. Combine a distribuição baseada em peso com o roteamento baseado em rótulos para controlar a liberação.

Weight-based and label-based routing verification

  1. Crie um arquivo chamado vs-tf-mocka-90-10.yaml com o seguinte conteúdo:

    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: vs-gateway-mocka
    spec:
      gateways:
      - simple-gateway
      hosts:
        - "*"
      http:
      - route:
          - destination:
              host: mocka
              subset: version-base
            weight: 90
          - destination:
              host: mocka
              subset: $asm-labels-sample
            weight: 10

    Esta configuração envia 90% do tráfego para a versão base do Serviço A. O sistema encaminha os 10% restantes com base no rótulo de tráfego -- se o cabeçalho my-asm-prefer-tag estiver definido como version-canary, esses 10% vão para a versão canário.

  2. Aplique a regra de roteamento ponderado:

    kubectl apply -n default -f vs-tf-mocka-90-10.yaml
  3. Envie tráfego canário e verifique a distribuição:

    for i in {1..200}; do curl -H'my-asm-prefer-tag: version-canary' -H'my-trace-id: x000'$i http://${ASM_GATEWAY_IP}/; echo; sleep 1; done;

    Saída esperada -- aproximadamente 90% das requisições chegam à versão base do Serviço A, enquanto 10% chegam à versão canário. O Serviço B encaminha consistentemente para a versão canário porque o rótulo se propaga pela cadeia de chamadas:

    -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: canary, ip: 172.17.0.130)
    -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: canary, ip: 172.17.0.130)
    -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: canary, ip: 172.17.0.130)
    ...
    -> mocka(version: canary, ip: 172.17.0.69)-> mockb(version: canary, ip: 172.17.0.130)

    Cerca de 9 em cada 10 requisições atingem mocka(version: base), enquanto aproximadamente 1 em 10 atinge mocka(version: canary). Em ambos os casos, o mockb encaminha para a versão canário.

  4. Envie tráfego base e verifique se todas as requisições chegam às versões base:

    for i in {1..200}; do curl -H'my-asm-prefer-tag: version-base' -H'my-trace-id: x000'$i http://${ASM_GATEWAY_IP}/; echo; sleep 1; done;

    Saída esperada -- 90% do tráfego vai diretamente para a versão base. O sistema também encaminha os 10% restantes para a versão base porque o rótulo resolve para version-base:

    -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: base, ip: 172.17.0.93)
    -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: base, ip: 172.17.0.93)
    -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: base, ip: 172.17.0.93)
    -> mocka(version: base, ip: 172.17.0.90)-> mockb(version: base, ip: 172.17.0.93)

    Com o cabeçalho my-asm-prefer-tag definido como version-base, 90% vão para a versão base por peso fixo e os 10% restantes também resolvem para a base por rótulo. O resultado é 100% de tráfego base.

Próximos passos