La console ASM fournit des règles de routage intégrées pour les voies de trafic, mais ces règles ne prennent en charge que la correspondance par en-tête et par chemin. Lorsque vous avez besoin d'un partage pondéré du trafic, de cibles de secours ou d'une injection d'en-tête personnalisée, créez plutôt un VirtualService personnalisé.
Cette rubrique explique comment créer des VirtualServices personnalisés sur la passerelle d'entrée ASM et sur les proxies sidecar pour acheminer le trafic entre les voies en mode permissif.
Cette rubrique s'appuie sur la configuration des voies de trafic décrite dans Utiliser les voies de trafic en mode permissif pour gérer le trafic de bout en bout. Effectuez cette configuration avant de poursuivre. Les exemples ci-dessous modifient les étapes de Scénario 1 : Transmettre les ID de trace dans les traces et Scénario 2 : Transmettre des en-têtes de requête personnalisés dans les traces.
Fonctionnement
Un VirtualService personnalisé définit des règles de routage sur la passerelle d'entrée ASM ou sur les proxies sidecar. Chaque règle fait correspondre les requêtes entrantes selon les valeurs des en-têtes, puis les achemine vers des voies de trafic spécifiques (sous-ensembles) avec des pondérations configurables.
Les exemples de cette rubrique utilisent trois voies de trafic :
| Voie | Sous-ensemble | Rôle |
|---|---|---|
| s1 | s1 |
Ligne de base (par défaut) |
| s2 | s2 |
Voie Canary A |
| s3 | s3 |
Voie Canary B |
Logique de routage :
Les requêtes contenant l'en-tête
env: devsont réparties à parts égales (50/50) entre les voies s2 et s3.Si la voie s3 n'est pas disponible, le trafic bascule vers la voie s1.
Toutes les autres requêtes sont dirigées vers la voie s1.
Une fois que la passerelle d'entrée a acheminé une requête vers une voie, l'en-tête de routage de requête x-asm-prefer-tag épingle tous les appels suivants au sein de la même trace à cette voie.
Ne combinez pas les VirtualServices personnalisés avec la fonctionnalité de création de règles de routage intégrée pour la même voie de trafic. Les deux peuvent entrer en conflit et provoquer une distribution inattendue du trafic.
Créer un VirtualService personnalisé sur la passerelle d'entrée
Remplacez l'étape de création de règle de routage (sous-étape 3, « Créer des règles de drainage pour les trois voies » à l'étape 1) du Scénario 1 par le VirtualService suivant. Pour plus d'informations sur la gestion des VirtualServices, consultez la rubrique Gérer les services virtuels.
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
Référence des champs :
| Champ | Description |
|---|---|
gateways |
Lie ce VirtualService à la passerelle d'entrée ASM |
hosts: '*' |
Correspond à tous les noms d'hôte au niveau de la passerelle |
match.headers.env.exact: dev |
Correspond aux requêtes contenant l'en-tête env: dev |
route[].destination.subset |
Spécifie la voie de trafic cible |
route[].weight |
Contrôle le ratio de répartition du trafic |
route[].headers.request.set |
Définit x-asm-prefer-tag pour épingler les appels de trace suivants à la voie |
fallback.target |
Spécifie une voie de secours lorsque la cible principale n'est pas disponible |
La valeur headers.request.set doit correspondre à l'en-tête de routage de requête pour chaque voie. Par exemple, dans le Scénario 2, où l'en-tête de requête transmis sert d'en-tête de routage, modifiez les valeurs respectivement en my-trace-id: s1, my-trace-id: s2 et my-trace-id: s3.
Vérifier le comportement de routage
Exécutez les commandes de vérification de l Étape 3 : Vérifier que la fonctionnalité de déploiement Canary de bout en bout prend effet. Sans l'en-tête env: dev, toutes les requêtes sont acheminées vers la voie 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)
Pour tester la règle de routage env: dev, envoyez 100 requêtes à la voie s1 avec cet en-tête :
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;
Sortie attendue (échantillon représentatif) :
-> 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)
...
La sortie montre deux modèles de trace dans un ratio approximatif de 50:50 :
| Modèle de trace | Acheminé vers la voie | Explication |
|---|---|---|
v1 -> v3 -> v1 |
s2 | La requête a correspondu à env: dev et a été envoyée à la voie s2 |
v2 -> v1 -> v2 |
s3 | La requête a correspondu à env: dev et a été envoyée à la voie s3 |
Cela confirme que les requêtes avec l'en-tête env: dev sont réparties équitablement entre les voies s2 et s3, tandis que toutes les autres requêtes sont dirigées vers la voie s1.
Lorsque vous créez des VirtualServices personnalisés pour acheminer le trafic des voies de trafic en mode strict, il vous suffit de définir le champ route.destination.subset sur le nom de la voie de trafic cible. Une fois qu'une requête est acheminée vers une voie, toutes les requêtes suivantes de la trace sont toujours acheminées vers cette voie.
Créer des VirtualServices personnalisés sur les proxies sidecar
Pour acheminer les appels de service à service au sein du cluster — et pas seulement le trafic entrant via la passerelle d'entrée — créez un VirtualService sur les proxies sidecar. Deux champs diffèrent de la version de la passerelle d'entrée :
| Champ | Passerelle d'entrée | Proxy sidecar |
|---|---|---|
gateways |
Requis (istio-system/ingressgateway) |
Omis |
hosts |
'*' (tous les noms d'hôte) |
Domaine du cluster (par exemple, mocka.default.svc.cluster.local) |
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
Comme pour la version de la passerelle d'entrée, la valeur headers.request.set doit correspondre à l'en-tête de routage de requête correspondant.
Vérifier le routage sans l'en-tête env: dev
Envoyez des requêtes à chaque voie sans l'en-tête 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;'
Sortie attendue :
-> mocka(version: v1, ip: 192.168.0.50)-> mockb(version: v1, ip: 192.168.0.46)-> mockc(version: v1, ip: 192.168.0.48)
Toutes les requêtes sont acheminées vers la voie s1, quelle que soit la valeur de my-trace-id, car aucun en-tête env: dev n'est présent.
Vérifier le routage avec l'en-tête env: dev
Envoyez des requêtes à chaque voie avec l'en-tête 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;'
Sortie attendue (échantillon représentatif) :
-> 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)
...
La sortie montre les modèles de trace v1 -> v3 -> v1 et v2 -> v1 -> v2 dans un ratio de 50:50, confirmant que le VirtualService du proxy sidecar achemine les requêtes env: dev équitablement vers les voies s2 et s3. Une fois qu'une requête entre dans une voie, tous les appels suivants au sein de la trace restent dans cette voie.