Maîtriser Docker et Kubernetes : Déploiement et Scalabilité d'Applications Modernes
Maîtriser Docker et Kubernetes : Déploiement et Scalabilité d'Applications Modernes

Mise à l'échelle et Autoscaling avec Kubernetes

Bienvenue dans cette leçon consacrée à la mise à l'échelle et à l'autoscaling dans Kubernetes, des concepts fondamentaux pour toute application moderne nécessitant élasticité et résilience. Dans le cadre de notre cours "Maîtriser Docker et Kubernetes : Déploiement et Scalabilité d'Applications Modernes", vous allez découvrir comment Kubernetes permet à vos applications de s'adapter dynamiquement aux variations de charge, garantissant ainsi performance et efficacité.

Introduction : Le Cœur de la Flexibilité en Cloud

Dans un monde où les charges de travail fluctuent constamment – que ce soit un pic de trafic sur un site e-commerce pendant le Black Friday, une augmentation soudaine d'utilisateurs sur une application mobile, ou simplement les variations quotidiennes d'activité – la capacité d'une application à s'adapter est primordiale. C'est ici qu'interviennent la mise à l'échelle (scaling) et l'autoscaling.

  • Mise à l'échelle (Scaling) : Il s'agit du processus d'ajustement des ressources allouées à une application pour répondre à la demande. Cela peut impliquer l'ajout ou la suppression de serveurs, de processus ou de conteneurs.
  • Autoscaling : C'est la capacité d'un système à ajuster automatiquement ses ressources en fonction de métriques prédéfinies (CPU, mémoire, requêtes par seconde, etc.) et sans intervention humaine. C'est le Graal de l'efficacité opérationnelle, car il optimise les coûts et assure la performance.

Kubernetes, de par sa nature orchestratrice, est parfaitement outillé pour gérer ces aspects, offrant des mécanismes sophistiqués pour garantir que vos applications disposent toujours des bonnes ressources au bon moment.

Pourquoi la Mise à l'Échelle est Cruciale ?

La mise à l'échelle est essentielle pour plusieurs raisons :

  • Performance : Maintenir un temps de réponse acceptable même sous forte charge.
  • Disponibilité : Répartir la charge sur plusieurs instances pour éviter les points de défaillance uniques.
  • Coût : Éviter le sur-provisionnement de ressources en période de faible demande, et assurer l'accès aux ressources nécessaires en période de pointe.
  • Résilience : Permettre au système de se rétablir plus facilement des défaillances en remplaçant les composants défectueux.

Les Différents Types de Mise à l'Échelle dans Kubernetes

Kubernetes offre plusieurs stratégies de mise à l'échelle, chacune répondant à des besoins spécifiques :

  1. Scaling Horizontal : Ajouter ou supprimer des Pods.
  2. Scaling Vertical : Ajuster les ressources (CPU/mémoire) d'un Pod existant.
  3. Scaling au Niveau du Cluster : Ajouter ou supprimer des nœuds Worker.

Explorons chacun de ces mécanismes en détail.

1. Le Scaling Horizontal : Horizontal Pod Autoscaler (HPA)

Le Horizontal Pod Autoscaler (HPA) est sans doute le mécanisme d'autoscaling le plus couramment utilisé dans Kubernetes. Il ajuste automatiquement le nombre de réplicas de Pods dans un Deployment, ReplicaSet, ou StatefulSet en fonction de métriques observées.

Comment fonctionne le HPA ?

Le HPA agit comme un contrôleur dans Kubernetes. Il surveille en permanence les métriques spécifiées (généralement l'utilisation du CPU ou de la mémoire) pour les Pods cibles. Si une métrique dépasse (pour le scaling up) ou tombe en dessous (pour le scaling down) d'un seuil défini, le HPA indique au contrôleur du Deployment/ReplicaSet d'augmenter ou de diminuer le nombre de Pods.

Les métriques peuvent être :

  • Utilisation du CPU : Pourcentage d'utilisation du CPU par rapport à la requête (request) définie pour le Pod.
  • Utilisation de la mémoire : Pourcentage d'utilisation de la mémoire par rapport à la requête (request) définie pour le Pod.
  • Métriques personnalisées : Des métriques spécifiques à l'application (ex: requêtes par seconde, longueur de file d'attente).
  • Métriques externes : Des métriques provenant de sources externes au cluster (ex: longueur d'une file SQS, nombre de messages Kafka).

Configuration du HPA : La Pratique

Pour que le HPA fonctionne, votre cluster Kubernetes doit avoir le Metrics Server installé. Le Metrics Server est un agrégateur de données sur l'utilisation des ressources (CPU et mémoire) pour les nœuds et les Pods.

Étape 1 : Prérequis - Le Metrics Server

Assurez-vous que le Metrics Server est déployé dans votre cluster. Sur minikube, c'est généralement activé par minikube addons enable metrics-server. Pour d'autres distributions, référez-vous à leur documentation ou utilisez :

kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

Attendez quelques instants que les Pods du Metrics Server soient en cours d'exécution :

kubectl get pods -n kube-system | grep metrics-server
Étape 2 : Déploiement d'une Application Démontrable

Nous allons déployer une application php-apache qui consomme du CPU lorsque vous accédez à sa page. C'est une excellente façon de démontrer le scaling par CPU.

Créez un fichier php-apache-app.yaml :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: php-apache
spec:
  selector:
    matchLabels:
      app: php-apache
  replicas: 1 # Commençons avec un seul replica
  template:
    metadata:
      labels:
        app: php-apache
    spec:
      containers:
      - name: php-apache
        image: k8s.gcr.io/hpa-example
        ports:
        - containerPort: 80
        resources:
          requests: # Très important pour le HPA : définir les requêtes de ressources
            cpu: 200m # 200 milli-cœurs, soit 20% d'un cœur CPU

Appliquez ce déploiement :

kubectl apply -f php-apache-app.yaml

Exposez-le via un Service :

apiVersion: v1
kind: Service
metadata:
  name: php-apache
spec:
  selector:
    app: php-apache
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: ClusterIP # Ou NodePort si vous testez depuis l'extérieur du cluster

Appliquez le service :

kubectl apply -f php-apache-service.yaml
Étape 3 : Création du Horizontal Pod Autoscaler (HPA)

Maintenant, créons l'objet HPA qui va surveiller l'utilisation du CPU de notre déploiement php-apache. Nous allons le configurer pour maintenir l'utilisation du CPU à 50% de la requête allouée (200m), soit 100m. Si l'utilisation dépasse 50%, il ajoutera des Pods, et si elle est bien en dessous, il en supprimera.

Créez un fichier hpa.yaml :

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache # Cible le déploiement que nous avons créé
  minReplicas: 1 # Nombre minimum de Pods
  maxReplicas: 10 # Nombre maximum de Pods
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50 # Cible 50% d'utilisation du CPU

Appliquez le HPA :

kubectl apply -f hpa.yaml

Vérifiez le statut du HPA :

kubectl get hpa php-apache-hpa

Vous devriez voir quelque chose comme :

NAME             REFERENCE         TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
php-apache-hpa   Deployment/php-apache   0%/50%    1         10        1          Xm

TARGETS indique 0%/50% car il n'y a pas encore de charge.

Étape 4 : Génération de Charge pour Activer l'Autoscaling

Pour que le HPA réagisse, nous devons augmenter la charge sur notre application. Nous allons utiliser un Pod busybox pour envoyer des requêtes en continu à notre service php-apache.

Obtenez l'IP du Service php-apache (ou utilisez le nom du service si vous êtes à l'intérieur du cluster) :

kubectl get svc php-apache

Disons que l'IP est 10.96.123.45.

Lancez un Pod busybox qui va générer du trafic :

kubectl run -it --rm --restart=Never busybox --image=busybox -- /bin/sh -c "while true; do wget -q -O- http://php-apache; done"

Note: http://php-apache fonctionne si vous exécutez busybox dans le même namespace. Sinon, utilisez l'IP du service.

Laissez cette commande s'exécuter dans un terminal séparé.

Étape 5 : Observation du Scaling

Ouvrez un nouveau terminal et surveillez le HPA et les Pods :

kubectl get hpa php-apache-hpa -w

Et dans un autre terminal, surveillez les Pods :

kubectl get pods -l app=php-apache -w

Vous devriez observer le TARGETS du HPA augmenter progressivement. Une fois qu'il dépasse 50%, le REPLICAS va augmenter, et de nouveaux Pods php-apache seront créés.

NAME             REFERENCE         TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
php-apache-hpa   Deployment/php-apache   90%/50%   1         10        1          Xm
php-apache-hpa   Deployment/php-apache   90%/50%   1         10        2          Xm  <-- Scaling Up!
php-apache-hpa   Deployment/php-apache   75%/50%   1         10        3          Xm
...

Une fois que vous arrêtez le busybox (Ctrl+C), la charge diminuera, et après une période de stabilisation, le HPA réduira progressivement le nombre de Pods à minReplicas.

2. Le Scaling Vertical : Vertical Pod Autoscaler (VPA)

Le Vertical Pod Autoscaler (VPA) est un autre type d'autoscaling, mais au lieu d'ajouter ou de supprimer des Pods, il ajuste les requêtes (requests) et les limites (limits) de ressources (CPU et mémoire) pour les Pods existants.

Comment fonctionne le VPA ?

Le VPA observe l'utilisation réelle des ressources par vos Pods au fil du temps. Il utilise ces données pour recommander ou appliquer automatiquement de nouvelles valeurs pour les requests et limits de CPU et de mémoire.

Le VPA est composé de trois principaux composants :

  • Recommender : Il observe l'utilisation historique et actuelle des ressources par les Pods et calcule les valeurs recommandées pour les requests et limits.
  • Updater : Il expulse (cordonne et draine) les Pods qui n'ont pas les bonnes requêtes/limites, permettant au contrôleur du déploiement de recréer les Pods avec les nouvelles configurations recommandées par le Recommender.
  • Admission Controller : Il intercepte les nouvelles créations de Pods et injecte les requests et limits recommandées par le Recommender.

Cas d'Usage et Limitations du VPA

Le VPA est utile pour :

  • Optimiser l'utilisation des ressources : S'assurer que les Pods ne sont ni sous-provisionnés (leading à des problèmes de performance) ni sur-provisionnés (gaspi de ressources).
  • Simplifier la configuration des ressources : Vous n'avez plus besoin de deviner les valeurs initiales pour vos requests et limits.

Limitations :

  • Redémarrages de Pods : Si l'Updater est activé pour appliquer les changements, il peut redémarrer vos Pods, ce qui peut entraîner une brève interruption de service. Ce comportement est souvent indésirable pour des applications sensibles.
  • Exclusivité avec HPA : Un Pod ne peut pas être à la fois géré par un VPA et un HPA pour la même ressource (ex: CPU). Si vous utilisez le VPA pour le CPU, vous ne pouvez pas utiliser le HPA pour le CPU sur les mêmes Pods. Cependant, vous pouvez combiner HPA pour le CPU et VPA pour la mémoire.
  • Statut Expérimental/Alpha : Historiquement, le VPA a souvent été en phase alpha/bêta, et son adoption n'est pas aussi généralisée que le HPA.

3. Le Scaling au Niveau du Cluster : Cluster Autoscaler (CA)

Alors que le HPA gère le nombre de Pods et le VPA les ressources par Pod, que se passe-t-il si votre cluster manque de nœuds pour accueillir de nouveaux Pods ? C'est là qu'intervient le Cluster Autoscaler (CA).

Le Cluster Autoscaler n'est pas une fonctionnalité intégrée de Kubernetes au même titre que le HPA, mais un composant additionnel qui interagit avec l'API de votre fournisseur de cloud (AWS, GCP, Azure, etc.) ou votre infrastructure on-premise pour ajuster le nombre de nœuds dans votre cluster.

Comment fonctionne le CA ?

Le CA surveille les événements dans le cluster pour décider quand ajouter ou supprimer des nœuds :

  • Scaling Up (Ajout de nœuds) :
    • Lorsqu'il y a des Pods qui ne peuvent pas être ordonnancés (schedules) parce qu'il n'y a pas assez de ressources (CPU, mémoire) sur les nœuds existants.
    • Lorsqu'un nœud est sur le point d'être rempli et qu'un nouveau Pod nécessiterait une capacité supplémentaire.
  • Scaling Down (Suppression de nœuds) :
    • Lorsqu'un nœud est sous-utilisé pendant une période prolongée (ex: moins de 50% de CPU/mémoire utilisé, ou avec peu de Pods).
    • Lorsqu'un Pod peut être déplacé vers un autre nœud pour libérer un nœud entier.

Avant de supprimer un nœud, le CA s'assure que tous les Pods qui s'y exécutent peuvent être déplacés en toute sécurité vers d'autres nœuds disponibles.

Quand utiliser le Cluster Autoscaler ?

Le CA est indispensable pour :

  • Optimiser les coûts d'infrastructure : Ne payer que pour les nœuds dont vous avez réellement besoin.
  • Assurer la disponibilité : Garantir que votre cluster peut toujours accueillir de nouveaux Pods, même lors de pics de charge importants qui dépasseraient la capacité des nœuds actuels.
  • Éviter les "Pod pending" : Empêcher les Pods de rester indéfiniment en attente de ressources.

Le Cluster Autoscaler travaille en tandem avec le HPA. Le HPA augmente le nombre de Pods pour répondre à la demande. Si cette augmentation nécessite plus de ressources que les nœuds actuels ne peuvent fournir, le Cluster Autoscaler interviendra pour ajouter de nouveaux nœuds au cluster.

Concepts Clés et Bonnes Pratiques pour l'Autoscaling

Pour un autoscaling efficace et robuste dans Kubernetes, plusieurs concepts et pratiques sont cruciaux.

Requêtes et Limites de Ressources (Requests & Limits)

C'est la fondation de tout autoscaling intelligent dans Kubernetes. Pour que le scheduler de Kubernetes sache où placer les Pods et que le HPA/VPA puisse prendre des décisions éclairées, vous devez définir des resources.requests et resources.limits pour vos conteneurs.

  • requests : La quantité minimale de ressources (CPU, mémoire) qu'un conteneur demande. Le scheduler utilise cette valeur pour placer les Pods sur les nœuds. C'est également la base de calcul pour l'utilisation ciblée du HPA (ex: 50% de 200m CPU).
  • limits : La quantité maximale de ressources qu'un conteneur est autorisé à utiliser. Si un conteneur dépasse sa limite de CPU, il est "throttled" (ralenti). S'il dépasse sa limite de mémoire, il est tué (OOMKilled).

Bonne pratique : Toujours définir des requests et des limits. Commencez par des valeurs raisonnables et ajustez-les en fonction de l'observation et des recommandations du VPA (si utilisé en mode recommandation).

Fenêtre de Stabilisation et Cooldown

L'autoscaling rapide peut entraîner un "flapping" (montées et descentes fréquentes et inutiles du nombre de réplicas ou de nœuds) si les métriques fluctuent rapidement. Pour éviter cela, le HPA et le Cluster Autoscaler intègrent des mécanismes de stabilisation :

  • behavior.scaleDown.stabilizationWindowSeconds (HPA) : Période pendant laquelle le HPA considère les observations passées pour décider de réduire le nombre de réplicas. Le HPA ne réduira pas le nombre de réplicas si l'une des observations récentes (dans cette fenêtre) suggère qu'un nombre plus élevé de réplicas est nécessaire.
  • scale-down-delay-after-add / scale-down-delay-after-delete (Cluster Autoscaler) : Le Cluster Autoscaler attendra une certaine période après l'ajout/suppression d'un nœud avant de considérer d'autres actions de scaling, pour laisser le temps au cluster de se stabiliser.

Ces paramètres sont essentiels pour la robustesse de votre système d'autoscaling.

Monitoring et Observabilité

L'autoscaling ne peut être efficace sans une visibilité complète sur la performance de vos applications et de votre infrastructure.

  • Surveillez vos métriques d'autoscaling : Regardez l'utilisation du CPU, de la mémoire, et les métriques personnalisées que vous utilisez pour le HPA.
  • Surveillez l'état de vos Pods et nœuds : Soyez alerté si des Pods sont en Pending ou si des nœuds sont NotReady.
  • Utilisez des outils comme Prometheus, Grafana, ou les services de monitoring de votre fournisseur cloud pour visualiser l'historique de l'autoscaling et ajuster vos seuils.

Combinaison des Stratégies d'Autoscaling

La véritable puissance de l'autoscaling dans Kubernetes réside dans la combinaison intelligente de ces stratégies :

  1. HPA pour gérer la charge immédiate et les fluctuations rapides au niveau des Pods. C'est votre première ligne de défense.
  2. VPA pour optimiser les requests et limits de chaque Pod sur le long terme, garantissant que le HPA a des bases de calcul précises et que les Pods utilisent leurs ressources de manière efficace.
  3. Cluster Autoscaler pour s'assurer que l'infrastructure sous-jacente peut toujours supporter le nombre de Pods requis par le HPA, en ajoutant ou supprimant des nœuds selon les besoins.

En mettant en œuvre ces trois types d'autoscaling, vous construisez un système hautement élastique, résilient et optimisé en termes de coûts.

Conclusion : Maîtriser la Flexibilité avec Kubernetes

La mise à l'échelle et l'autoscaling sont des piliers fondamentaux de la conception et du déploiement d'applications modernes. Kubernetes excelle dans ce domaine en offrant une suite d'outils puissants : le Horizontal Pod Autoscaler (HPA) pour les ajustements rapides du nombre de Pods, le Vertical Pod Autoscaler (VPA) pour l'optimisation des ressources par Pod, et le Cluster Autoscaler (CA) pour la gestion dynamique de l'infrastructure sous-jacente.

En comprenant et en maîtrisant ces concepts, vous êtes désormais armé pour créer des applications qui non seulement répondent à la demande de manière fluide et efficace, mais optimisent également les coûts d'infrastructure. N'oubliez pas l'importance des requests et limits, des fenêtres de stabilisation, et d'une surveillance continue pour affiner vos stratégies d'autoscaling. La flexibilité est la clé, et Kubernetes vous la donne.