Tests de charge distribués à l'aide de Google Kubernetes Engine

Last reviewed 2022-04-22 UTC

Ce tutoriel explique comment utiliser Google Kubernetes Engine (GKE) afin de déployer un framework de tests de charge distribués qui crée du trafic pour une API REST simple à l'aide de plusieurs conteneurs. Ce tutoriel teste la charge d'une application Web déployée sur App Engine qui expose les points de terminaison de type REST pour répondre aux requêtes HTTP POST entrantes.

Vous pouvez utiliser ce même modèle afin de créer des frameworks de tests de charge pour un éventail de scénarios et d'applications, tels que des systèmes de messagerie, des systèmes de gestion de flux de données et des systèmes de base de données.

Objectifs

  • Définir des variables d'environnement pour contrôler la configuration du déploiement
  • Créer un cluster GKE
  • Effectuer des tests de charge
  • (Facultatif) Augmenter le nombre d'utilisateurs ou étendre le modèle à d'autres cas d'utilisation

Coûts

Dans ce document, vous utilisez les composants facturables suivants de Google Cloud :

  • Service
  • Artifact Registry
  • Cloud Build
  • Cloud Storage
  • Google Kubernetes Engine

Obtenez une estimation des coûts en fonction de votre utilisation prévue à l'aide du simulateur de coût. Les nouveaux utilisateurs de Google Cloud peuvent bénéficier d'un essai gratuit.

Avant de commencer

  1. Connectez-vous à votre compte Google Cloud. Si vous débutez sur Google Cloud, créez un compte pour évaluer les performances de nos produits en conditions réelles. Les nouveaux clients bénéficient également de 300 $ de crédits gratuits pour exécuter, tester et déployer des charges de travail.
  2. Dans Google Cloud Console, sur la page de sélection du projet, sélectionnez ou créez un projet Google Cloud.

    Accéder au sélecteur de projet

  3. Vérifiez que la facturation est activée pour votre projet Google Cloud.

  4. Activer les API App Engine, Artifact Registry, Cloud Build, Compute Engine, Resource Manager, Google Kubernetes Engine, and Identity and Access Management.

    Activer les API

  5. Dans Google Cloud Console, sur la page de sélection du projet, sélectionnez ou créez un projet Google Cloud.

    Accéder au sélecteur de projet

  6. Vérifiez que la facturation est activée pour votre projet Google Cloud.

  7. Activer les API App Engine, Artifact Registry, Cloud Build, Compute Engine, Resource Manager, Google Kubernetes Engine, and Identity and Access Management.

    Activer les API

  8. Une fois que vous avez terminé les tâches décrites dans ce document, vous pouvez éviter de continuer à payer des frais en supprimant les ressources que vous avez créées. Pour en savoir plus, consultez la section Effectuer un nettoyage.

  9. Attribuez des rôles à votre compte Google. Exécutez la commande suivante une fois pour chacun des rôles IAM suivants : roles/serviceusage.serviceUsageAdmin, roles/container.admin, roles/appengine.appAdmin, roles/appengine.appCreator, roles/artifactregistry.admin, roles/resourcemanager.projectIamAdmin, roles/compute.instanceAdmin.v1, roles/iam.serviceAccountUser, roles/cloudbuild.builds.builder, roles/iam.serviceAccountAdmin

    gcloud projects add-iam-policy-binding PROJECT_ID --member="user:EMAIL_ADDRESS" --role=ROLE
    • en remplaçant PROJECT_ID par l'ID de votre projet :
    • Remplacez EMAIL_ADDRESS par votre adresse e-mail.
    • Remplacez ROLE par chaque rôle individuel.

Exemple de charge de travail

Le schéma suivant montre un exemple de charge de travail où les requêtes passent d'un client à une application.

Requêtes passant d'un client à une application.

Pour modéliser cette interaction, vous pouvez utiliser Locust, un outil de tests de charge distribués basé sur Python, capable de distribuer des requêtes sur plusieurs chemins d'accès cibles. Par exemple, Locust peut distribuer des requêtes sur les chemins d'accès cibles /login et /metrics. La charge de travail est modélisée en tant qu'ensemble de tâches dans Locust.

Architecture

Cette architecture implique deux composants principaux :

  • L'image de conteneur Docker Locust
  • Le mécanisme de gestion et d'orchestration de conteneurs

L'image de conteneur Docker Locust contient le logiciel Locust. Le Dockerfile, que vous obtenez lorsque vous clonez le dépôt GitHub, fourni avec ce tutoriel, utilise une image Python de base et inclut des scripts pour démarrer le service Locust et exécuter les tâches. Pour se rapprocher des clients du monde réel, chaque tâche Locust est pondérée. Par exemple, l'enregistrement se produit tous les milliers de requêtes client.

GKE fournit une gestion et une orchestration des conteneurs. Avec GKE, vous pouvez spécifier le nombre de nœuds de conteneur qui constituent la base de votre framework de tests de charge. Vous pouvez également organiser vos nœuds de calcul de tests de charge en pods, et spécifier le nombre de pods que GKE doit continuer à exécuter.

Pour déployer les tâches de tests de charge, procédez comme suit :

  1. Déployez un nœud maître de tests de charge.
  2. Déployez un groupe de nœuds de calcul de tests de charge. Grâce à ces derniers, vous pouvez créer une quantité de trafic importante à des fins de test.

Le schéma suivant décrit l'architecture illustrant les tests de charge à l'aide d'un exemple d'application. Le pod maître diffuse l'interface Web utilisée pour opérer et surveiller les tests de charge. Les pods de nœuds de calcul génèrent le trafic de requête REST pour l'application en cours de test et envoient des métriques au maître.

Le pod maître diffuse l'interface Web utilisée pour opérer et surveiller les tests de charge. Les pods de nœuds de calcul génèrent le trafic de requête REST pour l'application en cours de test.

À propos du nœud maître de tests de charge

Le nœud maître Locust constitue le point d'entrée pour l'exécution des tâches de tests de charge. Sa configuration spécifie plusieurs éléments, y compris les ports par défaut utilisés par le conteneur :

  • 8089 pour l'interface Web
  • 5557 et 5558 pour la communication avec les nœuds de calcul

Ces informations servent ensuite à la configuration des nœuds de calcul Locust.

Vous déployez un Service pour vous assurer que les autres Pods du cluster peuvent accéder aux ports nécessaires via hostname:port. Ces ports peuvent également être référencés via un nom de port descriptif.

Ce service permet aux nœuds de calcul Locust de découvrir facilement le nœud maître et de communiquer de manière fiable avec lui, même si celui-ci tombe en panne et que le déploiement le remplace par un nouveau pod.

Un second service, déployé avec l'annotation nécessaire, permet de créer un équilibreur de charge réseau interne à stratégie directe qui rend le service d'application Web Locust accessible aux clients extérieurs à votre cluster qui utilisent le même réseau VPC et sont situés dans la même région Google Cloud que votre cluster.

Après avoir déployé le nœud maître Locust, vous pouvez ouvrir l'interface Web à l'aide de l'adresse IP privée provisionnée par l'équilibreur de charge réseau interne à stratégie directe. Après avoir déployé les nœuds de calcul Locust, vous pouvez démarrer la simulation et consulter des statistiques globales via l'interface Web Locust.

À propos des nœuds de calcul de tests de charge

Les nœuds de calcul Locust exécutent les tâches de tests de charge. Vous utilisez un seul déploiement pour créer plusieurs pods. Les pods sont répartis dans le cluster Kubernetes. Chaque pod utilise des variables d'environnement afin de contrôler des informations de configuration, telles que le nom d'hôte du système soumis aux tests et le nom d'hôte du nœud maître Locust.

Le schéma suivant illustre la relation entre le nœud maître Locust et les nœuds de calcul Locust.

Le nœud maître Locust est en haut de la hiérarchie, et plusieurs nœuds de calcul se trouvent en dessous.

Initialiser des variables communes

Vous devez définir plusieurs variables qui contrôlent l'emplacement où sont déployés les éléments de l'infrastructure.

  1. Ouvrez Cloud Shell.

    Ouvrir Cloud Shell

    Dans ce tutoriel, vous allez exécuter toutes les commandes de terminal à partir de Cloud Shell.

  2. Définissez les variables d'environnement qui nécessitent une personnalisation :

    export GKE_CLUSTER=GKE_CLUSTER
    export AR_REPO=AR_REPO
    export REGION=REGION
    export ZONE=ZONE
    export SAMPLE_APP_LOCATION=SAMPLE_APP_LOCATION
    

    Remplacez les éléments suivants :

    • GKE_CLUSTER : nom de votre cluster GKE.
    • AR_REPO : nom de votre dépôt Artifact Registry
    • REGION : région dans laquelle votre cluster GKE et votre dépôt Artifact Registry seront créés
    • ZONE : zone de la région dans laquelle votre instance Compute Engine sera créée
    • SAMPLE_APP_LOCATION : emplacement(régional) où votre exemple d'application App Engine sera déployé

    Ces commandes doivent ressembler à l'exemple suivant :

    export GKE_CLUSTER=gke-lt-cluster
    export AR_REPO=dist-lt-repo
    export REGION=us-central1
    export ZONE=us-central1-b
    export SAMPLE_APP_LOCATION=us-central
    
  3. Définissez les variables d'environnement supplémentaires suivantes :

    export GKE_NODE_TYPE=e2-standard-4
    export GKE_SCOPE="https://www.googleapis.com/auth/cloud-platform"
    export PROJECT=$(gcloud config get-value project)
    export SAMPLE_APP_TARGET=${PROJECT}.appspot.com
    
  4. Définissez la zone par défaut afin de ne pas avoir à spécifier ces valeurs dans les commandes suivantes :

    gcloud config set compute/zone ${ZONE}
    

Créer un cluster GKE

  1. Créez un compte de service avec les autorisations minimales requises par le cluster :

    gcloud iam service-accounts create dist-lt-svc-acc
    gcloud projects add-iam-policy-binding  ${PROJECT} --member=serviceAccount:dist-lt-svc-acc@${PROJECT}.iam.gserviceaccount.com --role=roles/artifactregistry.reader
    gcloud projects add-iam-policy-binding  ${PROJECT} --member=serviceAccount:dist-lt-svc-acc@${PROJECT}.iam.gserviceaccount.com --role=roles/container.nodeServiceAccount
    
  2. Créez le cluster GKE :

    gcloud container clusters create ${GKE_CLUSTER} \
    --service-account=dist-lt-svc-acc@${PROJECT}.iam.gserviceaccount.com \
    --region ${REGION} \
    --machine-type ${GKE_NODE_TYPE} \
    --enable-autoscaling \
    --num-nodes 3 \
    --min-nodes 3 \
    --max-nodes 10 \
    --scopes "${GKE_SCOPE}"
    
  3. Connectez-vous au cluster GKE :

    gcloud container clusters get-credentials ${GKE_CLUSTER} \
       --region ${REGION} \
       --project ${PROJECT}
    

Configurer l'environnement

  1. Clonez l'exemple de dépôt depuis GitHub :

    git clone https://github.com/GoogleCloudPlatform/distributed-load-testing-using-kubernetes
    
  2. Changez votre répertoire de travail dans le dépôt cloné :

    cd distributed-load-testing-using-kubernetes
    

Créer l'image de conteneur

  1. Créer un dépôt Artifact Registry :

    gcloud artifacts repositories create ${AR_REPO} \
        --repository-format=docker  \
        --location=${REGION} \
        --description="Distributed load testing with GKE and Locust"
    
  2. Créez l'image de conteneur et stockez-la dans votre dépôt Artifact Registry :

    export LOCUST_IMAGE_NAME=locust-tasks
    export LOCUST_IMAGE_TAG=latest
    gcloud builds submit \
        --tag ${REGION}-docker.pkg.dev/${PROJECT}/${AR_REPO}/${LOCUST_IMAGE_NAME}:${LOCUST_IMAGE_TAG} \
        docker-image
    

    L'image Docker Locust associée intègre une tâche de test qui appelle les points de terminaison /login et /metrics dans l'exemple d'application. Dans cet exemple d'ensemble de tâches de test, le ratio respectif des requêtes envoyées à ces deux points de terminaison sera de 1 à 999.

    
    class MetricsTaskSet(TaskSet):
        _deviceid = None
    
        def on_start(self):
            self._deviceid = str(uuid.uuid4())
    
        @task(1)
        def login(self):
            self.client.post(
                '/login', {"deviceid": self._deviceid})
    
        @task(999)
        def post_metrics(self):
            self.client.post(
                "/metrics", {"deviceid": self._deviceid, "timestamp": datetime.now()})
    
    class MetricsLocust(FastHttpUser):
        tasks = {MetricsTaskSet}
    

  3. Vérifiez que l'image Docker se trouve dans votre dépôt Artifact Registry :

    gcloud artifacts docker images list ${REGION}-docker.pkg.dev/${PROJECT}/${AR_REPO} | \
        grep ${LOCUST_IMAGE_NAME}
    

    Le résultat ressemble à ce qui suit :

    Listing items under project PROJECT, location REGION, repository AR_REPO
    
    REGION-docker.pkg.dev/PROJECT/AR_REPO/locust-tasks  sha256:796d4be067eae7c82d41824791289045789182958913e57c0ef40e8d5ddcf283  2022-04-13T01:55:02  2022-04-13T01:55:02
    

Déployer l'exemple d'application

  1. Créez et déployez l'exemple d'application Web en tant que App Engine :

    gcloud app create --region=${SAMPLE_APP_LOCATION}
    gcloud app deploy sample-webapp/app.yaml \
    --project=${PROJECT}
    
  2. Lorsque vous y êtes invité, saisissez y pour procéder au déploiement.

    Le résultat ressemble à ce qui suit :

    File upload done.
    Updating service [default]...done.
    Setting traffic split for service [default]...done.
    Deployed service [default] to [https://PROJECT.appspot.com]
    

    L'exemple d'application App Engine met en œuvre les points de terminaison /login et /metrics :

    @app.route('/login',  methods=['GET', 'POST'])
    def login():
        deviceid = request.values.get('deviceid')
        return '/login - device: {}\n'.format(deviceid)
    
    @app.route('/metrics',  methods=['GET', 'POST'])
    def metrics():
        deviceid = request.values.get('deviceid')
        timestamp = request.values.get('timestamp')
    
        return '/metrics - device: {}, timestamp: {}\n'.format(deviceid, timestamp)

Déployer les pods maîtres et les nœuds de calcul Locust :

  1. Remplacez les valeurs des variables d'environnement par les paramètres d'hôte, de projet et d'image cibles dans les fichiers locust-master-controller.yaml et locust-worker-controller.yaml, puis créez les déploiements de nœud maître Locust et de nœud de calcul Locust :

    envsubst < kubernetes-config/locust-master-controller.yaml.tpl | kubectl apply -f -
    envsubst < kubernetes-config/locust-worker-controller.yaml.tpl | kubectl apply -f -
    envsubst < kubernetes-config/locust-master-service.yaml.tpl | kubectl apply -f -
    
  2. Vérifiez les déploiements Locust :

    kubectl get pods -o wide
    

    Le résultat ressemble à ceci :

    NAME                             READY   STATUS    RESTARTS   AGE   IP           NODE
    locust-master-87f8ffd56-pxmsk    1/1     Running   0          1m    10.32.2.6    gke-gke-load-test-default-pool-96a3f394
    locust-worker-58879b475c-279q9   1/1     Running   0          1m    10.32.1.5    gke-gke-load-test-default-pool-96a3f394
    locust-worker-58879b475c-9frbw   1/1     Running   0          1m    10.32.2.8    gke-gke-load-test-default-pool-96a3f394
    locust-worker-58879b475c-dppmz   1/1     Running   0          1m    10.32.2.7    gke-gke-load-test-default-pool-96a3f394
    locust-worker-58879b475c-g8tzf   1/1     Running   0          1m    10.32.0.11   gke-gke-load-test-default-pool-96a3f394
    locust-worker-58879b475c-qcscq   1/1     Running   0          1m    10.32.1.4    gke-gke-load-test-default-pool-96a3f394
    
  3. Vérifiez les services :

    kubectl get services
    

    Le résultat ressemble à ceci :

    NAME                TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)             AGE
    kubernetes          ClusterIP      10.87.240.1     <none>        443/TCP             12m
    locust-master       ClusterIP      10.87.245.22    <none>        5557/TCP,5558/TCP    1m
    locust-master-web   LoadBalancer   10.87.246.225   <pending>     8089:31454/TCP       1m
    
  4. Exécutez une boucle de contrôle pendant que l'adresse IP privée de l'équilibreur de charge réseau interne à stratégie directe (adresse IP externe GKE) est provisionnée pour le service d'application Web du nœud maître Locust :

    kubectl get svc locust-master-web --watch
    
  5. Appuyez sur Ctrl+C pour quitter la boucle de contrôle une fois qu'une adresse EXTERNAL-IP est provisionnée.

Se connecter à l'interface Web Locust

Vous pouvez utiliser l'interface Web du nœud maître Locust pour exécuter les tâches de tests de charge sur le système soumis aux tests.

  1. Obtenez l'adresse IP de l'équilibreur de charge interne du service hôte Web :

    export INTERNAL_LB_IP=$(kubectl get svc locust-master-web  \
                                   -o jsonpath="{.status.loadBalancer.ingress[0].ip}") && \
                                   echo $INTERNAL_LB_IP
    
  2. Selon la configuration de votre réseau, vous pouvez vous connecter à l'application Web Locust de deux manières via l'adresse IP provisionnée :

    • Le routage réseau. Si votre réseau est configuré de manière à autoriser le routage depuis votre poste de travail vers le réseau VPC de votre projet, vous pouvez accéder directement à l'adresse IP de l'équilibreur de charge réseau interne à stratégie directe à partir de votre poste de travail.

    • Proxy et tunnel SSH. S'il n'existe aucune route réseau entre votre poste de travail et votre réseau VPC, vous pouvez acheminer le trafic vers l'adresse IP de l'équilibreur de charge réseau interne à stratégie directe en créant une instance Compute Engine avec un proxy nginx et un tunnel SSH entre votre poste de travail et l'instance.

le routage réseau.

S'il existe une route pour le trafic réseau entre votre poste de travail et le réseau VPC de votre projet Google Cloud, ouvrez votre navigateur, puis ouvrez l'interface Web du nœud maître Locust. Remplacez [INTERNAL_LB_IP] dans l'URL suivante par l'adresse IP indiquée à l'étape précédente : http://[INTERNAL_LB_IP]:8089.

Proxy et tunnel SSH

  1. Définissez une variable d'environnement avec le nom de l'instance.

    export PROXY_VM=locust-nginx-proxy
    
  2. Démarrez une instance avec un conteneur Docker ngnix configuré pour relayer le port de l'application Web Locust 8089 sur l'équilibreur de charge réseau interne à stratégie directe :

    gcloud compute instances create-with-container ${PROXY_VM} \
       --zone ${ZONE} \
       --container-image gcr.io/cloud-marketplace/google/nginx1:latest \
       --container-mount-host-path=host-path=/tmp/server.conf,mount-path=/etc/nginx/conf.d/default.conf \
       --metadata=startup-script="#! /bin/bash
         cat <<EOF  > /tmp/server.conf
         server {
             listen 8089;
             location / {
                 proxy_pass http://${INTERNAL_LB_IP}:8089;
             }
         }
    EOF"
    
  3. Ouvrez un tunnel SSH depuis Cloud Shell vers l'instance de proxy :

    gcloud compute ssh --zone ${ZONE} ${PROXY_VM} \
                     -- -N -L 8089:localhost:8089
    
  4. Cliquez sur l'icône Aperçu sur le Web (Icône "Aperçu sur le Web" de Cloud Shell), puis sélectionnez Modifier le port dans la liste des options.

  5. Dans la boîte de dialogue Modifier le port d'aperçu, saisissez 8089 dans le champ Numéro de port, puis sélectionnezModifier et prévisualiser.

    Un onglet de navigateur va s'ouvrir avec l'interface Web Locust.

Exécuter un test de charge de base sur votre exemple d'application

  1. Une fois que vous avez ouvert l'interface Locust dans votre navigateur, une boîte de dialogue permettant de démarrer un nouveau test de charge s'affiche.

    L'interface Web du nœud maître Locust fournit une boîte de dialogue permettant de démarrer un nouvel essaim et de spécifier le nombre d'utilisateurs et le taux d'apparition.

  2. Spécifiez le Nombre d'utilisateurs (pic d'activité de la simultanéité) sur 10 et le taux de génération (utilisateurs ayant commencé/seconde) sur 5 par seconde.

  3. Cliquez ensuite sur Start swarming (Démarrer le travail en essaim) pour commencer la simulation.

    Une fois que le travail en essaim des requêtes a commencé, les métriques de simulation (nombre de requêtes, nombre de requêtes par seconde, etc.) s'affinent, car les statistiques commencent à s'agréger, comme illustré dans l'image suivante :

    L'interface Web Locust montre que les statistiques commencent à s'agréger.
  4. Affichez le service déployé et d'autres métriques depuis Google Cloud Console.

    Le tableau de bord d'App Engine affiche un graphique représentant une heure de requêtes par type.
  5. Lorsque vous avez observé le comportement de l'application testée, cliquez sur Arrêter pour mettre fin au test.

Augmenter le nombre d'utilisateurs (facultatif)

Si vous souhaitez tester une charge accrue sur l'application, vous pouvez ajouter des utilisateurs simulés. Avant cela, vous devez vous assurer qu'il y a suffisamment de ressources pour permettre l'augmentation de la charge. Avec Google Cloud, vous pouvez ajouter des pods de nœuds de calcul Locust au déploiement sans redéployer les pods existants, à condition que les ressources de VM sous-jacentes acceptent un nombre accru de pods. Le cluster GKE initial commence avec trois nœuds et peut procéder à un autoscaling jusqu'à 10 nœuds.

  • Faites passer le pool de pods de nœuds de calcul Locust à 20.

    kubectl scale deployment/locust-worker --replicas=20
    

    Le déploiement et le démarrage des nouveaux pods prennent quelques minutes.

Si vous voyez s'afficher une erreur PodUnschedulable, vous devez ajouter plus de nœuds au cluster. Pour en savoir plus, consultez la page Redimensionner un cluster GKE.

Une fois les pods démarrés, revenez à l'interface Web du nœud maître Locust et relancez les tests de charge.

Étendre le modèle

Pour étendre ce modèle, vous pouvez créer des tâches Locust ou même basculer vers un framework de tests de charge différent.

Vous pouvez personnaliser les métriques que vous collectez. Par exemple, vous pouvez mesurer le nombre de requêtes par seconde ou surveiller le temps de latence des réponses lorsque la charge augmente, ou encore vérifier les taux d'échec des réponses et les types d'erreurs.

Pour en savoir plus, consultez la documentation de Cloud Monitoring.

Effectuer un nettoyage

Une fois que vous avez terminé le tutoriel, vous pouvez effacer les ressources que vous avez créées afin qu'elles ne vous soient plus facturées.

Supprimer le projet

Le moyen le plus simple d'empêcher la facturation est de supprimer le projet que vous avez créé pour ce tutoriel.

Pour supprimer le projet :

  1. Dans la console Google Cloud, accédez à la page Gérer les ressources.

    Accéder à la page Gérer les ressources

  2. Dans la liste des projets, sélectionnez le projet que vous souhaitez supprimer, puis cliquez sur Supprimer.
  3. Dans la boîte de dialogue, saisissez l'ID du projet, puis cliquez sur Arrêter pour supprimer le projet.

Supprimer le cluster GKE

Si vous ne souhaitez pas supprimer l'ensemble du projet, exécutez la commande suivante pour supprimer le cluster GKE :

   gcloud container clusters delete ${GKE_CLUSTER} --region ${REGION}
   

Étapes suivantes