Test di carico distribuito con Google Kubernetes Engine

Last reviewed 2024-08-13 UTC

Questo documento spiega come utilizzare Google Kubernetes Engine (GKE) per eseguire il deployment di un framework di test di carico distribuito che utilizza più container per creare traffico per una semplice API basata su REST. Questo documento esegue test di carico su un'applicazione web di cui è stato eseguito il deployment in App Engine che espone endpoint in stile REST per rispondere alle richieste POST HTTP in entrata.

Puoi utilizzare lo stesso pattern per creare framework di test di carico per una serie di scenari e applicazioni, come sistemi di messaggistica, sistemi di gestione degli stream di dati e sistemi di database.

Obiettivi

  • Definisci le variabili di ambiente per controllare la configurazione del deployment.
  • Creare un cluster GKE.
  • Esegui test di carico.
  • Se vuoi, aumenta il numero di utenti o estendi il pattern ad altri casi d'uso.

Costi

In questo documento utilizzi i seguenti componenti fatturabili di Google Cloud:

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

Per generare una stima dei costi basata sull'utilizzo previsto, utilizza il Calcolatore prezzi. I nuovi utenti di Google Cloud potrebbero essere idonei per una prova gratuita.

Prima di iniziare

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Enable the App Engine, Artifact Registry, Cloud Build, Compute Engine, Resource Manager, Google Kubernetes Engine, and Identity and Access Management APIs.

    Enable the APIs

  5. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  6. Make sure that billing is enabled for your Google Cloud project.

  7. Enable the App Engine, Artifact Registry, Cloud Build, Compute Engine, Resource Manager, Google Kubernetes Engine, and Identity and Access Management APIs.

    Enable the APIs

  8. Al termine delle attività descritte in questo documento, puoi evitare la fatturazione continua eliminando le risorse che hai creato. Per ulteriori informazioni, consulta la sezione Pulizia.

  9. Grant roles to your user account. Run the following command once for each of the following IAM roles: 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:USER_IDENTIFIER" --role=ROLE
    • Replace PROJECT_ID with your project ID.
    • Replace USER_IDENTIFIER with the identifier for your user account. For example, user:myemail@example.com.

    • Replace ROLE with each individual role.

Carico di lavoro di esempio

Il seguente diagramma mostra un esempio di carico di lavoro in cui le richieste passano dal client all'applicazione.

Richieste che vanno dal client all'applicazione.

Per modellare questa interazione, puoi utilizzare Locust, un strumento di test di carico distribuito basato su Python che può distribuire le richieste su più percorsi target. Ad esempio, Locust può distribuire le richieste ai percorsi target /login e /metrics. Il carico di lavoro viene modellato come insieme di attività in Locust.

Architettura

Questa architettura prevede due componenti principali:

  • L'immagine container Docker di Locust.
  • Il meccanismo di orchestrazione e gestione dei container.

L'immagine container Docker di Locust contiene il software Locust. Il file Dockerfile, che ottieni quando cloni il repository GitHub che accompagna questo documento, utilizza un'immagine di base Python e include script per avviare il servizio Locust ed eseguire le attività. Per approssimare i client reali, ogni attività Locust viene ponderata. Ad esempio, la registrazione avviene una volta ogni mille richieste totali dei clienti.

GKE fornisce l'orchestrazione e la gestione dei container. Con GKE, puoi specificare il numero di nodi contenitore che costituiscono la base del tuo framework di test di carico. Puoi anche organizzare i tuoi worker di test di carico in pod e specificare quanti pod vuoi che GKE continui a eseguire.

Per eseguire il deployment delle attività di test di carico:

  1. Esegui il deployment di un test di carico principale, denominato master da Locust.
  2. Esegui il deployment di un gruppo di worker per i test di carico. Con questi worker per i test di carico, puoi creare una quantità significativa di traffico a scopo di test.

Il seguente diagramma mostra l'architettura che dimostra i test di carico utilizzando un'applicazione di esempio. Il pod principale fornisce l'interfaccia web utilizzata per eseguire e monitorare i test di carico. I pod worker generano il traffico delle richieste REST per l'applicazione in fase di test e inviano le metriche al master.

Il pod principale serve l'interfaccia web utilizzata per eseguire e monitorare i test di carico. I pod worker generano il traffico delle richieste REST per l'applicazione in fase di test.

Informazioni sul test di carico principale

Il master Locust è il punto di contatto per l'esecuzione delle attività di test di carico. La configurazione principale di Locust specifica diversi elementi, tra cui le porte predefinite utilizzate dal contenitore:

  • 8089 per l'interfaccia web
  • 5557 e 5558 per comunicare con i lavoratori

Queste informazioni vengono utilizzate in seguito per configurare i worker Locust.

Esegui il deployment di un servizio per assicurarti che le porte necessarie siano accessibili agli altri pod all'interno del cluster tramite hostname:port. Queste porte possono essere anche richiamate tramite un nome descrittivo.

Questo servizio consente ai worker Locust di rilevare e comunicare facilmente e in modo affidabile con il master, anche se il master non funziona e viene sostituito da un nuovo pod dal deployment.

Viene implementato un secondo servizio con l'annotazione necessaria per creare un bilanciatore del carico di rete passthrough interno che rende accessibile il servizio dell'applicazione web Locust ai client esterni al cluster che utilizzano la stessa rete VPC e si trovano nella stessa regione Google Cloud del cluster.

Dopo aver eseguito il deployment del master Locust, puoi aprire l'interfaccia web utilizzando l'indirizzo IP interno di cui è stato eseguito il provisioning dal bilanciatore del carico di rete passthrough interno. Dopo aver eseguito il deployment dei worker Locust, puoi avviare la simulazione e esaminare le statistiche aggregate tramite l'interfaccia web di Locust.

Informazioni sui worker per i test di carico

I worker Locust eseguono le attività di test di carico. Utilizzi un singolo deployment per creare più pod. I pod sono distribuiti nel cluster Kubernetes. Ogni pod utilizza le variabili di ambiente per controllare le informazioni di configurazione, ad esempio il nome host del sistema in test e il nome host del master Locust.

Il seguente diagramma mostra la relazione tra il master Locust e i worker Locust.

Il master Locust si trova nella parte superiore di una gerarchia con più worker sottostanti.

Inizializzare le variabili comuni

Devi definire diverse variabili che controllano dove vengono implementati gli elementi dell'infrastruttura.

  1. Apri Cloud Shell:

    Apri Cloud Shell

    Esegui tutti i comandi di terminale in questo documento da Cloud Shell.

  2. Imposta le variabili di ambiente che richiedono la personalizzazione:

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

    Sostituisci quanto segue:

    • GKE_CLUSTER: il nome del tuo cluster GKE.
    • AR_REPO: il nome del repository Artifact Registry
    • REGION: la regione in cui verranno creati il cluster GKE e il repository Artifact Registry
    • ZONE: la zona della tua regione in cui verrà creata l'istanza Compute Engine
    • SAMPLE_APP_LOCATION: la località(regionale) in cui verrà eseguita il deployment dell'applicazione App Engine di esempio

    I comandi dovrebbero essere simili all'esempio seguente:

    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. Imposta le seguenti variabili di ambiente aggiuntive:

    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. Imposta la zona predefinita in modo da non dover specificare questi valori nei comandi successivi:

    gcloud config set compute/zone ${ZONE}
    

Crea un cluster GKE

  1. Crea un account di servizio con le autorizzazioni minime richieste dal 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. Crea il 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. Connettiti al cluster GKE:

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

Configura l'ambiente

  1. Clona il repository di esempio da GitHub:

    git clone https://github.com/GoogleCloudPlatform/distributed-load-testing-using-kubernetes
    
  2. Cambia la directory di lavoro impostandola sul repository clonato:

    cd distributed-load-testing-using-kubernetes
    

Crea l'immagine container

  1. Crea un repository Artifact Registry:

    gcloud artifacts repositories create ${AR_REPO} \
        --repository-format=docker  \
        --location=${REGION} \
        --description="Distributed load testing with GKE and Locust"
  2. Crea l'immagine container e archiviala nel tuo repository 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'immagine Docker di Locust inclusa incorpora un'attività di test che chiama gli endpoint /login e /metrics nell'applicazione di esempio. In questo insieme di attività di test di esempio, il rispettivo rapporto tra le richieste inviate a questi due endpoint sarà 1 su 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. Verifica che l'immagine Docker sia nel repository Artifact Registry:

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

    L'output è simile al seguente:

    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
    

Esegui il deployment dell'applicazione di esempio

  1. Crea ed esegui il deployment di sample-webapp come App Engine:

    gcloud app create --region=${SAMPLE_APP_LOCATION}
    gcloud app deploy sample-webapp/app.yaml \
    --project=${PROJECT}
    
  2. Quando richiesto, digita y per procedere con il deployment.

    L'output è simile al seguente:

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

    L'applicazione App Engine di esempio implementa gli endpoint /login e /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)

Esegui il deployment dei pod Locust master e worker

  1. Sostituisci i valori variabile di ambiente per i parametri di immagine, progetto e host di destinazione nei file locust-master-controller.yaml e locust-worker-controller.yaml e crea i deployment di Locust master e worker:

    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. Verifica i deployment di Locust:

    kubectl get pods -o wide
    

    L'output è simile al seguente:

    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. Verifica i servizi:

    kubectl get services
    

    L'output è simile al seguente:

    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. Esegui un loop di monitoraggio mentre viene eseguito il provisioning dell'indirizzo IP interno del bilanciatore del carico di rete passthrough interno (indirizzo IP esterno di GKE) per il servizio dell'applicazione web master Locust:

    kubectl get svc locust-master-web --watch
    
  5. Premi Ctrl+C per uscire dal loop di visualizzazione dopo aver eseguito il provisioning di un indirizzo EXTERNAL-IP.

Connettiti al frontend web di Locust

Utilizza l'interfaccia web principale di Locust per eseguire le attività di test di carico sul sistema in test.

  1. Prendi nota dell'indirizzo IP del bilanciatore del carico interno del servizio host web:

    export INTERNAL_LB_IP=$(kubectl get svc locust-master-web  \
                                   -o jsonpath="{.status.loadBalancer.ingress[0].ip}") && \
                                   echo $INTERNAL_LB_IP
    
  2. A seconda della configurazione di rete, puoi collegarti all'applicazione web Locust tramite l'indirizzo IP di cui è stato eseguito il provisioning in due modi:

    • Routing di rete. Se la tua rete è configurata per consentire il routing dalla tua workstation alla rete VPC del progetto, puoi accedere direttamente all'indirizzo IP del bilanciatore di carico di rete passthrough interno dalla tua workstation.

    • Proxy e tunnel SSH. Se non esiste una route di rete tra la tua workstation e la tua rete VPC, puoi indirizzare il traffico all'indirizzo IP del bilanciatore del carico di rete passthrough interno creando un'istanza Compute Engine con un proxy nginx e un tunnel SSH tra la workstation e l'istanza.

Routing di rete

Se esiste una route per il traffico di rete tra la tua workstation e la rete VPC del progetto Google Cloud, apri il browser e poi l'interfaccia web principale di Locust. Per aprire l'interfaccia di Locust, vai al seguente URL:

http://INTERNAL_LB_IP:8089

Sostituisci INTERNAL_LB_IP con l'URL e l'indirizzo IP che hai annotato nel passaggio precedente.

Proxy e tunnel SSH

  1. Imposta una variabile di ambiente con il nome dell'istanza.

    export PROXY_VM=locust-nginx-proxy
    
  2. Avvia un'istanza con un container Docker ngnix configurato per eseguire il proxy della porta dell'applicazione web Locust 8089 sul bilanciatore del carico di rete passthrough interno:

    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. Apri un tunnel SSH da Cloud Shell all'istanza proxy:

    gcloud compute ssh --zone ${ZONE} ${PROXY_VM} \
                     -- -N -L 8089:localhost:8089
    
  4. Fai clic sull'icona Anteprima web (Icona Anteprima web di Cloud Shell) e seleziona Cambia porta tra le opzioni elencate.

  5. Nella finestra di dialogo Cambia porta di anteprima, inserisci 8089 nel campo Numero porta e seleziona Cambia e visualizza anteprima.

    A breve si aprirà una scheda del browser con l'interfaccia web di Locust.

Esegui un test di carico di base sull'applicazione di esempio

  1. Dopo aver aperto il frontend di Locust nel browser, viene visualizzata una finestra di dialogo che può essere utilizzata per avviare un nuovo test di carico.

    L&#39;interfaccia web principale di Locust fornisce una finestra di dialogo per avviare un nuovo sciame e specificare il numero di utenti e il tasso di schiusa.

  2. Specifica il numero totale di utenti (concurrency massima) come 10 e la frequenza di generazione (utenti avviati/secondo) come 5 utenti per secondo.

  3. Fai clic su Avvia swarming per iniziare la simulazione.

    Dopo l'inizio delle richieste, le statistiche iniziano ad aggregarsi per le metriche di simulazione, come il numero di richieste e richieste al secondo, come mostrato nell'immagine seguente:

    L&#39;interfaccia web di Locust mostra che le statistiche iniziano ad aggregarsi.

  4. Visualizza il servizio di cui è stato eseguito il deployment e altre metriche dalla console Google Cloud.

    La dashboard di App Engine mostra un grafico di un&#39;ora di richieste per tipo.

  5. Dopo aver osservato il comportamento dell'applicazione in test, fai clic su Interrompi per terminare il test.

(Facoltativo) Aumenta il numero di utenti

Se vuoi testare un aumento del carico sull'applicazione, puoi aggiungere utenti simulati. Prima di poter aggiungere utenti simulati, devi assicurarti che siano disponibili risorse sufficienti per supportare l'aumento del carico. Con Google Cloud, puoi aggiungere pod di lavoro Locust al deployment senza eseguire nuovamente il deployment dei pod esistenti, a condizione che tu disponga delle risorse VM sottostanti per supportare un numero maggiore di pod. Il cluster GKE iniziale inizia con 3 nodi e può eseguire la scalabilità automatica fino a 10 nodi.

  • Scala il pool di pod di worker Locust a 20.

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

    Il deployment e l'avvio dei nuovi pod richiedono alcuni minuti.

Se viene visualizzato un errore Pod Unschedulable, devi aggiungere altri nodi al cluster. Per maggiori dettagli, consulta la sezione Modificare le dimensioni di un cluster GKE.

Dopo l'avvio dei pod, torna all'interfaccia web principale di Locust e riavvia il test di carico.

Espandi il pattern

Per estendere questo pattern, puoi creare nuove attività Locust o persino passare a un altro framework di test di carico.

Puoi personalizzare le metriche raccolte. Ad esempio, potresti voler misurare le richieste al secondo, monitorare la latenza di risposta con l'aumento del carico o controllare le percentuali di errore di risposta e i tipi di errori.

Per informazioni, consulta la documentazione di Cloud Monitoring.

Esegui la pulizia

Per evitare che al tuo account Google Cloud vengano addebitati costi relativi alle risorse utilizzate in questo documento, elimina il progetto che contiene le risorse oppure mantieni il progetto ed elimina le singole risorse.

Elimina il progetto

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

Elimina il cluster GKE

Se non vuoi eliminare l'intero progetto, esegui il seguente comando per eliminare il cluster GKE:

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

Passaggi successivi