Fractionnement du trafic dans Apache APISIX Ingress Controller
Fei Han
March 27, 2021
Le fractionnement du trafic est une fonctionnalité qui divise et achemine le trafic vers plusieurs services backend. Des solutions comme les API Gateway (par exemple Apache APISIX et Traefik), les Service Mesh (par exemple Istio et Linkerd) sont capables de réaliser ce fractionnement du trafic et de mettre en œuvre des fonctionnalités comme le Canary Release et le Blue-Green Deployment.
Le fractionnement du trafic est également une fonctionnalité clé dans les Ingress Controller. En tant que couche d'entrée dans le cluster Kubernetes, il est souhaitable de réduire le risque lié au déploiement d'une nouvelle version de l'application en configurant des règles de fractionnement du trafic dans l'ingress controller, de sorte qu'une quantité contrôlée de trafic soit acheminée vers les nouvelles instances déployées. Dans cet article, nous allons présenter le fractionnement du trafic (également appelé canary release) dans Ingress Nginx et Kong Ingress Controller, et finalement expliquer le fractionnement du trafic dans Apache APISIX Ingress Controller.
(PS : Pour des descriptions plus concises, nous utilisons le terme "canary app" pour décrire le service backend qui est acheminé après que les règles de canary soient déclenchées, et le terme "stable app" pour décrire le service backend qui est acheminé lorsque les règles de canary ne sont pas déclenchées. Par exemple, dans le diagramme suivant, les applications canary et stable sont respectivement "foo-canary" et "foo".)
Ingress Nginx
Ingress Nginx prend en charge le canary release, qui est contrôlé par une annotation "nginx.ingress.kubernetes.io/canary", et il prend en charge plusieurs annotations pour personnaliser cette fonctionnalité.
- nginx.ingress.kubernetes.io/canary-by-header
La destination est déterminée par la valeur de l'en-tête (indiquée par nginx.ingress.kubernetes.io/canary-by-header). L'application Canary sera acheminée si la valeur est "always", sinon l'application stable sera acheminée (la valeur de l'en-tête est "never").
- nginx.ingress.kubernetes.io/canary-by-header-value
Cette annotation étend nginx.ingress.kubernetes.io/canary-by-header, maintenant la valeur de l'en-tête n'a plus besoin d'être "always" ou "never".
- nginx.ingress.kubernetes.io/canary-by-header-pattern
Similaire à nginx.ingress.kubernetes.io/canary-by-header, mais la valeur est une expression régulière compatible avec PCRE.
- nginx.ingress.kubernetes.io/canary-by-cookie
Utilise le champ de données dans l'en-tête Cookie pour décider du service backend.
- nginx.ingress.kubernetes.io/canary-weight
Attribue une valeur de poids entre 0 et 100, le trafic sera acheminé en fonction de ce poids. Un poids de 0 signifie que tout le trafic sera acheminé vers l'application canary et un poids de 100 acheminera tout le trafic vers l'application stable.
L'extrait YAML suivant achemine les requêtes dont le chemin URI commence par "/get" et dont l'User-Agent correspond au motif ".Mozilla." vers l'application canary "foo-canary".
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "User-Agent"
nginx.ingress.kubernetes.io/canary-by-header-pattern:
".*Mozilla.*"
name: ingress-v1beta1
Kong
La passerelle Kong dispose d'un plugin de canary release et expose ce plugin à son ingress controller via la ressource KongPlugin. Les administrateurs/utilisateurs doivent créer un objet KongPlugin et remplir la règle de canary release, en injectant une annotation "konghq.com/plugins" au Service Kubernetes cible. Ou vous pouvez créer un objet KongClusterPlugin pour que cette règle de canary soit effective dans tout le cluster.
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: foo-canary
config:
percentage: 30
upstream_host: foo.com
upstream_fallback: false
upstream_port: 80
plugin: canary
---
apiVersion: v1
kind: Service
metadata:
name: foo-canary
labels:
app: foo
annotations:
konghq.com/plugins: foo-canary
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
name: http
selector:
app: foo
canary: true
Le cas ci-dessus marque le service "foo-canary" comme "canary", et crée une règle de canary release pour acheminer 30% du trafic vers ce service.
Apache APISIX
Apache APISIX fractionne le trafic avec des règles personnalisées via son plugin traffic-split, et Apache APISIX Ingress Controller implémente la fonctionnalité de fractionnement du trafic dans ApisixRoute (en tant que support de première classe, sans dépendre d'annotations) via ce plugin et les capacités de correspondance de route flexibles dans ApisixRoute.
Basé sur le poids
En configurant plusieurs services Kubernetes, la règle de canary basée sur le poids peut être appliquée comme suit :
apiVersion: apisix.apache.org/v2alpha1
kind: ApisixRoute
metadata:
name: foo-route
spec:
http:
- name: rule1
match:
hosts:
- foo.org
paths:
- /get*
backends:
- serviceName: foo-canary
servicePort: 80
weight: 10
- serviceName: foo
servicePort: 80
weight: 5
Le cas ci-dessus achemine ⅔ des requêtes dont l'hôte est "foo.org" et dont le chemin URI commence par "/get" vers le service "foo-canary" et les autres vers "foo".
Le poids pour le service canary peut être faible pour une vérification à petite échelle, et augmenter le poids en modifiant ApisixRoute jusqu'à ce que tout le trafic soit acheminé vers le service canary, terminant ainsi complètement le déploiement.
Basé sur des règles
Le champ Exprs dans ApisixRoute permet aux utilisateurs de configurer des règles de correspondance de route personnalisées. D'autre part, plusieurs règles de route peuvent être regroupées dans un seul objet ApisixRoute, ce qui permet une manière transparente de mettre en œuvre le fractionnement du trafic basé sur des règles.
apiVersion: apisix.apache.org/v2alpha1
kind: ApisixRoute
metadata:
name: foo-route
spec:
http:
- name: rule1
priority: 1
match:
hosts:
- foo.org
paths:
- /get*
backends:
- serviceName: foo
servicePort: 80
- name: rule2
priority: 2
match:
hosts:
- foo.org
paths:
- /get*
exprs:
- subject:
scope: Query
name: id
op: In
set:
- "3"
- "13"
- "23"
- "33"
backends:
- serviceName: foo-canary
servicePort: 80
Les requêtes dont l'hôte est "foo.org" et dont le chemin URI commence par "/get" seront séparées en deux parties :
- Le paramètre id dont la valeur est 3, 13, 23 ou 33 déclenchera la règle2 et sera acheminé vers foo-canary ;
- Les autres déclencheront la règle1 et seront acheminés vers foo.
Résumé
Le fractionnement du trafic (Canary release) dans Ingress Nginx prend en charge le schéma basé sur le poids et celui basé sur les règles d'en-tête, mais il repose sur des annotations, dont la sémantique est faible ; La méthode Kong ne prend en charge que la configuration du canary release par poids, les scénarios sont quelque peu limités, et la configuration est compliquée (vous devez configurer plusieurs ressources) ; En revanche, le fractionnement du trafic dans Apache APISIX Ingress Controller est flexible et facile à configurer, il fonctionne bien pour les schémas de fractionnement du trafic basés sur le poids et sur les règles.