As faixas de tráfego direcionam requisições para versões específicas de serviços em toda a cadeia de chamadas. Por exemplo, todas as requisições marcadas com v2 alcançam a instância v2 de cada serviço na cadeia. No modo permissivo, se não existir uma versão correspondente para um determinado serviço, o tráfego retorna automaticamente à versão base em vez de falhar. Essa abordagem permite releases canary seguros e testes baseados em versão em arquiteturas com múltiplos serviços, sem exigir que todos os serviços tenham todas as versões implantadas.
Como funciona
Quatro tipos de recursos atuam em conjunto para implementar as faixas de tráfego:
|
Recurso |
Função |
|
OpenTelemetry Instrumentation |
Propaga automaticamente cabeçalhos de baggage entre chamadas de serviço sem alterações no código |
|
ASMHeaderPropagation |
CRD específico do ASM que extrai cabeçalhos especificados (como |
|
DestinationRule |
Define subconjuntos de serviço (v1, v2, v3) com base em rótulos de pod |
|
VirtualService |
Roteia requisições para o subconjunto correto correspondendo ao cabeçalho |
Fluxo de tráfego:
Client request
|
v
Ingress Gateway (sets version header, distributes traffic by weight)
|
v
mocka (version matched via header) --> mockb (version matched) --> mockc (version matched)
| | |
v v v
If no matching version exists, Same fallback logic Same fallback logic
falls back to v1 (baseline)
O campo fallback utilizado nas rotas do VirtualService é uma extensão específica do ASM para a API padrão do Istio VirtualService. Ele é acionado quando o subconjunto alvo não possui nenhum endpoint íntegro, roteando o tráfego para o subconjunto de fallback especificado em vez de retornar um erro. Esse campo não está disponível no Istio upstream.
Cabeçalhos de baggage
O baggage é um mecanismo do OpenTelemetry para propagar contexto de chave-valor entre processos em um rastro distribuído. Ele utiliza um cabeçalho HTTP:
baggage: userId=alice,serverNode=DF%2028,isProduction=false
Os cabeçalhos de baggage transportam dados de contexto, como IDs de tenant, IDs de rastro e credenciais de segurança, permitindo análise de rastros e correlação de logs sem modificações no código.
Para mais informações sobre faixas de tráfego, consulte Visão geral das faixas de tráfego.
Pré-requisitos
Antes de começar, certifique-se de ter:
Uma instância do Service Mesh (ASM) da Enterprise Edition ou Ultimate Edition, versão 1.21.6.54 ou posterior -- consulte Crie uma instância do ASM ou Atualize uma instância do ASM
Um cluster Kubernetes adicionado à instância do ASM -- consulte Adicionar um cluster a uma instância do ASM
Um ingress gateway do ASM chamado
ingressgateway-- consulte Crie um ingress gatewayHelm instalado na máquina local -- consulte Instale o Helm
Etapa 1: Implantar o OpenTelemetry Operator e configure a instrumentação automática
O OpenTelemetry Operator instrumenta automaticamente os pods de serviço para propagar cabeçalhos de baggage entre chamadas sem alterações no código.
Implantar o OpenTelemetry Operator
-
Conecte-se ao cluster Kubernetes com kubectl. Crie o namespace
opentelemetry-operator-system:kubectl create namespace opentelemetry-operator-system -
Instale o OpenTelemetry Operator com Helm:
helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts helm install \ --namespace=opentelemetry-operator-system \ --version=0.46.0 \ --set admissionWebhooks.certManager.enabled=false \ --set admissionWebhooks.certManager.autoGenerateCert=true \ --set manager.image.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/opentelemetry-operator" \ --set manager.image.tag="0.92.1" \ --set kubeRBACProxy.image.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/kube-rbac-proxy" \ --set kubeRBACProxy.image.tag="v0.13.1" \ --set manager.collectorImage.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/opentelemetry-collector" \ --set manager.collectorImage.tag="0.97.0" \ --set manager.opampBridgeImage.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/operator-opamp-bridge" \ --set manager.opampBridgeImage.tag="0.97.0" \ --set manager.targetAllocatorImage.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/target-allocator" \ --set manager.targetAllocatorImage.tag="0.97.0" \ --set manager.autoInstrumentationImage.java.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/autoinstrumentation-java" \ --set manager.autoInstrumentationImage.java.tag="1.32.1" \ --set manager.autoInstrumentationImage.nodejs.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/autoinstrumentation-nodejs" \ --set manager.autoInstrumentationImage.nodejs.tag="0.49.1" \ --set manager.autoInstrumentationImage.python.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/autoinstrumentation-python" \ --set manager.autoInstrumentationImage.python.tag="0.44b0" \ --set manager.autoInstrumentationImage.dotnet.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/autoinstrumentation-dotnet" \ --set manager.autoInstrumentationImage.dotnet.tag="1.2.0" \ --set manager.autoInstrumentationImage.go.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/opentelemetry-go-instrumentation" \ --set manager.autoInstrumentationImage.go.tag="v0.10.1.alpha-2-aliyun" \ opentelemetry-operator open-telemetry/opentelemetry-operator -
Verifique se o pod do operator está em execução. Saída esperada:
kubectl get pod -n opentelemetry-operator-systemNAME READY STATUS RESTARTS AGE opentelemetry-operator-854fb558b5-pvllj 2/2 Running 0 1m
Configure a instrumentação automática
Crie um arquivo instrumentation.yaml para declarar o propagador de baggage. Escolha a configuração conforme a existência de um OpenTelemetry Collector implantado no ambiente.
Sem OpenTelemetry Collector -- Desabilita a exportação de métricas e rastreamento para evitar erros quando nenhum endpoint de collector estiver disponível:
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
name: demo-instrumentation
spec:
env:
- name: OTEL_METRICS_EXPORTER
value: none
propagators:
- baggage
sampler:
argument: "1"
type: always_off
Com OpenTelemetry Collector -- Habilita rastreamento completo com amostragem baseada no pai:
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
name: demo-instrumentation
spec:
propagators:
- baggage
sampler:
type: parentbased_traceidratio
argument: "1"
Aplique o recurso de instrumentação no namespace default:
kubectl apply -f instrumentation.yaml
Implantar um OpenTelemetry Collector para coletar dados de observabilidade é uma prática recomendada. Para detalhes sobre a coleta de dados de rastreamento do ASM, consulte Coletar dados de rastreamento do ASM para o Managed Service for OpenTelemetry .
Etapa 2: Implantar serviços de exemplo
Esta etapa implanta três serviços -- mocka, mockb e mockc -- cada um com três versões (v1, v2, v3). Os serviços formam uma cadeia de chamadas: mocka -> mockb -> mockc. Cada pod possui anotações para instrumentação automática Java, de modo que os cabeçalhos de baggage são propagados automaticamente.
-
Ative a injeção automática de proxy sidecar para o namespace
default. Consulte Gerencie namespaces globais.Para mais informações sobre injeção de sidecar, consulte Ative injeção automática de proxy sidecar .
-
Crie um arquivo
mock.yamlcom o seguinte conteúdo.Pontos principais sobre os manifestos YAML:
Configuração
Finalidade
Rótulo
ASM_TRAFFIC_TAGMarca cada pod com sua versão (v1, v2 ou v3) para roteamento por faixa de tráfego
instrumentation.opentelemetry.io/inject-java: "true"Aciona a instrumentação automática do OpenTelemetry para o contêiner Java
instrumentation.opentelemetry.io/container-names: "default"Especifique qual contêiner deve ser instrumentado
Variável de ambiente
upstream_urlDefina a cadeia de chamadas:
mocka->mockb->mockc -
Implante os serviços. Com a instrumentação automática configurada, os pods propagam automaticamente os cabeçalhos de baggage ao longo da cadeia de chamadas.
kubectl apply -f mock.yaml
Etapa 3: Crie regras de roteamento para faixas de tráfego
Esta etapa cria destination rules, um CRD ASMHeaderPropagation, virtual services e regras de ingress gateway. Em conjunto, esses recursos roteiam requisições para a versão correta do serviço com base no cabeçalho version propagado, com retorno para v1 quando uma versão não existir.
Crie destination rules
As destination rules definem subconjuntos de serviço com base em rótulos de pod. Nem todo serviço possui todas as três versões -- isso é intencional e demonstra o comportamento de fallback do modo permissivo.
|
Serviço |
Subconjuntos disponíveis |
|
|
v1, v2, v3 |
|
|
v1, v3 |
|
|
v1, v2 |
-
Crie um arquivo
dr-mock.yamlcom o seguinte conteúdo. -
Conecte-se à instância do ASM com kubectl e aplique as destination rules:
kubectl apply -f dr-mock.yaml
Crie um CRD ASMHeaderPropagation
O CRD ASMHeaderPropagation informa ao ASM quais cabeçalhos extrair do contexto de baggage e propagar ao longo da cadeia de chamadas. Neste exemplo, o cabeçalho version é extraído para que os serviços downstream recebam o contexto de roteamento correto.
-
Crie um arquivo
propagation.yaml:Campo
Descrição
apiVersionistio.alibabacloud.com/v1beta1-- Grupo de API específico do ASMkindASMHeaderPropagation-- CRD para propagação de cabeçalhos a partir do contexto de baggagespec.headersLista de nomes de cabeçalhos a serem extraídos do baggage e propagados como cabeçalhos de requisição
apiVersion: istio.alibabacloud.com/v1beta1 kind: ASMHeaderPropagation metadata: name: version-propagation spec: headers: - version -
Conecte-se à instância do ASM com kubectl e aplique o CRD:
kubectl apply -f propagation.yaml
Crie virtual services
Os virtual services roteiam requisições para o subconjunto correto correspondendo ao cabeçalho version. Cada regra inclui um alvo de fallback apontando para v1 (a versão base). No modo permissivo, quando uma requisição tem como alvo uma versão inexistente (por exemplo, mockb não possui v2), o ASM roteia para o subconjunto de fallback em vez de retornar um erro.
-
Crie um arquivo
vs-mock.yamlcom o seguinte conteúdo.O padrão de roteamento para cada serviço segue esta estrutura:
# For each version match, specify a primary destination and a fallback - match: - headers: version: exact: v2 # Match the propagated version header route: - destination: host: <service>.default.svc.cluster.local subset: v2 # Primary: route to matching version fallback: target: host: <service>.default.svc.cluster.local subset: v1 # Fallback: route to baseline when v2 has no healthy endpoints -
Conecte-se à instância do ASM com kubectl e aplique os virtual services:
kubectl apply -f vs-mock.yaml
Crie regras de ingress gateway
O ingress gateway distribui o tráfego de entrada entre as versões do serviço por peso e define o cabeçalho version em cada requisição para corresponder à versão alvo.
-
Crie um arquivo
gw-mock.yamlcom o seguinte conteúdo.Esta configuração distribui o tráfego para v1, v2 e v3 do
mockana proporção de 40:30:30. Para cada requisição, o gateway define o cabeçalhoversioncomo a versão alvo, garantindo que os serviços downstream na cadeia de chamadas recebam o contexto de roteamento correto por meio da propagação de baggage. -
Conecte-se à instância do ASM com kubectl e aplique as regras de gateway:
kubectl apply -f gw-mock.yaml
Etapa 4: Verifique o roteamento das faixas de tráfego
Obtenha o endereço IP público do ingress gateway. Consulte Obter o endereço IP do ingress gateway do ASM.
-
Defina o IP do gateway como variável de ambiente. Substitua
<gateway-ip>pelo endereço IP real.export ASM_GATEWAY_IP=<gateway-ip> -
Envie requisições repetidas para observar a distribuição de tráfego. Saída de exemplo:
for i in {1..100}; do curl http://${ASM_GATEWAY_IP}; echo ''; sleep 1; done-> mocka(version: v1, ip: 192.168.1.27)-> mockb(version: v1, ip: 192.168.1.30)-> mockc(version: v1, ip: 192.168.1.14) -> mocka(version: v2, ip: 192.168.1.28)-> mockb(version: v1, ip: 192.168.1.30)-> mockc(version: v2, ip: 192.168.1.1) -> mocka(version: v3, ip: 192.168.1.26)-> mockb(version: v3, ip: 192.168.1.29)-> mockc(version: v1, ip: 192.168.1.14) -
Verifique os resultados. A saída confirma dois comportamentos: Distribuição baseada em peso: O tráfego divide-se entre v1, v2 e v3 na proporção aproximada de 40:30:30. Fallback do modo permissivo: Quando uma versão não existe para um serviço, o tráfego retorna para v1:
Faixa v2:
mocka-v2->mockb-v1(não existemockb-v2, então o tráfego retorna para v1) ->mockc-v2Faixa v3:
mocka-v3->mockb-v3->mockc-v1(não existemockc-v3, então o tráfego retorna para v1)
Faixa
mocka
mockb
mockc
v1
v1
v1
v1
v2
v2
v1 (sem v2, retorna)
v2
v3
v3
v3
v1 (sem v3, retorna)