Implemente um cluster Redis no GKE

Este tutorial fornece práticas recomendadas para criar uma aplicação com estado e atualizar o cluster do Google Kubernetes Engine (GKE) que está a executar a aplicação. Este tutorial usa o Redis como exemplo para implementar uma aplicação com estado, mas os mesmos conceitos são aplicáveis a outros tipos de aplicações com estado implementadas no GKE.

Objetivos

Este tutorial abrange os seguintes passos:

  1. Crie um cluster do GKE inscrito num canal de lançamento.
  2. Crie um Redis Cluster no GKE.
  3. Implemente a aplicação cliente Redis no GKE.
  4. Siga estas práticas recomendadas para atualizações de node pools:
    1. Configure o Pod Disruption Budget (PDB).
    2. Configure a janela de manutenção e as exclusões.
    3. Configure a estratégia de atualização de nós para atualização por picos ou atualização azul-verde.
  5. Teste a aplicação.
  6. Atualize o cluster.
  7. Teste a interrupção da carga de trabalho.

O diagrama seguinte mostra uma vista de alto nível da arquitetura de cluster para este tutorial:

Diagrama de arquitetura

Custos

Neste documento, usa os seguintes componentes faturáveis do Google Cloud:

Para gerar uma estimativa de custos com base na sua utilização prevista, use a calculadora de preços.

Os novos Google Cloud utilizadores podem ser elegíveis para uma avaliação sem custo financeiro.

Quando terminar as tarefas descritas neste documento, pode evitar a faturação contínua eliminando os recursos que criou. Para mais informações, consulte o artigo Limpe.

Antes de começar

Configure o seu projeto

  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, click Create project to begin creating a new Google Cloud project.

    Roles required to create a project

    To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. Enable the GKE API.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the API

  5. In the Google Cloud console, on the project selector page, click Create project to begin creating a new Google Cloud project.

    Roles required to create a project

    To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  6. Verify that billing is enabled for your Google Cloud project.

  7. Enable the GKE API.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the API

  8. Defina predefinições para a CLI Google Cloud

    1. Na Google Cloud consola, inicie uma instância do Cloud Shell:
      Abrir Cloud Shell

    2. Transfira o código-fonte desta app de exemplo:

       git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
       cd kubernetes-engine-samples/quickstarts/hello-app-redis/manifests
      
    3. Defina as variáveis de ambiente predefinidas:

       gcloud config set project PROJECT-ID
       gcloud config set compute/zone COMPUTE-ZONE
      

      Substitua os seguintes valores:

    Crie um cluster do GKE inscrito num canal de lançamento

    Para criar o cluster do GKE, conclua os passos seguintes:

    1. Crie um cluster com o nome redis-test com três nós:

      gcloud container clusters create redis-test \
          --location CONTROL_PLANE_LOCATION \
          --num-nodes=3 \
          --release-channel regular
      

      Substitua CONTROL_PLANE_LOCATION pela localização do Compute Engine do plano de controlo do seu cluster. Indique uma região para clusters regionais ou uma zona para clusters zonais.

      Depois de criar o cluster, deve ver um resultado semelhante ao seguinte exemplo:

        NAME: redis-test
        LOCATION: us-central1-c
        MASTER_VERSION: 1.22.10-gke.600
        MASTER_IP: 34.69.67.7
        MACHINE_TYPE: e2-medium
        NODE_VERSION: 1.22.10-gke.600
        NUM_NODES: 3
        STATUS: RUNNING
      
    2. Configure o kubectl para comunicar com o cluster:

      gcloud container clusters get-credentials redis-test
      

    Crie um cluster do Redis no GKE

    Nesta secção, adiciona um cluster Redis sobre o cluster GKE que criou anteriormente implementando um ConfigMap, um StatefulSet e um serviço sem cabeçalho.

    Para criar um cluster do Redis, conclua estes passos:

    1. Consulte o ficheiro ConfigMap (redis-configmap.yaml) que armazena a configuração do Redis. O fragmento abaixo mostra os scripts da sonda de prontidão e da sonda de atividade.

      readiness.sh: |-
        #!/bin/sh
      
        pingResponse="$(redis-cli -h localhost ping)"
        if [ "$?" -eq "124" ]; then
          echo "PING timed out"
          exit 1
        fi
      
        if [ "$pingResponse" != "PONG"]; then
          echo "$pingResponse"
          exit 1
        fi
      liveness.sh: |-
        #!/bin/sh
      
        pingResponse="$(redis-cli -h localhost ping | head -n1 | awk '{print $1;}')"
        if [ "$?" -eq "124" ]; then
          echo "PING timed out"
          exit 1
        fi
      
        if [ "$pingResponse" != "PONG"] && [ "$pingResponse" != "LOADING" ] && [ "$pingResponse" != "MASTERDOWN" ]; then
          echo "$pingResponse"
          exit 1
        fi

      Os scripts readiness.sh e liveness.sh usam redis-cli ping para verificar se o servidor redis está em execução ou não. Se devolver PONG, o servidor Redis está a funcionar. Estes scripts vão ser usados no redis-cluster.yaml.

      Para saber mais acerca dos parâmetros do Redis neste ConfigMap, consulte a secção de parâmetros de configuração do cluster Redis no tutorial do cluster Redis.

    2. Implemente o ConfigMap:

      kubectl apply -f redis-configmap.yaml
      
    3. Consulte o fragmento StatefulSet (redis-cluster.yaml) abaixo, que mostra a utilização da sondagem de prontidão e da sondagem de atividade.

      Para saber como configurar sondas no Kubernetes, consulte o artigo Configure sondas.

      startupProbe:
        periodSeconds: 5
        timeoutSeconds: 5
        successThreshold: 1
        failureThreshold: 20
        tcpSocket:
          port: redis
      livenessProbe:
        periodSeconds: 5
        timeoutSeconds: 5
        successThreshold: 1
        failureThreshold: 5
        exec:
          command: ["sh", "-c", "/probes/liveness.sh"]
      readinessProbe:
        periodSeconds: 5
        timeoutSeconds: 1
        successThreshold: 1
        failureThreshold: 5
        exec:
          command: ["sh", "-c", "/probes/readiness.sh"]

      Recomendamos vivamente que use sondas de prontidão e de atividade quando atualizar conjuntos de nós. Isto garante que os seus pods estão prontos durante uma atualização.

    4. Implemente o StatefulSet:

      kubectl apply -f redis-cluster.yaml
      
    5. O serviço sem interface chamado redis-service.yaml destina-se à ligação dos nós do Redis. O campo clusterIP está definido como None para criar um serviço sem interface.

      Implemente o serviço:

      kubectl apply -f redis-service.yaml
      
    6. Aguarde aproximadamente dois minutos e verifique se todos os pods estão em execução através do seguinte comando:

      kubectl get pods
      

      Deverá ver uma saída semelhante ao seguinte exemplo:

      NAME      READY   STATUS              RESTARTS   AGE
      redis-0   1/1     Running             0          2m29s
      redis-1   1/1     Running             0          2m8s
      redis-2   1/1     Running             0          107s
      redis-3   1/1     Running             0          85s
      redis-4   1/1     Running             0          54s
      redis-5   1/1     Running             0          23s
      
    7. Verifique se os volumes persistentes foram criados executando o seguinte comando:

      kubectl get pv
      

      Deverá ver uma saída semelhante ao seguinte exemplo:

      NAME       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                  STORAGECLASS   REASON   AGE
      pvc-HASH   1Gi        RWO            Delete           Bound    default/data-redis-5   standard                75s
      pvc-HASH   1Gi        RWO            Delete           Bound    default/data-redis-1   standard                2m59s
      pvc-HASH   1Gi        RWO            Delete           Bound    default/data-redis-3   standard                2m16s
      pvc-HASH   1Gi        RWO            Delete           Bound    default/data-redis-2   standard                2m38s
      pvc-HASH   1Gi        RWO            Delete           Bound    default/data-redis-0   standard                3m20s
      pvc-HASH   1Gi        RWO            Delete           Bound    default/data-redis-4   standard                104s
      

      Neste resultado, HASH representa um hash anexado a cada nome de volume persistente.

    Atribua funções ao seu Redis Cluster

    Quando a configuração estiver concluída, atribua funções ao cluster Redis.

    O script seguinte obtém os endereços IP dos pods e, em seguida, atribui as funções de líder e seguidor transmitindo cada um dos endereços IP dos pods para o comando:

    #!/bin/bash
    # Usage: ./roles.sh
    
    urls=$(kubectl get pods -l app=redis -o jsonpath='{range.items[*]}{.status.podIP} ')
    command="kubectl exec -it redis-0 -- redis-cli --cluster create --cluster-replicas 1 "
    
    for url in $urls
    do
        command+=$url":6379 "
    done
    
    echo "Executing command: " $command
    $command

    Para atribuir funções ao seu cluster Redis, conclua estes passos:

    1. Execute o script:

      chmod +x ./roles.sh
      ./roles.sh
      
    2. Escreva yes quando lhe for pedido.

    3. Inicie sessão num nó do Redis para verificar a respetiva função. Por exemplo, para verificar se redis-0 tem uma função de líder, execute o seguinte comando:

      kubectl exec -it redis-0 -- redis-cli role
      

      Deverá ver uma saída semelhante ao seguinte exemplo:

      1) "master"
      2) (integer) 574
      3) 1) 1) "10.28.2.3"
             2) "6379"
             3) "574"
      

    Implemente a aplicação cliente Redis

    Para implementar a sua aplicação no cluster do GKE que criou, defina uma implementação para a sua aplicação. O ficheiro denominado app-deployment.yaml contém a definição de implementação da aplicação.

    Para saber mais acerca das sondas e das regras de afinidade de pods usadas nesta implementação, consulte o artigo Práticas recomendadas do GKE: conceber e criar clusters de elevada disponibilidade.

    Para criar a implementação, conclua os seguintes passos:

    1. Aplique a implementação:

      kubectl apply -f app-deployment.yaml
      
    2. Exponha a aplicação através de um balanceador de carga:

      kubectl expose deployment hello-web \
          --type=LoadBalancer \
          --port 80 \
          --target-port 8080
      
    3. Aguarde aproximadamente um minuto e obtenha o endereço IP externo da aplicação executando o seguinte comando:

      kubectl get service
      

      Na saída, copie o valor indicado na coluna hello-web's EXTERNAL-IP:

      NAME             TYPE           CLUSTER-IP    EXTERNAL-IP    PORT(S)              AGE
      hello-web        LoadBalancer   10.13.10.55   EXTERNAL_IP   80:30703/TCP         166m
      
    4. Verifique se a aplicação está a funcionar colando o EXTERNAL_IP no seu navegador de Internet. Deverá ver uma saída semelhante ao seguinte exemplo:

      I have been hit [1] times since deployment!
      

      Tome nota do número da visita. Tem de usá-lo na secção Testar a interrupção da aplicação.

    5. Defina uma variável para o EXTERNAL_IP que acabou de copiar. Use este valor quando criar scripts para testar a sua aplicação na secção seguinte:

      export IP=EXTERNAL_IP
      

    Configure as práticas recomendadas para atualizações de node pools

    Siga estas práticas recomendadas para aplicações com estado para otimizar a disponibilidade durante as atualizações do conjunto de nós.

    Configure o Pod Disruption Budget (PDB)

    Crie um orçamento de interrupção de pods para limitar o número de pods replicados que estão inativos em simultâneo durante uma interrupção voluntária. Isto é útil para aplicações com estado em que tem de existir um quórum para o número de réplicas estar disponível durante uma atualização.

    apiVersion: policy/v1
    kind: PodDisruptionBudget
    metadata:
      name: redis-pdb
    spec:
      minAvailable: 3
      selector:
        matchLabels:
          app: redis

    Numa definição de PDB:

    • app especifica a que aplicação se aplica este PDB.
    • minAvailable define o número mínimo de pods a estar disponível durante uma interrupção. Pode ser um valor ou uma percentagem (por exemplo, 30%).
    • maxUnavailable define o número máximo de agrupamentos que podem estar indisponíveis durante uma interrupção. Também pode ser um valor ou uma percentagem.

    Para configurar a PDB, conclua estes passos:

    1. Implemente o PDB:

      kubectl apply -f pdb-minavailable.yaml
      
    2. Verifique se o PDB foi criado:

      kubectl get pdb
      

    Configure os períodos de manutenção e as exclusões

    As atualizações automáticas de nós simplificam o processo de atualização e mantêm os nós no cluster atualizados quando o plano de controlo é atualizado automaticamente. Esta funcionalidade está ativada por predefinição. Para saber mais, consulte o artigo Atualizar nós automaticamente.

    Use janelas de manutenção e exclusões de manutenção para configurar intervalos de tempo e controlar quando a manutenção pode e não pode ocorrer em clusters do GKE:

    1. Configurar uma janela de manutenção que comece às 02:00 UTC a 19 de agosto de 2022 e termine quatro horas mais tarde. Esta janela de manutenção é executada diariamente. Durante este período, é permitida a manutenção automática.

      gcloud container clusters update redis-test \
         --maintenance-window-start 2022-08-19T02:00:00Z \
         --maintenance-window-end 2022-08-19T06:00:00Z \
         --maintenance-window-recurrence FREQ=DAILY
      
    2. Configure um período de exclusão que impeça a manutenção durante o feriado do Ano Novo. Esta exclusão de manutenção usa o âmbito no_upgrades. Durante este período, não é permitida qualquer tipo de manutenção automática. Para saber mais, consulte o artigo Âmbito da manutenção a excluir.

      gcloud container clusters update redis-test \
         --add-maintenance-exclusion-name new-year \
         --add-maintenance-exclusion-start 2022-12-26T00:00:00Z \
         --add-maintenance-exclusion-end 2023-01-02T02:00:00Z \
         --add-maintenance-exclusion-scope no_upgrades
      
    3. Confirme se a janela de manutenção e as exclusões foram aplicadas. Procure em maintenancePolicy:

      gcloud container clusters describe redis-test
      

    Para saber mais, consulte o artigo Configure janelas de manutenção e exclusões.

    Configure uma estratégia de atualização de nós

    Existem duas estratégias de atualização de nós que pode usar para os conjuntos de nós no seu cluster do GKE: atualizações azul-verde e atualizações de picos. Para saber mais, consulte Estratégias de atualização de nós.

    Atualizações azul-verde

    Escolha atualizações azul-verde se as cargas de trabalho forem menos tolerantes a interrupções e um aumento temporário do custo devido a uma maior utilização de recursos for aceitável.

    Execute o seguinte comando para alterar os conjuntos de nós atuais para a estratégia de atualização azul-verde.

    gcloud container node-pools update default-pool \
    --cluster=redis-test \
    --enable-blue-green-upgrade \
    --location CONTROL_PLANE_LOCATION \
    --node-pool-soak-duration=120s
    

    A duração da imersão do conjunto de nós está definida como dois minutos para poupar tempo durante a fase de imersão do conjunto de nós para efeitos deste tutorial. Esta fase é usada para validar o estado de funcionamento da carga de trabalho depois de os nós do conjunto azul terem sido esvaziados. Recomendamos que defina a duração da preparação do conjunto de nós para uma hora (3600 segundos) ou uma duração mais adequada à aplicação.

    Para mais informações sobre a gestão da atribuição de pods, consulte os artigos Implemente um pod num conjunto de nós específico e Implementar serviços em conjuntos de nós específicos.

    Para mais informações sobre a configuração de atualizações azul-verde, consulte o artigo Configure atualizações azul-verde.

    Atualizações de aumentos

    Escolha atualizações rápidas se a otimização de custos for importante e se as cargas de trabalho puderem tolerar um encerramento gradual em menos de 60 minutos (o GKE respeita o PDB até 60 minutos).

    Execute o seguinte comando para alterar os conjuntos de nós atuais para a estratégia de atualização rápida.

    gcloud container node-pools update default-pool \
    --max-surge-upgrade=1 \
    --max-unavailable-upgrade=0 \
    --cluster=redis-test
    

    Com esta configuração (maxSurge=1 e maxUnavailable=0), só é possível adicionar um nó de pico ao conjunto de nós durante uma atualização, pelo que só é possível atualizar um nó de cada vez. Esta definição acelera os reinícios dos pods durante as atualizações, ao mesmo tempo que progride de forma conservadora.

    Para mais informações sobre a configuração de atualizações de picos, consulte o artigo Configure atualizações de picos.

    Verifique a configuração atual do conjunto de nós:

       gcloud container node-pools describe default-pool \
       --cluster redis-test \
       --location CONTROL_PLANE_LOCATION
    

    Para mais informações sobre a visualização de pools de nós, consulte o artigo Veja pools de nós num cluster.

    Teste a aplicação

    Nesta secção, usa dois scripts: um que envia pedidos para a sua aplicação e outro que mede a taxa de êxito dos pedidos. Use estes scripts para medir o que acontece quando atualiza o cluster.

    Para criar os scripts:

    1. Altere para o diretório que contém os scripts:

      cd
      cd kubernetes-engine-samples/quickstarts/hello-app-redis/scripts
      
    2. Consulte o script denominado generate_load.sh que envia um pedido de consultas por segundo (CPS) à sua aplicação. O script guarda o código de resposta HTTP no diretório atual num ficheiro denominado output. O valor de output é usado no script que criar no passo seguinte.

      #!/bin/bash
      # Usage: ./generate_load.sh <IP> <QPS>
      
      IP=$1
      QPS=$2
      
      while true
        do for N in $(seq 1 $QPS)
          do curl -I -m 5 -s -w "%{http_code}\n" -o /dev/null http://${IP}/ >> output &
          done
        sleep 1
      done
    3. Consulte o script denominado print_error_rate.sh, que calcula a taxa de êxito com base no resultado gerado por generate_load.sh.

      #!/bin/bash
      # Usage: watch ./print_error_rate.sh
      
      TOTAL=$(cat output | wc -l);
      SUCCESS=$(grep "200" output |  wc -l);
      ERROR1=$(grep "000" output |  wc -l)
      ERROR2=$(grep "503" output |  wc -l)
      ERROR3=$(grep "500" output |  wc -l)
      SUCCESS_RATE=$(($SUCCESS * 100 / TOTAL))
      ERROR_RATE=$(($ERROR1 * 100 / TOTAL))
      ERROR_RATE_2=$(($ERROR2 * 100 / TOTAL))
      ERROR_RATE_3=$(($ERROR3 * 100 / TOTAL))
      echo "Success rate: $SUCCESS/$TOTAL (${SUCCESS_RATE}%)"
      echo "App network Error rate: $ERROR1/$TOTAL (${ERROR_RATE}%)"
      echo "Resource Error rate: $ERROR2/$TOTAL (${ERROR_RATE_2}%)"
      echo "Redis Error rate: $ERROR3/$TOTAL (${ERROR_RATE_3}%)"
    4. Conceda autorização para executar os scripts:

      chmod u+x generate_load.sh print_error_rate.sh
      
    5. Defina uma variável para o número de CPS. Este valor é usado no script generate_load.sh, tal como a variável que definiu para EXTERNAL_IP. Recomendamos que defina um valor de 40.

      export QPS=40
      
    6. Execute o script generate_load.sh para começar a enviar QPS:

      ./generate_load.sh $IP $QPS 2>&1
      
    7. Deixe o script generate_load.sh em execução e abra um novo terminal. No novo terminal, execute o script print_error_rate.sh para verificar a taxa de erros:

      cd
      cd kubernetes-engine-samples/quickstarts/hello-app-redis/scripts
      watch ./print_error_rate.sh
      

      Deve ver uma taxa de êxito de 100% e taxas de erro de 0% à medida que as QPS são feitas.

    8. Deixe ambos os scripts em execução e abra um terceiro terminal em preparação para a secção seguinte.

    Atualize o cluster

    Para atualizar o cluster, conclua estes passos:

    1. Determine a versão do GKE que o cluster redis-test está a usar:

      V=$(gcloud container clusters describe redis-test | grep "version:" | sed "s/version: //")
      echo $V
      

      Deverá ver uma saída semelhante ao seguinte exemplo: 1.22.9-gke.2000.

    2. Apresente uma lista das versões do Kubernetes disponíveis:

      gcloud container get-server-config
      
    3. Na lista de versões, localize a secção validMasterVersions: e procure a versão redis-test que recuperou no passo anterior. Para evitar violar a política de variação da versão do GKE, escolha uma versão incompatível com os nós. Copie a versão da lista apresentada imediatamente antes da versão redis-test.

    4. Atualize o painel de controlo do cluster para a versão que selecionou e escreva y quando lhe for pedido:

      gcloud container clusters upgrade redis-test \
          --master \
          --cluster-version VERSION
      

      Substitua VERSION pela versão que selecionou na lista no passo anterior.

      A atualização do plano de controlo demora vários minutos.

    5. Atualize os nós do cluster para a versão que selecionou e escreva y quando lhe for pedido:

      gcloud container clusters upgrade redis-test \
          --cluster-version=VERSION \
          --node-pool=default-pool
      

      Substitua VERSION pela versão que selecionou na lista.

    Teste a interrupção da carga de trabalho

    Nesta secção, testa o estado da sua aplicação e observa a interrupção da carga de trabalho.

    1. Regresse à janela do terminal que está a executar ./print_error_rate.sh e observe como a taxa de êxito mudou durante a atualização. Deve notar uma ligeira diminuição na taxa de êxito e um ligeiro aumento na taxa de erros da rede de apps à medida que os nós são desativados para serem atualizados.

      No campo Success rate, vê quantas visitas foram feitas com êxito ao Website. Tome nota deste valor.

    2. Impeça a execução de ambos os scripts introduzindo CTRL+C nos terminais relevantes.

    3. Regresse ao Website da sua aplicação introduzindo o respetivo endereço IP (este é o EXTERNAL_IP que copiou durante a secção Implemente a aplicação cliente Redis) no seu navegador.

    4. Observe o número de visitas da sua aplicação. O número que vê deve ser igual a:

      ORIGINAL_VISIT_NUMBER + SUCCESSFUL_VISIT_NUMBER

      onde ORIGINAL_VISIT_NUMBER é o número que registou no passo final de Implemente a aplicação cliente Redis e SUCCESSFUL_VISIT_NUMBER é o valor que registou no primeiro passo desta secção.

    Limpar

    Depois de concluir o tutorial, pode limpar os recursos que criou para que deixem de usar a quota e incorrer em custos. As secções seguintes descrevem como eliminar ou desativar estes recursos.

    Elimine o projeto

    A forma mais fácil de eliminar a faturação é eliminar o projeto que criou para o tutorial.

    Para eliminar 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.

    Elimine o cluster

    Para eliminar o cluster que criou para este tutorial, execute o seguinte comando:

    gcloud container clusters delete redis-test
    

    O que se segue?