Pourquoi AISpeech choisit Apache APISIX plutôt que NGINX comme contrôleur Ingress pour k8s

Wei Jin

May 7, 2020

Case Study

Préface

Bonjour à tous, je suis Jin Wei d'AISpeech, une entreprise de haute technologie spécialisée dans la reconnaissance et l'analyse de la parole informatique, et je suis ici pour parler de l'intégration d'Apache APISIX avec K8s à la place de l'ingress natif.

Au moment de la rédaction, Apache APISIX a déjà été appliqué à notre environnement de production et a pris en charge une partie du trafic d'entrée des services. Nous migrons progressivement le trafic de l'ingress natif, comme le montre la figure ci-dessous.

Diagramme d'architecture

En fait, APISIX-ingress-controller enregistre l'ip du pod dans le nœud upstream, de sorte que le trafic des services peut accéder directement au pod et contourner le DNS kube. Vous pouvez implémenter certaines politiques de répartition de charge particulières via des plugins basés sur cela. Par conséquent, d'une part, nous nous appuyons sur cette capacité de routage dynamique d'Apache APISIX pour la distribution du trafic. D'autre part, nous ajoutons des plugins personnalisés pour répondre aux besoins des services.

D'après le diagramme ci-dessus, APISIX-ingress-controller semble redondant avec l'ingress natif. Dans cet article, nous expliquerons brièvement pourquoi nous avons abandonné l'ingress natif et construit notre propre contrôleur ingress basé sur Apache APISIX.

Qu'est-ce que l'Ingress

En un mot, Ingress est un moyen pour Kubernetes de gérer le trafic externe.

Quel problème Ingress résout-il

Puisque les services au sein d'un cluster Kubernetes sont des réseaux virtuels, le trafic externe nécessite au moins une ip publique et un port correctement mappé pour accéder aux services internes du cluster.

Kubernetes dispose de plusieurs moyens (NodePort, LoadBalancer, Ingress, …) pour exposer des interfaces permettant d'accéder aux services internes de Kubernetes. En comparaison, Ingress est certainement une manière plus économique d'atteindre un proxy inverse en exposant un nombre limité d'IP publiques.

En parlant de proxy inverse, nous pourrions également construire un NGINX directement pour le faire, mais il est significativement plus difficile de maintenir la synchronisation de l'état des services, qui varie facilement dans Kubernetes, dans NGINX.

La bonne nouvelle est que Kubernetes fournit et maintient officiellement un contrôleur ingress NGINX pour aider à résoudre le proxy inverse. Avec ce contrôleur ingress NGINX, nous pouvons rediriger tout le trafic souhaitant accéder à Kubernetes et le pointer correctement vers les services backend.

Problèmes avec le contrôleur ingress natif de Kubernetes

Le contrôleur ingress NGINX nous aide à maintenir la synchronisation de l'état entre le cluster Kubernetes et NGINX, et fournit des capacités de proxy inverse de base, alors pourquoi construisons-nous notre propre ingress ? Nous attendons plus du contrôleur ingress pour répondre à davantage de besoins des services.

Après avoir utilisé le contrôleur ingress natif de Kubernetes, nous avons trouvé que les problèmes suivants étaient prédominants :

  1. Problème de rechargement

    L'ingress natif de Kubernetes est conçu pour passer des fichiers de configuration YAML au contrôleur ingress, les convertir en fichiers de configuration NGINX, puis déclencher un rechargement pour que la configuration prenne effet.

    Cela est inacceptable, surtout lorsque le trafic utilise des connexions longues, ce qui peut entraîner des accidents.

    En revanche, Apache APISIX supporte le rechargement à chaud des configurations, vous pouvez donc définir et modifier les routes à tout moment sans déclencher un rechargement de NGINX.

  2. Écriture de scripts et remplissage de paramètres dans les annotations

    Le contrôleur ingress natif supporte des extraits de script définis par annotation dans le fichier YAML, ce qui ressemble à une solution temporaire pour supporter des fonctionnalités avancées et est, franchement, vraiment ingérable. Le grand nombre de scripts d'annotation pose des problèmes au personnel DevOps.

    Dans Apache APISIX, nous pouvons écrire la logique via le code du plugin pour exposer une interface de configuration simple qui facilite la maintenance de la configuration et évite l'interférence des scripts avec le personnel DevOps.

  3. Manque de support pour la répartition de charge avec état

    Les politiques de répartition de charge avancées ne sont pas supportées, comme la "persistance de session", etc. Kubernetes est un système de gestion d'applications conteneurisées orienté opérations, ce qui peut avoir à voir avec le fait que Kubernetes promeut une approche de déploiement sans état, donc Kubernetes ne supportera pas officiellement ces politiques de répartition de charge contradictoires dans un avenir proche. En fait, Google a déjà essayé de résoudre ces problèmes avec sa solution de maillage de services (Istio). L'architecture d'Istio est parfaite, mais au détriment des performances, ce qui pourrait être résolu avec mixer v2.

    Puisque Kubernetes supporte la mise à l'échelle, nous pouvons également étendre Apache APISIX pour répondre à nos besoins avancés de répartition de charge, car Apache APISIX supporte non seulement nativement la "persistance de session" et d'autres répartitions de charge, mais a également la capacité de mettre à l'échelle la phase de répartition de charge.

  4. Poids dynamiques

    Les services métier ont souvent besoin de contrôler le trafic par pourcentage, ce qui devient un problème dans Kubernetes.

    Bien que Kubernetes supporte IPVS (IP Virtual Server) après la version 1.8, ni les paramètres de démarrage de "kube-proxy" ni l'annotation de "kube-route" ne sont aussi faciles à utiliser qu'Apache APISIX, qui abstrait en interne les objets principaux comme route, service, consommateur, upstream, plugin, etc. Ajuster le poids de telles opérations est naturellement supporté, simplement en modifiant le "poids du nœud" sous "upstream".

  5. Capacités d'extension inflexibles

    Bien qu'Ingress ait été initialement conçu pour gérer le trafic externe, il n'y a pas moins de demandes pour le trafic externe que pour le trafic interne.

    La publication canari au niveau du service, la coupure de circuit, le contrôle de flux, l'authentification, le contrôle du trafic, et d'autres exigences sont plus couramment implémentées sur Ingress.

    Apache APISIX fournit un support de plugin pour l'extensibilité, et en plus des plugins officiels, vous pouvez personnaliser des plugins pour répondre à vos propres caractéristiques.

    Il y a aussi quelques problèmes de configuration causés par ConfigMap et Namespaces, qui sont liés à la manière dont nous les utilisons et ne sont pas génériques, donc je ne vais pas les aborder ici.

Contrôleur Ingress Apache APISIX

Grâce aux puissantes capacités de routage et d'extension d'Apache APISIX, utiliser Apache APISIX comme implémentation d'Ingress peut facilement résoudre les points douloureux mentionnés ci-dessus et fournir à la communauté une option supplémentaire de contrôleur ingress. Le diagramme de séquence est le suivant :

Diagramme de séquence

Pour implémenter le contrôleur ingress Apache APISIX, nous devons résoudre deux types de problèmes fondamentaux : l'un est de résoudre la synchronisation entre l'état du cluster Kubernetes et Apache APISIX ; l'autre est de définir les objets dans Apache APISIX dans Kubernetes (CRD).

Afin d'intégrer rapidement Apache APISIX et de tirer parti de celui-ci, nous avons créé le projet Apache APISIX ingress controller (tout le monde est bienvenu à participer), qui implémente actuellement le premier type de problème fondamental : synchroniser les informations des pods Kubernetes vers l'upstream d'Apache APISIX, tout en implémentant une sauvegarde principale pour résoudre ses propres problèmes de haute disponibilité.

Puisque Kubernetes utilise YAML pour définir l'état du cluster de manière déclarative, nous devons définir CRD (Custom Resource Definitions) pour les objets (route/service/upstream/plugin) dans Apache APISIX pour être intégrés dans Kubernetes.

De plus, pour faciliter la migration des utilisateurs existants d'ingress Kubernetes, nous essaierons d'être compatibles avec les éléments de configuration d'ingress existants.

Ces fonctionnalités seront l'objectif de nos prochains efforts, et nous vous invitons à participer.

Tags: