Teste de carga distribuída por meio do Google Kubernetes Engine

Last reviewed 2024-08-13 UTC

Este tutorial explica como usar o Google Kubernetes Engine (GKE) para implantar um framework de teste de carga distribuída que utiliza vários contêineres para criar tráfego para uma API simples baseada em REST. Este tutorial testa a carga de um aplicativo da Web implantado no App Engine que expõe endpoints no estilo REST para responder solicitações recebidas de HTTP POST.

É possível usar o mesmo padrão para criar frameworks de teste de carga para diversos de cenários e aplicativos, como sistemas de mensagens, sistemas de gerenciamento de fluxo de dados e sistemas de banco de dados.

Objetivos

  • Definir as variáveis do ambiente para controlar a configuração da implantação.
  • Criar um cluster do GKE.
  • Realizar o teste de carga.
  • Opcionalmente, ampliar o número de usuários ou o padrão para outros casos de uso.

Custos

Neste documento, você usará os seguintes componentes faturáveis do Google Cloud:

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

Para gerar uma estimativa de custo baseada na projeção de uso deste tutorial, use a calculadora de preços. Novos usuários do Google Cloud podem estar qualificados para uma avaliação gratuita.

Antes de começar

  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. Verifique se a cobrança está ativada para o seu projeto do Google Cloud.

  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. Verifique se a cobrança está ativada para o seu projeto do Google Cloud.

  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. Ao concluir as tarefas descritas neste documento, é possível evitar o faturamento contínuo excluindo os recursos criados. Saiba mais em Limpeza.

  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_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.

Exemplo da carga de trabalho

No diagrama abaixo, mostramos um exemplo de carga de trabalho em que as solicitações vão do cliente para aplicativo.

Solicitações do cliente para o aplicativo.

Para moldar essa interação, Locust, uma ferramenta de teste de carga distribuída baseada em Python que pode distribuir solicitações por vários caminhos de destino. Por exemplo, com o Locust, essa distribuição é feita para os caminhos de destino /login e /metrics. A carga de trabalho é definida como um conjunto de tarefas no Locust.

Arquitetura

Essa arquitetura envolve dois componentes principais:

  • A imagem do contêiner do Locust no Docker
  • O mecanismo de orquestração e gerenciamento de contêineres

A imagem do contêiner do Locust no Docker contém o software Locust. O Dockerfile, que você recebe ao clonar o repositório do GitHub que acompanha este documento, usa uma imagem Python básica e inclui scripts para iniciar o serviço do Locust e executar as tarefas. Para simular situações reais dos clientes, cada tarefa do Locust tem um peso. Por exemplo, o registro ocorre uma vez a cada mil solicitações de cliente.

O GKE fornece orquestração e gerenciamento de contêineres. Com o GKE, é possível especificar o número de nós de contêiner que fornecem a base para seu framework de teste de carga. Também é possível organizar seus workers de teste de carga em pods e especificar quantos pods você quer que o GKE continue executando.

Para implantar as tarefas de teste de carga, faça o seguinte:

  1. Implante uma principal de teste de carga, chamada de mestre pelo Locust.
  2. Implante um grupo de workers de teste de carga. Com esses workers, é possível criar uma quantidade substancial de tráfego para fins de teste.

O diagrama a seguir mostra a arquitetura que demonstra o teste de carga usando um aplicativo de amostra. O pod mestre atende à interface da Web usada para operar e monitorar o teste de carga. Os pods de worker geram o tráfego da solicitação REST para o aplicativo que está passando pelo teste e enviam as métricas para o mestre.

O pod principal atende à interface da Web usada para operar e monitorar os testes de carga. Os pods de worker geram o tráfego de solicitação REST para o aplicativo que está passando pelo teste.

Sobre o mestre de testes de carga

O mestre do Locust é o ponto de entrada para executar as tarefas de teste de carga. A configuração do mestre do Locust especifica vários elementos, incluindo as portas padrão usadas pelo contêiner:

  • 8089 para a interface da Web
  • 5557 e 5558 para comunicação com workers

Essas informações serão usadas depois na configuração dos workers do Locust.

Implante um Serviço para garantir que as portas necessárias possam ser acessadas por outros pods no cluster usando hostname:port. Essas portas também podem ser referenciadas por um nome descritivo.

Esse serviço permite que os workers do Locust descubram e se comuniquem de forma confiável com o mestre, mesmo se o mestre falhar e for substituído por um novo pod pela implantação.

Um segundo Serviço é implantado com a anotação necessária para criar um balanceamento de carga de rede de passagem interno que torna o serviço do aplicativo da Web Locust acessível a clientes fora do cluster que usem a mesma rede VPC e estejam localizados na mesma região do Google Cloud que o cluster.

Depois de implantar o mestre do Locust, é possível abrir a interface da Web usando o endereço IP interno provisionado pelo balanceador de carga de rede de passagem interno. Após a implantação dos workers do Locust, inicie a simulação e veja as estatísticas agrupadas nessa interface.

Sobre os workers de teste de carga

Os workers do Locust executam as tarefas de teste de carga. Use uma única implantação para criar vários pods. Esses pods são distribuídos no cluster do Kubernetes. Cada um deles usa variáveis de ambiente para controlar informações de configuração, por exemplo, os nomes dos hosts do sistema em teste e do mestre do Locust.

No diagrama a seguir, veja a relação entre o mestre e os workers do Locust.

O mestre do Locust fica na parte superior de uma hierarquia com vários workers abaixo dele.

Inicializar variáveis comuns

É preciso definir diversas variáveis que controlam onde os elementos da infraestrutura serão implantados.

  1. Abra o Cloud Shell:

    Abrir o Cloud Shell

    Você executa todos os comandos do terminal deste documento no Cloud Shell.

  2. Defina as variáveis de ambiente que exigem personalização:

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

    Substitua:

    • GKE_CLUSTER: o nome do cluster do GKE.
    • AR_REPO: o nome do repositório do Artifact Registry
    • REGION: a região em que o cluster do GKE e o repositório do Artifact Registry serão criados
    • ZONE: a zona na sua região em que a instância do Compute Engine será criada
    • SAMPLE_APP_LOCATION: o local (regional) em que o aplicativo de exemplo do App Engine será implantado

    Os comandos serão semelhantes a este exemplo:

    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. Defina as seguintes variáveis de ambiente adicionais:

    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. Defina a zona padrão para não precisar especificar esses valores em comandos seguintes:

    gcloud config set compute/zone ${ZONE}
    

Crie um cluster do GKE

  1. Crie uma conta de serviço com as permissões mínimas exigidas pelo 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. Crie o cluster do 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. Conecte-se ao cluster do GKE:

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

Configure o ambiente

  1. Clone o repositório de amostra do GitHub:

    git clone https://github.com/GoogleCloudPlatform/distributed-load-testing-using-kubernetes
    
  2. Altere o diretório de trabalho para o repositório clonado:

    cd distributed-load-testing-using-kubernetes
    

Crie a imagem do contêiner

  1. Crie um repositório do Artifact Registry:

    gcloud artifacts repositories create ${AR_REPO} \
        --repository-format=docker  \
        --location=${REGION} \
        --description="Distributed load testing with GKE and Locust"
    
  2. Crie a imagem do contêiner e armazene-a no repositório do 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
    

    A imagem do Docker do Locust incorpora uma tarefa de teste que chama os endpoints /login e /metrics no aplicativo de amostra. Neste exemplo de conjunto de tarefas de teste, a proporção de solicitações enviadas para esses dois endpoints será de 1 para 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. Verifique se a imagem do Docker está no repositório do Artifact Registry:

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

    A saída será assim:

    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
    

Implantar o aplicativo de amostra

  1. Crie e implante o sample-webapp como App Engine:

    gcloud app create --region=${SAMPLE_APP_LOCATION}
    gcloud app deploy sample-webapp/app.yaml \
    --project=${PROJECT}
    
  2. Quando solicitado, digite y para continuar a implantação.

    O resultado será assim:

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

    O aplicativo de amostra do App Engine implementa os endpoints /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)

Implante os nós do mestre e de trabalho do Locust

  1. Substitua os valores da variável de ambiente pelos parâmetros de host, projeto e imagem de destino nos arquivos locust-master-controller.yaml e locust-worker-controller.yaml. Depois, crie as implantações mestre e worker do 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. Verifique as implantações do Locust:

    kubectl get pods -o wide
    

    A saída tem uma aparência semelhante à seguinte:

    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. Verifique os serviços:

    kubectl get services
    

    A saída tem uma aparência semelhante à seguinte:

    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. Execute um loop de observação enquanto o endereço IP interno do balanceador de carga de rede de passagem interno (endereço IP externo do GKE) é provisionado para o serviço mestre de aplicativo da Web do Locust:

    kubectl get svc locust-master-web --watch
    
  5. Pressione Ctrl+C para sair do loop de observação depois que um endereço EXTERNAL-IP for provisionado.

Conectar-se ao front-end da Web do Locust

É possível usar a interface mestre da Web do Locust para executar as tarefas de teste de carga no sistema sendo testado.

  1. Anote o endereço IP interno do balanceador de carga do serviço de host da Web:

    export INTERNAL_LB_IP=$(kubectl get svc locust-master-web  \
                                   -o jsonpath="{.status.loadBalancer.ingress[0].ip}") && \
                                   echo $INTERNAL_LB_IP
    
  2. Dependendo da configuração de rede, há duas maneiras de se conectar ao aplicativo da Web Locust pelo endereço IP provisionado:

    • Roteamento de rede. Se a rede estiver configurada para permitir o roteamento da estação de trabalho para a rede VPC do projeto, é possível acessar diretamente o endereço IP interno de balanceamento de carga de rede de passagem da estação de trabalho.

    • Túnel proxy e SSH Se não houver uma rota de rede entre a estação de trabalho e a rede VPC, crie uma instância do Compute Engine com um proxy nginx e um túnel SSH entre a estação de trabalho e a instância para direcionar o tráfego ao endereço IP interno de balanceamento de carga de rede de passagem interno.

Roteamento de rede

Se houver uma rota para o tráfego de rede entre a estação de trabalho e a rede VPC do projeto do Google Cloud, abra o navegador e, em seguida, a interface da Web mestre do Locust. Para abrir a interface do Locust, acesse o seguinte URL:

http://INTERNAL_LB_IP:8089

Substitua INTERNAL_LB_IP pelo URL e endereço IP que você anotou na etapa anterior.

Túnel proxy e SSH

  1. Defina uma variável de ambiente com o nome da instância.

    export PROXY_VM=locust-nginx-proxy
    
  2. Inicie uma instância com um contêiner do Docker ngnix configurado para fazer o proxy da porta 8089 do aplicativo da Web do Locust no balanceamento de carga de rede de passagem 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. Abra um túnel SSH do Cloud Shell para a instância de proxy:

    gcloud compute ssh --zone ${ZONE} ${PROXY_VM} \
                     -- -N -L 8089:localhost:8089
    
  4. Clique no ícone Visualização da Web (Ícone de visualização da Web do Cloud Shell) e selecione Alterar porta nas opções listadas.

  5. Na caixa de diálogo Alterar porta de visualização, insira 8089 no campo Número da porta e selecione Alterar e visualizar.

    Em instantes, uma guia do navegador será aberta com a interface da Web do Locust.

Executar um teste de carga básico no seu aplicativo de amostra

  1. Depois de abrir o front-end do Locust no navegador, você verá uma caixa de diálogo que pode ser usada para iniciar um novo teste de carga.

    A interface mestre da Web do Locust abre uma caixa de diálogo para iniciar um novo sawrm e especificar o número de usuários e a taxa de geração.

  2. Especifique o total de Número de usuários (pico de simultaneidade) como 10 e a Taxa de geração (usuários iniciados por segundo) como 5 usuários por segundo.

  3. Clique em Start swarming para iniciar a simulação.

    Depois que o swarming das solicitações é iniciado, as estatísticas começam a ser agregadas para as métricas de simulação, como o número de solicitações e solicitações por segundo, como mostra a imagem abaixo:

    A interface da Web do Locust mostra que as estatísticas começam a ser agregadas.

  4. Veja o serviço implantado e outras métricas do Console do Google Cloud.

    O painel do App Engine mostra um gráfico de uma hora de solicitações divididas por tipo.

  5. Quando você observar o comportamento do aplicativo em teste, clique em Parar para encerrá-lo.

Como aumentar o número de usuários (opcional)

Se quiser testar o aumento de carga no aplicativo, é possível adicionar usuários simulados. Antes de adicionar usuários simulados, você precisa garantir que haja recursos suficientes para suportar o aumento da carga. Com o Google Cloud, é possível adicionar pods de trabalho do Locust à implantação sem reimplantar os pods atuais, contanto que você tenha os recursos de VM subjacentes para suportar um número maior de pods. O cluster inicial do GKE começa com 3 nós e pode fazer o escalonamento automático para até 10 nós.

  • Aumente o pool de pods de worker do Locust para 20.

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

    Demora alguns minutos para implantar e iniciar os novos pods.

Se você vir um erro de Pod não programável, será necessário adicionar mais nós ao cluster. Para detalhes, consulte Como redimensionar o cluster do GKE.

Depois que os pods forem iniciados, retorne à interface mestre da Web do Locust e reinicie o teste de carga.

Estender o padrão

Para estender esse padrão, é possível criar novas tarefas do Locust ou até mudar para um framework de teste de carga diferente.

É possível personalizar as métricas coletadas. Por exemplo, é possível medir as solicitações por segundo, monitorar a latência das respostas à medida que a carga aumenta ou verificar as taxas de falha de resposta e os tipos de erros.

Para mais informações, consulte a documentação do Cloud Monitoring.

Limpar

Para evitar cobranças na sua conta do Google Cloud pelos recursos usados neste documento, exclua o projeto ou mantenha o projeto e exclua cada um dos recursos.

Exclua o projeto

  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.

Excluir o cluster do GKE

Se você não quiser excluir o projeto todo, execute o seguinte comando para excluir o cluster do GKE:

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

A seguir