scaling

Publié le 9 janvier 2025.

Une bonne application est une application qui tient sa charge d’utilisateurs, notamment grâce à un scaling controlé. Dans cet article nous aborderons ce sujet, et plus particulièrement que faire quand les métriques classiques (ressources CPU et mémoire) ne permettent pas d’avoir un scaling efficace.

 

Le scaling est une part primordiale de la gestion d’infrastructure. En effet, toute application reçoit un trafic d'intensité variée pendant la journée, il est donc utile d’avoir du scaling en place pour supporter les pics de charge et limiter les coûts pendant les périodes plus calmes.

La version habituelle : CPU & RAM

Les Horizontal Pod Autoscalers

Habituellement, ce scaling se fait via des métriques système, comme l’utilisation CPU ou mémoire. C’est en effet les métriques par défaut des horizontal pods autoscalers de Kubernetes, la ressource de base de l’autoscaling pour cette technologie :

 
spec:
    maxReplicas: 3 # Nombre maximal de réplicas
    metrics:
    - resource:
        name: cpu # Métrique utilisée pour le scaling
        target:
          averageUtilization: 50 # Utilisation moyenne visée
          type: Utilization
      type: Resource
    minReplicas: 1 # Nombre minimal de réplicas
    scaleTargetRef:
      apiVersion: apps/v1
      kind: Deployment
      name: ingress-nginx-controller # Cible du scaling

Exemple de HPA et explications utilisant les métriques de CPU et de mémoire pour faire son scaling

Voici donc un exemple de Horizontal Pod Autoscaler utilisant les métriques de mémoire et de CPU pour faire un son autoscaling. On voit donc une variation du nombre de replicas entre 5 et 20, avec pour objectif d’avoir une utilisation CPU proche des 50%. Il est aussi possible de faire ce scaling via la mémoire, mais c’est une solution plus dangereuse car certaines applications ne consomment pas plus de mémoire en fonction de leur utilisation.

Les autoscaling groups

Il est aussi possible de faire de l’autoscaling en dehors de Kubernetes, comme par exemple pour des tasks ECS dans AWS, en utilisant les autoscalings groups.

image (2)

 

image (3)

(716 < CPU < +Infinity correspond à plus de 70% (716/1024 = 0,7)

Voici un example d’autoscaling d’une task ECS. Cette task va avoir 5 nouvelles replicas quand son utilisation CPU moyenne dépasse les 70% et va perdre 3 replicas quand son utilisation CPU moyenne descend en dessous des 60%.

Une technologie similaire existe chez GCP : les Managed Instances et autoscaling groups. Il est donc possible de faire cet autoscaling directement via les outils des cloud providers, même sur les machines virtuelles directement, comme avec les autoscalings groups d’AWS

Cependant, cette méthode ne permet pas de résoudre tous les problèmes de scaling.

Une alternative centrée sur l'expérience utilisateur

Cependant, il arrive que ces métriques ne suffisent pas. Prenons par exemple une application qui fonctionne de la manière suivante :

  • on a un nombre fixe de workers (prenons 8 par exemple) dans notre application qui traitent les requêtes reçues
  • Supposons qu’il y ai 2 types de requêtes possibles sur cette application :
    • des requêtes courtes, auquel l’application répond instantanément et qui représentent la majorité du traffic de cette application (environ 90% de requêtes rapides et 10% de requêtes lentes)
    • des requêtes longues nécessitant des updates en base de données représentant une part infime du traffic

Que se passerait-il si 8 requêtes longues arrivent en même temps sur cette application ?

Les 8 workers de l’application seraient occupés à traiter les requêtes en base de données, et l’application refuserait les requêtes courtes car aucun workers n'est disponible. Cependant, il n’y aurait aucune charge sur le CPU ou sur la mémoire, car les workers seraient uniquement en attente de réponse de la base de données. L’application ne scalerait donc pas si il y l'autoscaling en place se basait seulement sur les métriques CPU ou mémoire.

Dans notre cas, il est donc utile de mettre en place un autoscaling utilisant d’autre métriques que les ressources des machines. On peut ainsi à avoir un autoscaling en place utilisant des métriques orientée vers l’expérience utilisateur et non les statistiques de la machine, comme le nombre de requêtes ou le temps de réponse de l’application, avec des outils externes qui mesurent ces données.

Dans notre cas, une solution envisagée serait de mettre en place un scaling sur le nombre de requêtes et le temps de réponse de l’application, données qui seraient récupérées au niveau du load balancer de l’application. En effet, dans notre cas, le temps de réponse de l’application augmenterait fortement lorsque les workers ne sont pas disponibles, l’application scalerait pour ajouter de nouveaux worker et absorber la charge. De plus, l’application scalerait en fonction du nombre de requêtes, ce qui permet aussi de traiter la variation de traffic pendant la journée.

image (5)

Nombre de requêtes par seconde

image (4)

Nombre de conteneurs voulus

On vois ainsi la corrélation entre le nombre de requête et les nombre de conteneurs du service, montrant que l’autoscaling suit le nombre de requête que l’application reçois

Comment mettre en place ce scaling ?

Il existe plusieurs méthodes pour mettre en place ce type de scaling, voici donc une méthode utilisant les métriques cloudwatch et les autoscaling groups aws. Pour faire son scaling, le composant responsable de l’autoscaling dans AWS va récupérer les métriques du load balancer servant d'entrée dans les services, et plus particulièrement les métriques suivantes :

  • temps de réponse moyen
  • nombre de requêtes par seconde

L’objectif va donc être d’augmenter le nombre de replicas quand le temps de réponse dépasse un certain seuil, et quand le nombre de requêtes dépasse un certain seuil, pour éviter d’augmenter le nombre de réplicas en l’absence de traffic. Il sera aussi possible de réduire le nombre de replicas quand le temps de réponse sera revenu à des valeurs plus faibles.

Conclusion

En conclusion cet article vous a présenté une solution de scaling, utilisant des métriques métiers tels que le temps de réponse et le nombre de requêtes, cette solution étant une alternative au scaling utilisant les métriques CPU et mémoire. Il existe cependant d’autres méthodes pour faire ce type de scaling, notamment en utilisant Keda sur Kubernetes