Fractionnement du trafic dans Apache APISIX Ingress Controller

Fei Han

March 27, 2021

Products

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".)

1.png

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.

Share article link