Pour le service de sauvegarde Clumio Protect, nous utilisons Amazon Elastic Kubernetes Service (EKS) afin de gérer nos clusters Kubernetes. Le principal avantage d’utiliser un Kubernetes géré réside dans l’intégration étroite avec les autres services de votre fournisseur de cloud. Plus précisément, lorsque vous créez un nouveau service Kubernetes, un contrôleur de service, fourni par AWS et installé dans le cluster, crée une nouvelle instance d’Elastic Load Balancer (ELB) et la configure pour acheminer le trafic vers le service. Parallèlement, ce contrôleur gère l’ensemble du cycle de vie de l’équilibreur de charge correspondant : il assure une configuration correcte de ses contrôles d’intégrité et met à jour le groupe cible de l’équilibreur de charge lorsque vous ajoutez ou supprimez des nœuds du cluster. Enfin, il supprime l’équilibreur de charge lorsque vous supprimez votre service Kubernetes du cluster.
Bien qu’il soit très pratique d’utiliser des services Kubernetes s’appuyant sur des équilibreurs de charge AWS, plusieurs éléments doivent être pris en compte.
L’architecture cloud native de Clumio
Notre architecture repose sur des microservices, et chacun de nos clusters Kubernetes en compte plusieurs dizaines. Le nombre de services est particulièrement élevé dans nos clusters de développement, où nous hébergeons autant d’environnements de développement isolés que possible au sein d’un même cluster. Certains clusters de développement comptent plus de 300 services, et ce chiffre ne cesse d’augmenter. Il va sans dire que chaque équilibreur de charge AWS a un coût et qu’il serait déraisonnable pour nous de disposer de plus de 300 équilibreurs de charge AWS uniquement pour un seul cluster de développement. Un autre problème réside dans la limite du nombre d’équilibreurs de charge que chaque cluster EKS peut prendre en charge. Cette limite est liée au nombre maximal de règles dans un groupe de sécurité EC2. Concrètement, un cluster EKS moyen ne pouvait pas compter plus de 60 équilibreurs de charge classiques. Pour résoudre ce problème, nous avons décidé d’utiliser Kubernetes Ingress pour la plupart de nos services. Le mécanisme Ingress nous permet de partager un seul ELB entre plusieurs services au sein d’un cluster EKS, ce qui réduit l’utilisation des ressources et les coûts.
Pourquoi ajouter un Ingress Kubernetes ?
La création d’un nouvel équilibreur de charge AWS prend généralement un certain temps. Ce délai est acceptable pour la plupart des opérations ; toutefois, pour certaines modifications, comme le déploiement simultané de plusieurs microservices, nous souhaitions réduire au minimum le temps nécessaire à leur Readiness. Pour répondre à ce cas d’utilisation, l’ajout d’un nouvel Ingress Kubernetes permet une Readiness instantanée. Selon l’implémentation spécifique, un contrôleur Ingress doit soit recharger la nouvelle configuration, à l’instar des contrôleurs Ingress Nginx, soit appliquer la nouvelle configuration à l’exécution, à l’instar des contrôleurs Ingress basés sur Envoy.
Lorsque l’on travaille avec des services, on s’attend à ce que chacun d’entre eux dispose d’un nom DNS, éventuellement externe. Avec l’approche « un ELB par service », il n’est pas possible de créer un nom DNS tant que l’ELB n’a pas été créé. En utilisant un seul ELB pré-alloué pour le contrôleur Ingress, il est possible d’attribuer à l’avance autant d’alias DNS que souhaité à cet ELB, ce qui permet à tous nos services d’être disponibles dès que nous créons des définitions Ingress pour chacun d’entre eux.
Certains de nos services exposent une API REST, mais la grande majorité d’entre eux disposent de points de terminaison gRPC. Nous avions besoin d’un contrôleur Ingress prenant en charge à la fois HTTPS et gRPC, et nous souhaitions que le protocole TLS soit géré au niveau du contrôleur Ingress. Cette dernière exigence n’était pas impérative, et nous avons envisagé d’utiliser des sidecars Istio pour terminer le TLS directement dans un pod de microservice. Cependant, nous avons décidé d’utiliser le contrôleur Ingress pour terminer le TLS, car il est plus simple à gérer et impose en général moins de surcharge au cluster. Une autre exigence était de pouvoir déployer plusieurs instances du contrôleur Ingress sur le même cluster. Une définition Ingress spécifique peut comporter une annotation kubernetes.io/ingress.class pour indiquer quel contrôleur Ingress doit être utilisé.
Nous avons testé plusieurs contrôleurs Ingress et avons constaté qu’il était étonnamment difficile d’en trouver un qui réponde à toutes nos exigences. Certains contrôleurs ne fonctionnaient pas correctement avec gRPC, d’autres ne prenaient pas en charge plusieurs instances de contrôleur au sein d’un même cluster. Finalement, nous avons constaté que le contrôleur Ingress de NGINX répondait à nos besoins. Nous n’avons dû apporter qu’un léger ajustement à sa configuration afin d’augmenter la taille du tampon gRPC pour qu’il fonctionne avec notre pile gRPC.
Nous améliorons constamment nos services au niveau de l’infrastructure afin de la faire évoluer et d’optimiser les coûts de maintenance. Au départ, nous utilisions un équilibreur de charge dédié par service, mais nous avons très vite atteint la limite du nombre d’équilibreurs de charge autorisés par cluster. Nous avons alors mis à jour notre infrastructure pour utiliser des contrôleurs Ingress hébergés afin d’assurer la connectivité externe de nos services, ce qui nous a permis de réduire considérablement le nombre d’équilibreurs de charge AWS classiques nécessaires au fonctionnement du produit. L’utilisation d’AWS Application Load Balancer (ALB) n’était pas envisageable à l’époque, car ALB ne prenait pas en charge gRPC. Fin 2020, AWS a annoncé avoir ajouté la prise en charge de HTTP/2 de bout en bout et de gRPC pour Application Load Balancer. Nous pouvons désormais utiliser le contrôleur AWS Load Balancer, anciennement connu sous le nom d’« AWS ALB Ingress Controller », qui a été transféré au groupe d’intérêt spécial Kubernetes AWS (SIG-AWS) afin de permettre à AWS et aux autres contributeurs du SIG-AWS d’assurer officiellement la maintenance du projet. Nous sommes impatients d’utiliser ce contrôleur Ingress pour notre infrastructure. Nous nous intéressons également à l’API Kubernetes Gateway, une nouvelle API Kubernetes actuellement en cours de développement par le groupe d’intérêt spécial Network (SIG-Network). Par rapport à l’API Ingress, l’API Gateway propose une API de proxy plus générale, compatible avec davantage de protocoles que le simple HTTP, et modélise davantage de composants d’infrastructure afin d’offrir de meilleures options de déploiement et de gestion aux opérateurs de clusters. Nous sommes impatients de tester les futurs contrôleurs Kubernetes implémentant l’API Gateway.
Réduire la consommation de ressources et les coûts
Le mécanisme Ingress de Kubernetes nous aide à réduire l’utilisation des ressources et les coûts. Nous ne sommes plus limités par les contraintes d’EC2 et d’EKS concernant le nombre de services déployés sur un même cluster Kubernetes géré. Certains contrôleurs Ingress open source prennent en charge les services gRPC dès leur installation, mais nécessitent une vérification supplémentaire pour s’assurer qu’ils fonctionnent correctement dans un cas d’utilisation spécifique. La communauté Kubernetes fournit et améliore en permanence les API Kubernetes, telles que l’API Ingress ou l’API Gateway, tandis que les fournisseurs commerciaux et open source proposent diverses implémentations de ces API. Cela permet de choisir l’implémentation la mieux adaptée à un cas d’utilisation spécifique et de remplacer les implémentations sans modifications majeures au niveau de l’application.