O console do ASM fornece regras de roteamento integradas para faixas de tráfego, mas elas suportam apenas correspondência de cabeçalho e caminho. Para divisão ponderada de tráfego, destinos de fallback ou injeção personalizada de cabeçalhos, crie um VirtualService personalizado.
Este tópico descreve como criar VirtualServices personalizados no gateway de entrada do ASM e em proxies sidecar para rotear o tráfego entre faixas no modo permissivo.
Este tópico baseia-se na configuração de faixas de tráfego descrita em Usar faixas de tráfego no modo permissivo para gerenciar tráfego de ponta a ponta. Conclua essa configuração antes de prosseguir. Os exemplos abaixo modificam etapas do Cenário 1: Transmitir IDs de rastreamento em traces e do Cenário 2: Transmitir cabeçalhos de requisição personalizados em traces.
Como funciona
Um VirtualService personalizado define regras de roteamento no gateway de entrada do ASM ou em proxies sidecar. Cada regra identifica requisições recebidas pelos valores de cabeçalho e as direciona para faixas de tráfego específicas (subconjuntos) com pesos configuráveis.
Os exemplos neste tópico utilizam três faixas de tráfego:
|
Faixa |
Subconjunto |
Função |
|
s1 |
|
Linha de base (padrão) |
|
s2 |
|
Faixa canária A |
|
s3 |
|
Faixa canária B |
Lógica de roteamento:
Requisições com o cabeçalho
env: devdividem-se igualmente (50/50) entre as faixas s2 e s3.Se a faixa s3 estiver indisponível, o tráfego retornará à faixa s1.
Todas as demais requisições seguirão para a faixa s1.
Após o gateway de entrada rotear uma requisição para uma faixa, o cabeçalho de roteamento x-asm-prefer-tag fixa todas as chamadas subsequentes do mesmo trace nessa faixa.
Não combine VirtualServices personalizados com o recurso de criação de regras de roteamento integradas para a mesma faixa de tráfego. O uso simultâneo pode gerar conflitos e causar distribuição inesperada de tráfego.
Crie um VirtualService personalizado no gateway de entrada
Substitua a etapa de criação de regra de roteamento (subetapa 3, "Criar regras de drenagem para as três faixas" na Etapa 1) do Cenário 1 pelo VirtualService a seguir. Para obter detalhes sobre gerenciamento de VirtualServices, consulte Gerenciar serviços virtuais.
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: swimlane-ingress-vs-custom
namespace: istio-system
spec:
gateways:
- istio-system/ingressgateway
hosts:
- '*'
http:
# Route 1: Match requests with the "env: dev" header.
# Split traffic 50/50 between lanes s2 and s3.
- match:
- headers:
env:
exact: dev
name: dev-route
route:
- destination:
host: mocka.default.svc.cluster.local
subset: s2
weight: 50
headers:
request:
set:
x-asm-prefer-tag: s2
- destination:
host: mocka.default.svc.cluster.local
subset: s3
fallback:
target:
host: mocka.default.svc.cluster.local
subset: s1
weight: 50
headers:
request:
set:
x-asm-prefer-tag: s3
# Route 2: Default route. Send all other requests to lane s1.
- name: base-route
route:
- destination:
host: mocka.default.svc.cluster.local
subset: s1
headers:
request:
set:
x-asm-prefer-tag: s1
Referência de campos:
|
Campo |
Descrição |
|
|
Vincula este VirtualService ao gateway de entrada do ASM |
|
|
Corresponde a todos os nomes de host no gateway |
|
|
Identifica requisições com o cabeçalho |
|
|
Especifica a faixa de tráfego de destino |
|
|
Controla a proporção da divisão de tráfego |
|
|
Define |
|
|
Indica uma faixa alternativa quando o destino principal está indisponível |
O valor de headers.request.set deve corresponder ao cabeçalho de roteamento de cada faixa. Por exemplo, no Cenário 2, em que o cabeçalho de requisição transmitido atua como cabeçalho de roteamento, altere os valores para my-trace-id: s1, my-trace-id: s2 e my-trace-id: s3, respectivamente.
Verifique o comportamento de roteamento
Execute os comandos de verificação da Etapa 3: Verificar se o recurso de liberação canária de ponta a ponta entrou em vigor. Sem o cabeçalho env: dev, todas as requisições seguem para a faixa s1:
-> mocka(version: v1, ip: 192.168.0.50)-> mockb(version: v1, ip: 192.168.0.46)-> mockc(version: v1, ip: 192.168.0.48)
Para testar a regra de roteamento env: dev, envie 100 requisições para a faixa s1 com esse cabeçalho:
for i in {1..100}; do curl -H 'x-asm-prefer-tag: s1' -H 'env: dev' -H'my-trace-id: x000'$i http://${ASM_GATEWAY_IP}/mock ; echo ''; sleep 1; done;
Saída esperada (amostra representativa):
-> mocka(version: v1, ip: 192.168.0.50)-> mockb(version: v3, ip: 192.168.0.42)-> mockc(version: v1, ip: 192.168.0.48)
-> mocka(version: v1, ip: 192.168.0.50)-> mockb(version: v3, ip: 192.168.0.42)-> mockc(version: v1, ip: 192.168.0.48)
-> mocka(version: v2, ip: 192.168.0.47)-> mockb(version: v1, ip: 192.168.0.46)-> mockc(version: v2, ip: 192.168.0.43)
-> mocka(version: v2, ip: 192.168.0.47)-> mockb(version: v1, ip: 192.168.0.46)-> mockc(version: v2, ip: 192.168.0.43)
-> mocka(version: v1, ip: 192.168.0.50)-> mockb(version: v3, ip: 192.168.0.42)-> mockc(version: v1, ip: 192.168.0.48)
...
A saída exibe dois padrões de trace em proporção aproximada de 50:50:
|
Padrão de trace |
Roteado para a faixa |
Explicação |
|
|
s2 |
A requisição correspondeu a |
|
|
s3 |
A requisição correspondeu a |
Isso confirma que as requisições com o cabeçalho env: dev se dividem uniformemente entre as faixas s2 e s3, enquanto as demais seguem para a faixa s1.
Ao criar VirtualServices personalizados para rotear tráfego de faixas no modo estrito, basta definir o campo route.destination.subset com o nome da faixa de tráfego de destino. Após o roteamento de uma requisição para uma faixa, todas as requisições subsequentes no trace seguirão sempre para essa mesma faixa.
Crie VirtualServices personalizados em proxies sidecar
Para rotear chamadas serviço a serviço dentro do cluster — e não apenas o tráfego que entra pelo gateway de entrada —, crie um VirtualService nos proxies sidecar. Dois campos diferem da versão do gateway de entrada:
|
Campo |
Gateway de entrada |
Proxy sidecar |
|
|
Obrigatório ( |
Omitido |
|
|
|
Domínio do cluster (ex.: |
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: swimlane-ingress-vs-custom
namespace: istio-system
spec:
hosts:
- mocka.default.svc.cluster.local
http:
- match:
- headers:
env:
exact: dev
name: dev-route
route:
- destination:
host: mocka.default.svc.cluster.local
subset: s2
weight: 50
headers:
request:
set:
x-asm-prefer-tag: s2
- destination:
host: mocka.default.svc.cluster.local
subset: s3
weight: 50
fallback:
target:
host: mocka.default.svc.cluster.local
subset: s1
headers:
request:
set:
x-asm-prefer-tag: s3
- name: base-route
route:
- destination:
host: mocka.default.svc.cluster.local
subset: s1
headers:
request:
set:
x-asm-prefer-tag: s1
Assim como na versão do gateway de entrada, o valor de headers.request.set deve corresponder ao cabeçalho de roteamento associado.
Verifique o roteamento sem o cabeçalho env: dev
Envie requisições para cada faixa sem o cabeçalho env: dev:
kubectl exec -it deploy/sleep -c sleep -- sh -c 'for i in $(seq 1 100); do curl -H "my-trace-id: s1" http://mocka:8000; echo ""; sleep 1; done;'
kubectl exec -it deploy/sleep -c sleep -- sh -c 'for i in $(seq 1 100); do curl -H "my-trace-id: s2" http://mocka:8000; echo ""; sleep 1; done;'
kubectl exec -it deploy/sleep -c sleep -- sh -c 'for i in $(seq 1 100); do curl -H "my-trace-id: s3" http://mocka:8000; echo ""; sleep 1; done;'
Saída esperada:
-> mocka(version: v1, ip: 192.168.0.50)-> mockb(version: v1, ip: 192.168.0.46)-> mockc(version: v1, ip: 192.168.0.48)
Todas as requisições seguem para a faixa s1, independentemente do valor de my-trace-id, pois não há cabeçalho env: dev presente.
Verifique o roteamento com o cabeçalho env: dev
Envie requisições para cada faixa com o cabeçalho env: dev:
kubectl exec -it deploy/sleep -c sleep -- sh -c 'for i in $(seq 1 100); do curl -H "my-trace-id: s1" -H "env: dev" http://mocka:8000; echo ""; sleep 1; done;'
kubectl exec -it deploy/sleep -c sleep -- sh -c 'for i in $(seq 1 100); do curl -H "my-trace-id: s2" -H "env: dev" http://mocka:8000; echo ""; sleep 1; done;'
kubectl exec -it deploy/sleep -c sleep -- sh -c 'for i in $(seq 1 100); do curl -H "my-trace-id: s3" -H "env: dev" http://mocka:8000; echo ""; sleep 1; done;'
Saída esperada (amostra representativa):
-> mocka(version: v1, ip: 192.168.0.50)-> mockb(version: v3, ip: 192.168.0.42)-> mockc(version: v1, ip: 192.168.0.48)
-> mocka(version: v2, ip: 192.168.0.47)-> mockb(version: v1, ip: 192.168.0.46)-> mockc(version: v2, ip: 192.168.0.43)
-> mocka(version: v1, ip: 192.168.0.50)-> mockb(version: v3, ip: 192.168.0.42)-> mockc(version: v1, ip: 192.168.0.48)
-> mocka(version: v2, ip: 192.168.0.47)-> mockb(version: v1, ip: 192.168.0.46)-> mockc(version: v2, ip: 192.168.0.43)
...
A saída mostra os padrões de trace v1 -> v3 -> v1 e v2 -> v1 -> v2 em proporção de 50:50. Isso confirma que o VirtualService do proxy sidecar distribui uniformemente as requisições env: dev entre as faixas s2 e s3. Assim que uma requisição entra em uma faixa, todas as chamadas subsequentes do trace permanecem nela.