Reduzir os custos diminuindo a escala dos clusters do GKE durante as horas de menor atividade

Last reviewed 2022-11-24 UTC

Este tutorial explica como pode reduzir os custos implementando um escalador automático agendado no Google Kubernetes Engine (GKE). Este tipo de dimensionamento automático dimensiona os clusters para cima ou para baixo de acordo com um horário baseado na hora do dia ou no dia da semana. Um escalador automático programado é útil se o seu tráfego tiver um fluxo previsível. Por exemplo, se for um retalhista regional ou se o seu software for para funcionários cujo horário de trabalho esteja limitado a uma parte específica do dia.

Este tutorial destina-se a programadores e operadores que querem aumentar de forma fiável os clusters antes da chegada de picos e reduzi-los novamente para poupar dinheiro à noite, aos fins de semana ou em qualquer outra altura em que haja menos utilizadores online. O artigo pressupõe que conhece o Docker, o Kubernetes, os Kubernetes CronJobs, o GKE e o Linux.

Introdução

Muitas aplicações têm padrões de tráfego irregulares. Por exemplo, os trabalhadores de uma organização podem interagir com uma aplicação apenas durante o dia. Como resultado, os servidores do centro de dados para essa aplicação ficam inativos à noite.

Além de outras vantagens, Google Cloud pode ajudar a poupar dinheiro ao alocar dinamicamente a infraestrutura de acordo com a carga de tráfego. Em alguns casos, uma configuração de ajuste automático simples pode gerir o desafio de alocação de tráfego desigual. Se for o seu caso, continue a usá-la. No entanto, noutros casos, as alterações acentuadas nos padrões de tráfego requerem configurações de escalamento automático mais ajustadas para evitar a instabilidade do sistema durante os aumentos de escala e evitar o aprovisionamento excessivo do cluster.

Este tutorial centra-se em cenários em que as alterações acentuadas nos padrões de tráfego são bem compreendidas e quer dar sugestões ao escalador automático de que a sua infraestrutura está prestes a sofrer picos. Este documento mostra como aumentar a escala dos clusters do GKE de manhã e diminuí-la à noite, mas pode usar uma abordagem semelhante para aumentar e diminuir a capacidade para quaisquer eventos conhecidos, como eventos de escala de picos, campanhas publicitárias ou tráfego de fim de semana.

Reduzir a escala de um cluster se tiver descontos de fidelidade

Este tutorial explica como reduzir os custos ao diminuir a escala dos clusters do GKE para o mínimo durante as horas de menor atividade. No entanto, se tiver comprado um desconto por utilização garantida, é importante compreender como estes descontos funcionam em conjunto com o dimensionamento automático.

Os contratos de fidelização oferecem-lhe preços significativamente reduzidos quando se compromete a pagar por uma quantidade definida de recursos (vCPUs, memória e outros). No entanto, para determinar a quantidade de recursos a comprometer, tem de saber antecipadamente quantos recursos as suas cargas de trabalho usam ao longo do tempo. Para ajudar a reduzir os custos, o diagrama seguinte ilustra os recursos que deve e não deve incluir no seu planeamento.

Distribuição de recursos, mostrando uma base de recursos comprometidos que são sempre atribuídos e recursos que são dimensionados automaticamente em resposta à procura (picos).

Conforme mostra o diagrama, a atribuição de recursos ao abrigo de um contrato de utilização comprometida é constante. Os recursos abrangidos pelo contrato têm de estar em utilização na maior parte do tempo para valerem o compromisso que assumiu. Por conseguinte, não deve incluir recursos usados durante picos no cálculo dos recursos comprometidos. Para recursos com picos, recomendamos que use as opções de escalamento automático do GKE. Estas opções incluem o escalador automático agendado abordado neste artigo ou outras opções geridas abordadas no artigo Práticas recomendadas para executar aplicações Kubernetes otimizadas em termos de custos no GKE.

Se já tiver um contrato de utilização garantida para uma determinada quantidade de recursos, não reduz os custos ao reduzir a escala do cluster abaixo desse mínimo. Nestes cenários, recomendamos que tente agendar alguns trabalhos para preencher as lacunas durante períodos de baixa procura de computação.

Arquitetura

O diagrama seguinte mostra a arquitetura da infraestrutura e do escalador automático agendado que implementa neste tutorial. O redimensionador automático agendado consiste num conjunto de componentes que funcionam em conjunto para gerir o redimensionamento com base num agendamento.

Arquitetura que mostra os componentes que, em conjunto, formam o escalador automático agendado.

Nesta arquitetura, um conjunto de CronJobs do Kubernetes exporta informações conhecidas sobre padrões de tráfego para uma métrica personalizada do Cloud Monitoring. Estes dados são, em seguida, lidos por um Horizontal Pod Autoscaler (HPA) do Kubernetes como entrada para quando o HPA deve dimensionar a sua carga de trabalho. Juntamente com outras métricas de carga, como a utilização da CPU alvo, o HPA decide como dimensionar as réplicas para uma determinada implementação.

Objetivos

  • Crie um cluster do GKE.
  • Implemente uma aplicação de exemplo que use um HPA do Kubernetes.
  • Configure os componentes para o escalador automático agendado e atualize o HPA para ler a partir de uma métrica personalizada agendada.
  • Configure um alerta para ser acionado quando o escalador automático agendado não estiver a funcionar corretamente.
  • Gerar carga para a aplicação.
  • Examine a forma como o HPA responde aos aumentos normais no tráfego e às métricas personalizadas agendadas que configurar.

O código deste tutorial está num repositório do GitHub.

Custos

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

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

Os novos Google Cloud utilizadores podem ser elegíveis 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.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator (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, Artifact Registry and the Cloud Monitoring APIs.

    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 APIs

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

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator (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, Artifact Registry and the Cloud Monitoring APIs.

    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 APIs

Prepare o seu ambiente

  1. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

  2. No Cloud Shell, configure o Google Cloud ID do projeto, o endereço de email e a zona e a região de computação:

    PROJECT_ID=YOUR_PROJECT_ID
    ALERT_EMAIL=YOUR_EMAIL_ADDRESS
    gcloud config set project $PROJECT_ID
    gcloud config set compute/region us-central1
    gcloud config set compute/zone us-central1-f
    

    Substitua o seguinte:

    • YOUR_PROJECT_ID: o nome do Google Cloud projeto para o projeto que está a usar.
    • YOUR_EMAIL_ADDRESS: um endereço de email para receber uma notificação quando o escalador automático agendado não estiver a funcionar corretamente.

    Pode escolher uma região e uma zona diferentes para este tutorial, se quiser.

  3. Clone o kubernetes-engine-samplesrepositório do GitHub:

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples/
    cd kubernetes-engine-samples/cost-optimization/gke-scheduled-autoscaler
    

    O código neste exemplo está estruturado nas seguintes pastas:

    • Root: contém o código usado pelos CronJobs para exportar métricas personalizadas para o Cloud Monitoring.
    • k8s/: contém um exemplo de implementação com um HPA do Kubernetes.
    • k8s/scheduled-autoscaler/: contém os CronJobs que exportam uma métrica personalizada e uma versão atualizada do HPA para ler a partir de uma métrica personalizada.
    • k8s/load-generator/: contém uma implementação do Kubernetes que tem uma aplicação para simular a utilização por hora. Uma implementação é um objeto da API Kubernetes que lhe permite executar várias réplicas de pods distribuídas entre os nós num cluster.
    • monitoring/: contém os componentes do Cloud Monitoring que configura neste tutorial.
  4. Crie o cluster do GKE

    1. No Cloud Shell, crie um cluster do GKE para executar o redimensionador automático agendado:

      gcloud container clusters create scheduled-autoscaler \
          --enable-ip-alias \
          --release-channel=stable \
          --machine-type=e2-standard-2 \
          --enable-autoscaling --min-nodes=1 --max-nodes=10 \
          --num-nodes=1 \
          --autoscaling-profile=optimize-utilization
      

      O resultado é semelhante ao seguinte:

      NAME                   LOCATION       MASTER_VERSION   MASTER_IP      MACHINE_TYPE   NODE_VERSION     NUM_NODES  STATUS
      scheduled-autoscaler   us-central1-f  1.22.15-gke.100  34.69.187.253  e2-standard-2  1.22.15-gke.100  1          RUNNING
      

      Esta não é uma configuração de produção, mas é uma configuração adequada para este tutorial. Nesta configuração, configura o dimensionamento automático do cluster com um mínimo de 1 nó e um máximo de 10 nós. Também ativa o perfil optimize-utilization para acelerar o processo de redução da escala.

    Implemente a aplicação de exemplo

    1. Implemente a aplicação de exemplo sem o escalador automático agendado:

      kubectl apply -f ./k8s
      
    2. Abra o ficheiro k8s/hpa-example.yaml.

      A lista seguinte mostra o conteúdo do ficheiro.

      spec:
        maxReplicas: 20
        minReplicas: 10
        scaleTargetRef:
          apiVersion: apps/v1
          kind: Deployment
          name: php-apache
        metrics:
        - type: Resource
          resource:
            name: cpu
            target:
              type: Utilization
              averageUtilization: 60

      Repare que o número mínimo de réplicas (minReplicas) está definido como 10. Esta configuração também define o cluster para ser dimensionado com base na utilização da CPU (as definições name: cpu e type: Utilization).

    3. Aguarde até que a aplicação fique disponível:

      kubectl wait --for=condition=available --timeout=600s deployment/php-apache
      EXTERNAL_IP=''
      while [ -z $EXTERNAL_IP ]
      do
          EXTERNAL_IP=$(kubectl get svc php-apache -o jsonpath={.status.loadBalancer.ingress[0].ip})
          [ -z $EXTERNAL_IP ] && sleep 10
      done
      curl -w '\n' http://$EXTERNAL_IP
      

      Quando a aplicação está disponível, o resultado é o seguinte:

      OK!
      
    4. Verifique as definições:

      kubectl get hpa php-apache
      

      O resultado é semelhante ao seguinte:

      NAME         REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
      php-apache   Deployment/php-apache   9%/60%    10        20        10         6d19h
      

      A coluna REPLICAS apresenta 10, que corresponde ao valor do campo minReplicas no ficheiro hpa-example.yaml.

    5. Verifique se o número de nós aumentou para 4:

      kubectl get nodes
      

      O resultado é semelhante ao seguinte:

      NAME                                                  STATUS   ROLES    AGE   VERSION
      gke-scheduled-autoscaler-default-pool-64c02c0b-9kbt   Ready    <none>   21S   v1.17.9-gke.1504
      gke-scheduled-autoscaler-default-pool-64c02c0b-ghfr   Ready    <none>   21s   v1.17.9-gke.1504
      gke-scheduled-autoscaler-default-pool-64c02c0b-gvl9   Ready    <none>   21s   v1.17.9-gke.1504
      gke-scheduled-autoscaler-default-pool-64c02c0b-t9sr   Ready    <none>   21s   v1.17.9-gke.1504
      

      Quando criou o cluster, definiu uma configuração mínima através da flag min-nodes=1. No entanto, a aplicação que implementou no início deste procedimento está a pedir mais infraestrutura porque minReplicas no ficheiro hpa-example.yaml está definido como 10.

      Definir minReplicas para um valor como 10 é uma estratégia comum usada por empresas como retalhistas, que esperam um aumento repentino no tráfego nas primeiras horas do dia útil. No entanto, definir valores elevados para o HPA minReplicas pode aumentar os custos porque o cluster não pode diminuir, nem mesmo à noite, quando o tráfego da aplicação é baixo.

    Configure um escalador automático programado

    1. No Cloud Shell, instale o adaptador de métricas personalizadas do Cloud Monitoring no seu cluster do GKE:

      kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml
      kubectl wait --for=condition=available --timeout=600s deployment/custom-metrics-stackdriver-adapter -n custom-metrics
      

      Este adaptador permite o dimensionamento automático de pods com base em métricas personalizadas do Cloud Monitoring.

    2. Crie um repositório no Artifact Registry e conceda autorizações de leitura:

      gcloud artifacts repositories create gke-scheduled-autoscaler \
        --repository-format=docker --location=us-central1
      gcloud auth configure-docker us-central1-docker.pkg.dev
      gcloud artifacts repositories add-iam-policy-binding gke-scheduled-autoscaler \
         --location=us-central1 --member=allUsers --role=roles/artifactregistry.reader
      
    3. Crie e envie o código do exportador de métricas personalizadas:

      docker build -t us-central1-docker.pkg.dev/$PROJECT_ID/gke-scheduled-autoscaler/custom-metric-exporter .
      docker push us-central1-docker.pkg.dev/$PROJECT_ID/gke-scheduled-autoscaler/custom-metric-exporter
      
    4. Implemente os CronJobs que exportam métricas personalizadas e implemente a versão atualizada do HPA que lê a partir destas métricas personalizadas:

      sed -i.bak s/PROJECT_ID/$PROJECT_ID/g ./k8s/scheduled-autoscaler/scheduled-autoscale-example.yaml
      kubectl apply -f ./k8s/scheduled-autoscaler
      
    5. Abra e examine o ficheiro k8s/scheduled-autoscaler/scheduled-autoscale-example.yaml.

      A lista seguinte mostra o conteúdo do ficheiro.

      apiVersion: batch/v1
      kind: CronJob
      metadata:
        name: scale-up
      spec:
        schedule: "50-59/1 * * * *"
        jobTemplate:
          spec:
            template:
              spec:
                containers:
                - name: custom-metric-extporter
                  image: us-central1-docker.pkg.dev/PROJECT_ID/gke-scheduled-autoscaler/custom-metric-exporter
                  command:
                    - /export
                    - --name=scheduled_autoscaler_example
                    - --value=10
                restartPolicy: OnFailure
            backoffLimit: 1
      ---
      apiVersion: batch/v1
      kind: CronJob
      metadata:
        name: scale-down
      spec:
        schedule: "1-49/1 * * * *"
        jobTemplate:
          spec:
            template:
              spec:
                containers:
                - name: custom-metric-extporter
                  image: us-central1-docker.pkg.dev/PROJECT_ID/gke-scheduled-autoscaler/custom-metric-exporter
                  command:
                    - /export
                    - --name=scheduled_autoscaler_example
                    - --value=1
                restartPolicy: OnFailure
            backoffLimit: 1

      Esta configuração especifica que os CronJobs devem exportar a contagem de réplicas de pods sugeridas para uma métrica personalizada denominada custom.googleapis.com/scheduled_autoscaler_example com base na hora do dia. Para facilitar a secção de monitorização deste tutorial, a configuração do campo de programação define aumentos e diminuições por hora. Para produção, pode personalizar esta programação de acordo com as necessidades da sua empresa.

    6. Abra e examine o ficheiro k8s/scheduled-autoscaler/hpa-example.yaml.

      A seguinte lista mostra o conteúdo do ficheiro.

      spec:
        maxReplicas: 20
        minReplicas: 1
        scaleTargetRef:
          apiVersion: apps/v1
          kind: Deployment
          name: php-apache
        metrics:
        - type: Resource
          resource:
            name: cpu
            target:
              type: Utilization
              averageUtilization: 60
        - type: External
          external:
            metric:
              name: custom.googleapis.com|scheduled_autoscaler_example
            target:
                type: AverageValue
                averageValue: 1

      Esta configuração especifica que o objeto HPA deve substituir o HPA implementado anteriormente. Tenha em atenção que a configuração reduz o valor em minReplicas para 1. Isto significa que a carga de trabalho pode ser reduzida ao mínimo. A configuração também adiciona uma métrica externa (type: External). Esta adição significa que o ajuste de escala automático é agora acionado por dois fatores.

      Neste cenário de várias métricas, o HPA calcula uma quantidade de réplicas proposta para cada métrica e, em seguida, escolhe a métrica que devolve o valor mais elevado. É importante compreender que o escalador automático agendado pode propor que, num determinado momento, o número de pods deve ser 1. No entanto, se a utilização real da CPU for superior ao esperado para um pod, o HPA cria mais réplicas.

    7. Verifique novamente o número de nós e réplicas do HPA executando novamente cada um dos seguintes comandos:

      kubectl get nodes
      kubectl get hpa php-apache
      

      O resultado que vê depende do que o escalador automático agendado fez recentemente. Em particular, os valores de minReplicas e nodes serão diferentes em diferentes pontos do ciclo de escalamento.

      Por exemplo, aproximadamente entre os minutos 51 e 60 de cada hora (que representam um período de pico de tráfego), o valor de HPA para minReplicas é 10 e o valor de nodes é 4.

      Por outro lado, para os minutos 1 a 50 (que representam um período de tráfego mais baixo), o valor de HPA minReplicas é 1 e o valor de nodes é 1 ou 2, consoante o número de agrupamentos que foram atribuídos e removidos. Para os valores mais baixos (minutos 1 a 50), o cluster pode demorar até 10 minutos a concluir a redução da escala.

    Configure alertas para quando o redimensionador automático agendado não estiver a funcionar corretamente

    Num ambiente de produção, normalmente, quer saber quando os CronJobs não estão a preencher a métrica personalizada. Para este efeito, pode criar um alerta que é acionado quando qualquer stream custom.googleapis.com/scheduled_autoscaler_example está ausente durante um período de cinco minutos.

    1. No Cloud Shell, crie um canal de notificação:

      gcloud beta monitoring channels create \
          --display-name="Scheduled Autoscaler team (Primary)" \
          --description="Primary contact method for the Scheduled Autoscaler team lead"  \
          --type=email \
          --channel-labels=email_address=${ALERT_EMAIL}
      

      O resultado é semelhante ao seguinte:

      Created notification channel NOTIFICATION_CHANNEL_ID.
      

      Este comando cria um canal de notificação do tipo email para simplificar os passos do tutorial. Em ambientes de produção, recomendamos que use uma estratégia menos assíncrona definindo o canal de notificação como sms ou pagerduty.

    2. Defina uma variável que tenha o valor apresentado no marcador de posição NOTIFICATION_CHANNEL_ID:

      NOTIFICATION_CHANNEL_ID=NOTIFICATION_CHANNEL_ID
      
    3. Implemente a política de alerta:

      gcloud alpha monitoring policies create \
          --policy-from-file=./monitoring/alert-policy.yaml \
          --notification-channels=$NOTIFICATION_CHANNEL_ID
      

      O ficheiro alert-policy.yaml contém a especificação para enviar um alerta se a métrica estiver ausente após cinco minutos.

    4. Aceda à página Alertas do Cloud Monitoring para ver a política de alertas.

      Aceder a Alertas

    5. Clique em Política de escalamento automático agendado e valide os detalhes da política de alerta.

    Gere carga para a aplicação de exemplo

    • No Cloud Shell, implemente o gerador de carga:

      kubectl apply -f ./k8s/load-generator
      

      A listagem seguinte mostra o script load-generator:

      command: ["/bin/sh", "-c"]
      args:
      - while true; do
          RESP=$(wget -q -O- http://php-apache.default.svc.cluster.local);
          echo "$(date +%H)=$RESP";
          sleep $(date +%H | awk '{ print "s("$0"/3*a(1))*0.5+0.5" }' | bc -l);
        done;
      

      Este script é executado no seu cluster até eliminar a implementação load-generator Envia pedidos ao seu serviço php-apache a cada poucos milissegundos. O comando sleep simula alterações na distribuição de carga durante o dia. Ao usar um script que gera tráfego desta forma, pode compreender o que acontece quando combina a utilização da CPU e as métricas personalizadas na configuração do HPA.

    Visualize o escalamento em resposta ao tráfego ou a métricas agendadas

    Nesta secção, reveja as visualizações que lhe mostram os efeitos do aumento e da diminuição da escala.

    1. No Cloud Shell, crie um novo painel de controlo:

      gcloud monitoring dashboards create \
          --config-from-file=./monitoring/dashboard.yaml
      
    2. Aceda à página Painéis de controlo do Cloud Monitoring:

      Aceder a Painéis de controlo

    3. Clique em Painel de controlo do escalador automático agendado.

      O painel de controlo apresenta três gráficos. Tem de aguardar, pelo menos, 2 horas (idealmente, 24 horas ou mais) para ver a dinâmica dos aumentos e das diminuições, e para ver como a distribuição de carga diferente durante o dia afeta o ajuste automático.

      Para ter uma ideia do que os gráficos mostram, pode estudar os seguintes gráficos, que apresentam uma vista de dia inteiro:

      • Métrica agendada (n.º desejado de pods) mostra uma série cronológica da métrica personalizada que está a ser exportada para o Cloud Monitoring através de CronJobs que configurou em Configurar um escalador automático agendado.

        Gráfico da procura de pods, que mostra um pico a cada hora.

      • Utilização da CPU (pedida vs. usada) mostra uma série cronológica da CPU pedida (vermelho) e da utilização real da CPU (azul). Quando a carga é baixa, o HPA respeita a decisão de utilização do escalador automático programado. No entanto, quando o tráfego aumenta, o HPA aumenta o número de pods conforme necessário, como pode ver nos pontos de dados entre as 12:00 e as 18:00.

        Gráfico da utilização da CPU, que mostra o crescimento da procura durante o dia até às 16:00 e, em seguida, a diminuição.

      • Número de pods (agendados vs. reais) + utilização média da CPU mostra uma vista semelhante às anteriores. A contagem de agrupamentos (vermelho) aumenta para 10 a cada hora, conforme agendado (azul). O número de pods aumenta e diminui naturalmente ao longo do tempo em resposta à carga (12:00 e 18:00). A utilização média da CPU (laranja) permanece abaixo do objetivo que definiu (60%).

        2 gráficos. Um mostra a procura de agrupamentos com picos de procura a cada hora. O outro mostra que a utilização da CPU sobe e desce, mas atinge o valor elevado configurado.

Limpar

Para evitar incorrer em custos na sua conta do Google Cloud pelos recursos usados neste tutorial, elimine o projeto que contém os recursos ou mantenha o projeto e elimine os recursos individuais.

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

O que se segue?