Test di carico distribuito con Google Kubernetes Engine

Last reviewed 2022-04-22 UTC

Questo tutorial 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 tutorial esegue il test del carico di un'applicazione web di cui è stato eseguito il deployment in App Engine che espone gli endpoint di tipo REST per rispondere alle richieste POST HTTP in entrata.

Puoi utilizzare questo stesso pattern per creare framework di test di carico per diversi scenari e applicazioni, come sistemi di messaggistica, sistemi di gestione stream di dati e sistemi di database.

Obiettivi

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

Costi

In questo documento vengono utilizzati i seguenti componenti fatturabili di Google Cloud:

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

Per generare una stima dei costi in base all'utilizzo previsto, utilizza il Calcolatore prezzi. I nuovi utenti di Google Cloud possono essere idonei a una prova senza costi aggiuntivi.

Prima di iniziare

  1. Accedi al tuo account Google Cloud. Se non conosci Google Cloud, crea un account per valutare le prestazioni dei nostri prodotti in scenari reali. I nuovi clienti ricevono anche 300 $di crediti gratuiti per l'esecuzione, il test e il deployment dei carichi di lavoro.
  2. Nella pagina del selettore di progetti della console Google Cloud, seleziona o crea un progetto Google Cloud.

    Vai al selettore progetti

  3. Assicurati che la fatturazione sia attivata per il tuo progetto Google Cloud.

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

    Abilita le API

  5. Nella pagina del selettore di progetti della console Google Cloud, seleziona o crea un progetto Google Cloud.

    Vai al selettore progetti

  6. Assicurati che la fatturazione sia attivata per il tuo progetto Google Cloud.

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

    Abilita le API

  8. Una volta completate le attività descritte in questo documento, puoi evitare la fatturazione continua eliminando le risorse che hai creato. Per ulteriori informazioni, consulta la pagina Pulizia.

  9. Concedi i ruoli al tuo Account Google. Esegui questo comando una volta per ciascuno dei seguenti ruoli IAM: 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
    • Sostituisci PROJECT_ID con l'ID progetto.
    • Sostituisci EMAIL_ADDRESS con il tuo indirizzo email.
    • Sostituisci ROLE con ogni singolo ruolo.

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 provenienti dal client all'applicazione.

Per creare un modello di questa interazione, puoi utilizzare Locust, uno strumento distribuito di test del carico basato su Python in grado di distribuire le richieste su più percorsi di destinazione. Ad esempio, Locust può distribuire le richieste ai percorsi di destinazione /login e /metrics. Il carico di lavoro è modellato come un insieme di attività in Locust.

Architettura

Questa architettura è composta da due componenti principali:

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

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

GKE offre l'orchestrazione e la gestione dei container. Con GKE, puoi specificare il numero di nodi container che forniscono la base per il framework di test di carico. Puoi anche organizzare i worker di test di carico in pod e specificare quanti pod vuoi che GKE mantenga in esecuzione.

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

  1. Esegui il deployment di un master di test di carico.
  2. Esegui il deployment di un gruppo di worker per il test di carico. Con questi worker per i test di carico puoi creare una quantità considerevole 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 master gestisce l'interfaccia web usata per operare 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 master gestisce 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 master di test di carico

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

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

Queste informazioni vengono utilizzate in un secondo momento per configurare i worker Locust.

Esegui il deployment di un servizio per assicurarti che le porte necessarie siano accessibili ad altri pod all'interno del cluster tramite hostname:port. È possibile fare riferimento a queste porte anche tramite un nome descrittivo.

Questo servizio consente ai worker Locust di rilevare facilmente e comunicare in modo affidabile con il master, anche in caso di errore del master e di sostituirlo con un nuovo pod dal deployment.

Viene eseguito il deployment di un secondo servizio con l'annotazione necessaria per creare un bilanciatore del carico di rete passthrough interno che rende il servizio per applicazioni web Locust accessibile 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 privato 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 visualizzare le statistiche aggregate tramite l'interfaccia web di Locust.

Informazioni sui worker per il test di carico

I worker Locust eseguono le attività di test di carico. si usa un solo deployment per creare più pod. I pod sono distribuiti nel cluster Kubernetes. Ogni pod usa variabili di ambiente per controllare le informazioni di configurazione, ad esempio il nome host del sistema sottoposto a 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 in cima a una gerarchia con più worker al di sotto.

Inizializzare le variabili comuni

Devi definire diverse variabili che controllano dove viene eseguito il deployment degli elementi dell'infrastruttura.

  1. Apri Cloud Shell:

    Apri Cloud Shell

    In questo tutorial esegui tutti i comandi del terminale 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 tuo 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à eseguito il deployment dell'applicazione App Engine di esempio

    I comandi dovrebbero essere simili al seguente esempio:

    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}
    

Configurare 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 nel 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 associata a Locust incorpora un'attività di test che chiama gli endpoint /login e /metrics nell'applicazione di esempio. In questo set di attività di test di esempio, il rispettivo rapporto di richieste inviate a questi due endpoint sarà compreso tra 1 e 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 si trovi nel tuo 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 dell'app web di esempio 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 master e worker Locust

  1. Sostituisci i valori della variabile di ambiente per i parametri host, progetto e immagine di destinazione nei file locust-master-controller.yaml e locust-worker-controller.yaml e crea i deployment worker e master 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. Verifica i deployment Locust:

    kubectl get pods -o wide
    

    L'output sarà 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 sarà 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 ciclo di controllo mentre viene eseguito il provisioning dell'indirizzo IP privato del bilanciatore del carico di rete passthrough interno (indirizzo IP esterno GKE) per il servizio applicazione web Locust master:

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

Connettiti al front-end web di Locust

Utilizza l'interfaccia web di Locust Master per eseguire le attività di test di carico sul sistema sottoposto a test.

  1. Ottieni l'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 della rete, puoi connetterti 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 in modo da consentire il routing dalla workstation alla rete VPC del progetto, puoi accedere direttamente all'indirizzo IP del bilanciatore del carico di rete passthrough interno dalla tua workstation.

    • Tunnel proxy e SSH. Se non esiste una route di rete tra la workstation e la rete VPC, puoi instradare il traffico all'indirizzo IP del bilanciatore del carico di rete passthrough interno creando un'istanza di 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 del master Locust. Sostituisci [INTERNAL_LB_IP] nel seguente URL con l'indirizzo IP osservato nel passaggio precedente: http://[INTERNAL_LB_IP]:8089.

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 del 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 dalle opzioni elencate.

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

    Tra poco 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
swarm e specificare il numero di utenti e la percentuale di tratteggio.

  2. Specifica il numero totale di utenti (contemporaneità massima) come 10 e la frequenza interna (utenti avviati/secondo) pari a 5 utenti al secondo.

  3. Fai clic su Inizia sciame per iniziare la simulazione.

    Una volta che le richieste iniziano a essere raggruppate, le statistiche iniziano ad aggregarsi per le metriche di simulazione, ad esempio il numero di richieste e richieste al secondo, come mostrato nella seguente immagine:

    L'interfaccia web di Locust mostra che le statistiche iniziano ad essere aggregate.
  4. Visualizza il servizio di cui hai eseguito il deployment e altre metriche nella console Google Cloud.

    La dashboard di App Engine mostra un grafico di un'ora di richieste per tipo.
  5. Dopo aver osservato il comportamento dell'applicazione in fase di test, fai clic su Arresta per terminare il test.

(Facoltativo) Fai lo scale up del numero di utenti

Se vuoi testare l'aumento del carico sull'applicazione, puoi aggiungere utenti simulati. Prima di poter aggiungere utenti simulati, devi assicurarti di disporre di risorse sufficienti per supportare l'aumento del carico. Con Google Cloud puoi aggiungere pod worker Locust al deployment senza eseguire nuovamente il deployment dei pod esistenti, purché tu disponga delle risorse VM sottostanti per supportare un numero maggiore di pod. Il cluster GKE iniziale viene avviato con 3 nodi e può scalare automaticamente 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 visualizzi un errore Pod non pianificabile, devi aggiungere altri nodi al cluster. Per maggiori dettagli, consulta Ridimensionamento di un cluster GKE.

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

Estendi la sequenza

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

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

Per ulteriori informazioni, consulta la documentazione di Cloud Monitoring.

Esegui la pulizia

Al termine del tutorial, puoi eseguire la pulizia delle risorse che hai creato in modo che non ti vengano addebitati costi in futuro.

Elimina il progetto

Il modo più semplice per eliminare la fatturazione è eliminare il progetto che hai creato per il tutorial.

Per eliminare il progetto:

  1. Nella console Google Cloud, vai alla pagina Gestisci risorse.

    Vai a Gestisci risorse

  2. Nell'elenco dei progetti, seleziona il progetto che vuoi eliminare, quindi fai clic su Elimina.
  3. Nella finestra di dialogo, digita l'ID del progetto e fai clic su Chiudi per eliminare il progetto.

Elimina il cluster GKE

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

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

Passaggi successivi