Aller au contenu

Comprendre Kubernetes Ingress : Plongée dans le vrai Load-balancer

Cet article explore l'importance de l'exposition des applications hors de Kubernetes et compare les services Kubernetes aux loadBalancers Ingress. Il offre un aperçu des différences, des implémentations possibles et des cas d'utilisation pour chaque type de ressource.

Comprendre Kubernetes Ingress : Plongée dans le vrai Load-balancer

L'exposition des applications en dehors de Kubernetes est l'un des objectifs les plus importants du processus de déploiement - c'est en fin de compte l'objectif final. C'est pourquoi nous recherchons des ressources capables d'exposer et de gérer le trafic des pods vers les utilisateurs externes, communément appelées ressources Edge.
Il s'agit bien d'un équilibreur de charge, mais lequel ? L'équilibreur de charge de service ou la ressource Ingress ?
Dans cet article, nous allons explorer les différences entre les services Kubernetes (ClusterIP, NodePort, ExternalName et LoadBalancer) et les équilibreurs de charge Ingress. Nous ferons un rappel historique, approfondirons les implémentations possibles et les cas d'utilisation.

Histoire et évolution

Commençons par un peu d'histoire ! Lorsque la première version de Kubernetes 1.0.0 est sortie en 2015, la seule solution pour exposer le trafic était de passer par l'un des services Kubernetes.

Il existait principalement quatre types de services :

  • ClusterIP : expose le service sur une IP interne dans le cluster uniquement, permettant à d'autres services au sein du cluster de communiquer avec lui.
  • NodePort : expose le service sur un port statique sur l'IP de chaque nœud, permettant l'accès depuis l'extérieur du cluster.
  • LoadBalancer : fournit un équilibreur de charge externe dans l'infrastructure du fournisseur de Cloud pour distribuer le trafic vers le service.
  • ExternalName : associe le service au contenu du champ externalName, ce qui permet d'accéder au service par un nom externe.

Quel service conviendra le mieux à notre besoin ? Par élimination, nous pouvons écarter ClusterIP, qui est uniquement un service interne. NodePort s'appuie sur les NodeIP, qui sont éphémères et externes, et ExternalName utilise des CNames au lieu de labels, ce qui ne convient pas à notre cas. Par conséquent, le LoadBalancer apparaît comme la meilleure solution pour nos besoins.

Voici un exemple de manifeste de service LoadBalancer :

apiVersion: v1
kind: Service
metadata:
  name: example-service
spec:
  selector:
    app: example
  ports:
    - port: 8765
      targetPort: 9376
  type: LoadBalancer

Après avoir appliqué ce manifeste de service dans un environnement Kubernetes géré, et attendu quelques secondes pour permettre à Kubernetes d'opérer sa magie en coulisses, vous obtiendrez quelque chose de similaire à ceci :

NAME       TYPE      CLUSTER-IP      EXTERNAL-IP      PORT(S)        AGE
my-service  LoadBalancer 10.100.200.20   203.0.113.10  80:32452/TCP    3h

À ce stade, l'application devient accessible via l'adresse IP externe 10.100.200.20, grâce au Cloud Controller Manager (CCM). Ce composant des clusters géré par Kubernetes fait office de pont entre les ressources Kubernetes et les services Cloud. En coulisses, lorsque le CCM détecte la création d'un nouveau service LoadBalancer, il interagit avec l'infrastructure du fournisseur de Cloud pour créer un véritable équilibreur de charge. Cet équilibreur de charge mappe alors le trafic du service à l'intérieur du cluster vers l'équilibreur de charge dans le Cloud.
Imaginons maintenant que nous ayons une architecture microservices. Voici à quoi ressemblerait le résultat final :

Cette architecture peut s'avérer coûteuse car elle nécessite un équilibreur de charge dédié pour chaque service. Il est donc nécessaire de trouver une solution centralisée qui gère l'ensemble du trafic en un seul point. C'est là qu'Ingress entre en jeu. La ressource Ingress a été ajoutée à Kubernetes en décembre 2015, à partir de la version 1.1.0 (en tant que ressource bêta). Voici comment fonctionne la meilleure pratique mise en œuvre par ingress :

Ingress est une ressource périphérique de Kubernetes conçue pour exposer le trafic des services à une URL publique. Elle offre des utilitaires avancés d'équilibrage de charge tels que l'interception des requêtes, la terminaison SSL/TLS, l'hébergement virtuel basé sur le nom, les règles de routage (hôte, chemin d'accès, etc.), et bien plus encore.

Ces fonctionnalités de routage sont configurées sur la base de règles déclaratives dans le manifeste ingress (se référer à la documentation Kubernetes Ingress pour plus de détails). Voici un exemple des options de routage :

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-wildcard-host
spec:
  rules:
  - host: "foo.bar.com" # domain name based routing
    http:
      paths:
      - pathType: Prefix  
        path: "/bar" # Path routing
        backend:
          service:   # Exposed service
            name: service1
            port:
              number: 80

Dans la nouvelle architecture, l'équilibreur de charge est géré par Ingress, spécifiquement mis en œuvre pour gérer les ressources Ingress. C'est l'une des raisons pour lesquelles il est nécessaire de disposer d'une ressource pour gérer Ingress, connue sous le nom de contrôleur Ingress. Selon l'architecture de l'environnement, au moins un des contrôleurs Ingress maintenus par la communauté Kubernetes doit être déployé dans le cluster.

Il existe deux types principaux de contrôleurs Ingress, chacun avec des modèles de mise en œuvre complètement différents.

  • Ingress basé sur un serveur web
  • Ingress basé sur un loadBalancer sur le Cloud.

Pour aller plus loin, étudions les avantages et les inconvénients de chacun d'entre eux ;)

Ingress basé sur un serveur web :

Ce type de contrôleur Ingress est basé sur un serveur web réel tel que NGINX ou HAproxy. En coulisse, lorsque ce type de contrôleur est déployé, il démarre un serveur web NGINX dans le cluster. La tâche du contrôleur consiste à convertir le modèle de configuration Ingress fourni dans le manifeste Ingress en une configuration réelle pour le serveur web. Ensuite, il met à jour le fichier de configuration générique.

Par exemple, si nous utilisons le contrôleur Ingress-Nginx, chaque fois qu'un Ingress est déployé, une mise à jour est effectuée dans le fichier nginx.conf du côté du contrôleur afin d'inclure le point d'extrémité nouvellement créé.

Prenons l'exemple de ce manifeste Ingress :

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /app
        pathType: Prefix
        backend:
          service:
            name: app-service
            port:
              number: 80

La configuration équivalente dans Nginx est indiquée ci-dessous :

http {
  server {
    server_name example.com;

    location /app {
      proxy_pass http://app-service:80;
    }
  }
}

Comme le montre la figure ci-dessus, pour ce type de contrôleur Ingress, nous avons besoin d'un équilibreur de charge de couche 4 (couche de transport). Le serveur web Ingresss, dans cet exemple Nginx, gérera le trafic du réseau d'application.
La terminaison SSL est mise en place exclusivement à l'extérieur du cluster Kubernetes, spécifiquement avant la ressource Ingress. Cette configuration permet de configurer facilement un certificat SSL/TLS puisqu'il n'y a qu'un seul point d'entrée du trafic qui fait partie du cluster lui-même.

Avantages :

  • Solution native Kubernetes et configuration centralisée.
  • Gestion TLS : nous pouvons déployer des outils de gestion de certificats pour gérer le cycle de vie des certificats et les fonctions de sécurité avancées dans le cluster Kubernetes lui-même.
  • Monitoring : nous pouvons exposer et gérer au niveau du cluster différents signaux de requête (latence, trafic, erreurs...).

Inconvénients :

  • Consommation de ressources : lorsqu'il est déployé sur Kubernetes, nous devons tenir compte d'une consommation élevée de ressources pour l'équilibrage de la charge, l'exécution des règles de routage et d'autres configurations.
  • Frais de maintenance : Il ne s'agit pas d'un service géré, nous devons donc gérer nous-mêmes les mises à jour et l'assistance.

Ingress basé sur un Load-balancer sur le Cloud

D'autre part, les contrôleurs d'entrée de LoadBalancer sur le Cloud dépendent de services gérés sur le Cloud. Tous les processus d'équilibrage de la charge sont essentiellement gérés par des LoadBalancers provisionnés dans le Cloud. Le trafic est dirigé par le gestionnaire du contrôleur du Cloud vers les cibles. Dans ce mode de mise en œuvre, nous opérons en dehors du contexte Kubernetes, car toutes les configurations sont effectuées dans un autre type d'équilibreur de charge externe au cluster.

Prenons un exemple concret de l'un des fournisseurs de services Cloud les plus utilisés, AWS. Ce dernier a mis en place un contrôleur Ingress basé sur AWS Application Load Balancer (ALB), connu sous le nom de "aws-alb-ingress-controller" :

Pour plus d'informations, consultez la documentation officielle d'Amazon, Kubernetes Ingress with AWS ALB Ingress Controller.

Avantages

  • Intégration native dans les clusters gérés (EKS, AKS, GKE...).
  • Service géré : Pas de maintenance et moins de responsabilité.
  • Haute disponibilité : en utilisant AWS ALB, il est autoscaling.

Inconvénients

  • Coût : les services gérés sont couteux.
  • Accessibilité limitée et nécessité de connaître le fournisseur de Cloud.

Résumé

Dans un cluster Kubernetes, Ingress c'est le Loadbalancer principal, et le choix de l'implémentation dépend de vos besoins spécifiques. Cet article vise à démystifier Ingress en approfondissant ses mécanismes sous-jacents et en soulignant les distinctions entre les contrôleurs d'ingress basés sur le web et ceux basés sur le Cloud.

Dernier