Estime seus custos do GKE no início do ciclo de desenvolvimento usando o GitLab


Neste tutorial, você verá a prática recomendada de mudar a visibilidade dos custos do Google Kubernetes Engine (GKE) para sua equipe de desenvolvimento usando o GitLab. A criação de reconhecimento de custos no início do processo de desenvolvimento ajuda você a evitar surpresas na sua fatura do Google Cloud. Mover uma tarefa ou informação para uma parte anterior de um processo às vezes é chamado de mudança para a esquerda.

Este tutorial é destinado a desenvolvedores, operadores e profissionais do FinOps que querem otimizar os custos nos clusters do GKE e que usam o GitLab na produção. Se você usa o GitHub, consulte Estimar os custos do GKE no início do ciclo de desenvolvimento usando o GitHub.

Neste tutorial, presumimos que você esteja familiarizado com as tecnologias a seguir:

Visão geral

Muitas equipes que estão adotando a nuvem pública não são adotadas no estilo de faturamento de pagamento por utilização. Muitas vezes, eles não entendem completamente o ambiente em que os aplicativos estão sendo executados. Neste caso, o GKE. O modelo operacional FinOps promove essa cultura de responsabilidade financeira. Uma prática recomendada do FinOps é fornecer às equipes informações em tempo real sobre os gastos, de modo que os problemas de custos possam ser tratados quando surgirem.

Neste documento, mostramos como dar um passo além, estimando o custo antes de se tornar uma despesa na sua fatura. Conforme destacado no site do GitLab, "A revisão de código é uma prática essencial de todos os projetos bem-sucedidos. Conceder sua aprovação quando uma solicitação de mesclagem estiver em boa forma é uma parte importante do processo de revisão." Dessa forma, o melhor momento para estimar custos é no início do processo durante o desenvolvimento e no momento da revisão do código. Os profissionais podem entender e discutir alternativas para o impacto de custo de novos recursos e correções de bugs antes que se torne um problema. O diagrama a seguir resume essa prática.

Prática recomendada para estimar custos antecipadamente.

Como o diagrama mostra, os desenvolvedores podem estimar os custos do GKE no ambiente local, idealmente no momento da criação. Essa estimativa fornece um bom entendimento do custo mensal da carga de trabalho de produção. Quando o recurso ou a correção do bug é concluído pelo código, eles podem propor uma solicitação de mesclagem que aciona um pipeline de CI/CD do GitLab (links em inglês). para verificar a diferença entre o custo antigo e o novo. Se houver aumentos acima de um limite predefinido, o pipeline solicitará automaticamente uma nova revisão de código. Essa prática ajuda os desenvolvedores a se familiarizarem com a capacidade de carga de trabalho e a corrigir proativamente problemas de aplicativos em vez de adicionar mais recursos sempre que uma instabilidade for encontrada na produção.

Objetivos

  • Crie e envie a imagem do estimador de custo do Kubernetes.
  • Crie um novo projeto do GitLab.
  • Configure o executor do GitLab para ser executado em um cluster do GKE.
  • Envie o código de exemplo para seu repositório do GitLab.
  • Altere o código e proponha uma solicitação de mescla para ver a estimativa de custo em ação.

Custos

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

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.

Ao concluir as tarefas descritas neste documento, é possível evitar o faturamento contínuo excluindo os recursos criados. Saiba mais em Limpeza.

Antes de começar

  1. No console do Google Cloud, acesse a página do seletor de projetos.

    Acessar o seletor de projetos

  2. Selecione ou crie um projeto do Google Cloud.

  3. Verifique se a cobrança está ativada para o seu projeto do Google Cloud.

  4. No Console do Google Cloud, ative o Cloud Shell.

    Ativar o Cloud Shell

    Na parte inferior do Console do Google Cloud, uma sessão do Cloud Shell é iniciada e exibe um prompt de linha de comando. O Cloud Shell é um ambiente shell com a CLI do Google Cloud já instalada e com valores já definidos para o projeto atual. A inicialização da sessão pode levar alguns segundos.

Como preparar o ambiente

  1. No Cloud Shell, clone o repositório gke-shift-left-cost do GitHub:

    git clone https://github.com/GoogleCloudPlatform/gke-shift-left-cost
    cd gke-shift-left-cost
    

    O código nesse repositório está estruturado nas seguintes pastas:

    • Raiz: contém um arquivo Dockerfile usado para criar a imagem do estimador de custos e o arquivo main.go que implementa a lógica de linha de comando para o estimador de custos.
    • api/: contém a API Go para manipular objetos do Kubernetes e fazer a estimativa de custo.
    • samples/: contém exemplos de manifestos do Kubernetes para que você possa testar o processo antes de implementá-lo na sua organização.
  2. Defina o ID do projeto do Cloud e a conta de usuário e o endereço de e-mail do GitLab:

    export GCP_PROJECT_ID=YOUR_PROJECT_ID
    export GITLAB_USER=YOUR_GITLAB_USER
    export GITLAB_EMAIL=YOUR_GITLAB_EMAIL_ADDRESS
    
    gcloud config set project $GCP_PROJECT_ID
    
    gcloud services enable cloudbilling.googleapis.com \
        compute.googleapis.com \
        container.googleapis.com \
        iamcredentials.googleapis.com \
        artifactregistry.googleapis.com
    
    gcloud config set compute/region us-central1
    gcloud config set compute/zone us-central1-f
    

    Substitua:

  • YOUR_PROJECT_ID : o ID do projeto do Cloud que você está usando neste tutorial.
  • YOUR_GITLAB_USER : a conta de usuário que você usa para fazer login na sua conta do GitLab.
  • YOUR_GITLAB_EMAIL_ADDRESS: o e-mail que você usa na sua conta do GitLab.

Como opção, você pode usar uma região e uma zona diferentes neste tutorial.

Como criar e enviar a imagem do estimador de custo do Kubernetes

A ferramenta de estimativa de custo do Kubernetes que acompanha este tutorial é um exemplo do que pode ser feito. Ele oferece a capacidade de estimar custos para objetos DaemonSet, Deployment, StatefulSet, ReplicaSet, HorizontalPodAutoScaler e PersistentVolumeClaim Kubernetes. Também é possível implementar sua própria ferramenta de estimativa de custos ou propor solicitações de envio com as melhorias que quiser.

  1. No Cloud Shell, permita que application-default use suas credenciais:

    gcloud auth application-default login
    
  2. Crie o binário do estimador de custo do Kubernetes:

    mkdir ./bin
    go test ./api
    go build -v -o ./bin/k8s-cost-estimator .
    
  3. Execute uma estimativa de custo em uma pasta de amostra para testar o binário:

    ./bin/k8s-cost-estimator \
        --k8s ./samples/k8s-cost-estimator-local/app-v1  \
        --config ./samples/k8s-cost-estimator-local/example-conf.yaml \
        --v trace
    

    Na saída, você verá uma tabela do Markdown que detalha os custos mensais estimados para a pasta ./samples/k8s-cost-estimator-local/app-v1/. Para entender melhor o custo de produção mensal dos aplicativos, os desenvolvedores podem executar essa etapa antes de enviar o code para o repositório remoto.

    INFO[0000] Starting cost estimation (version v0.0.1)...
    ...
    
    |         KIND          | MIN REQUESTED (USD) | MIN REQ + HPA CPU BUFFER (USD) | MAX REQUESTED (USD) | MIN LIMITED (USD) | MAX LIMITED (USD) |
    |-----------------------|---------------------|--------------------------------|---------------------|-------------------|-------------------|
    | Deployment            |             $133.31 |                        $198.71 |             $266.54 |           $312.83 |           $579.29 |
    | StatefulSet           |              $36.33 |                         $36.33 |              $36.33 |            $72.67 |            $72.67 |
    | DaemonSet             |              $29.68 |                         $29.68 |              $29.68 |            $53.19 |            $53.19 |
    | PersistentVolumeClaim |              $28.88 |                         $28.88 |              $28.88 |            $33.68 |            $33.68 |
    | **TOTAL**             |         **$228.20** |                    **$293.60** |         **$361.43** |       **$472.38** |       **$738.83** |
    
    INFO[0002] Finished cost estimation!
    
  4. Crie a imagem do contêiner do Estimador de custos do Kubernetes:

    docker build . -t \
    us-central1-docker.pkg.dev/$GCP_PROJECT_ID/docker-repo/k8s-cost-estimator:v0.0.1
    
  5. Crie o repositório do Docker do Artifact Registry para armazenar a imagem:

    gcloud artifacts repositories create docker-repo \
            --repository-format=docker \
            --location=us-central1 \
            --description="Docker repository"
    
  6. Registre gcloud como o auxiliar de credencial para o arquivo de configuração do Docker.

    gcloud auth configure-docker us-central1-docker.pkg.dev
    

    Se solicitado, confirme a atualização do arquivo.

  7. Envie a imagem para o Artifact Registry:

    docker push us-central1-docker.pkg.dev/$GCP_PROJECT_ID/docker-repo/k8s-cost-estimator:v0.0.1
    

Como criar um novo projeto do GitLab

  1. No Cloud Shell, altere o diretório para o exemplo do GitLab:

    cd samples/k8s-cost-estimator-gitlab
    
  2. Crie um token de acesso na página Tokens de acesso pessoal do GitLab:

    Navegue até a página Tokens de acesso pessoal do GitLab.

    1. No campo Nome, digite o nome do token que você está criando.
    2. No campo Escopo, selecione api e clique em Criar token de acesso pessoal.
    3. Copie o valor do Seu novo token de acesso pessoal.
  3. No Cloud Shell, salve o token de acesso pessoal em uma variável:

    GITLAB_API_TOKEN=YOUR_NEW_PERSONAL_ACCESS_TOKEN
    

    Substitua:

    • YOUR_NEW_PERSONAL_ACCESS_TOKEN: o token de acesso pessoal do GitLab que você criou.
  4. Crie um novo projeto do GitLab:

    GITLAB_PROJECT_OUTPUT=$(curl -X POST -H "content-type:application/json" -H "PRIVATE-TOKEN:$GITLAB_API_TOKEN" -d '{"name":"k8s-cost-estimator-gitlab","visibility":"public"}'        https://gitlab.com/api/v4/projects)
    GITLAB_PROJECT_ID=$(echo $GITLAB_PROJECT_OUTPUT | jq ".id")
    GITLAB_FINOPS_REVIEWER_ID=$(echo $GITLAB_PROJECT_OUTPUT | jq ".owner.id")
    
  5. Defina as variáveis da ferramenta do estimador de custo a ser usada quando uma solicitação de mesclagem for criada:

    curl -X POST -H "content-type:application/json" -H "PRIVATE-TOKEN:$GITLAB_API_TOKEN" -d "{\"key\": \"GITLAB_API_TOKEN\",\"value\": \"$GITLAB_API_TOKEN\", \"masked\":\"true\"}" https://gitlab.com/api/v4/projects/$GITLAB_PROJECT_ID/variables
    
    curl -X POST -H "content-type:application/json" -H "PRIVATE-TOKEN:$GITLAB_API_TOKEN" -d "{\"key\": \"GITLAB_FINOPS_REVIEWER_ID\",\"value\": \"$GITLAB_FINOPS_REVIEWER_ID\"}" https://gitlab.com/api/v4/projects/$GITLAB_PROJECT_ID/variables
    
    curl -X POST -H "content-type:application/json" -H "PRIVATE-TOKEN:$GITLAB_API_TOKEN" -d "{\"key\": \"GITLAB_FINOPS_COST_USD_THRESHOLD\",\"value\": \"10\"}" https://gitlab.com/api/v4/projects/$GITLAB_PROJECT_ID/variables
    
  6. Verifique se o projeto e as variáveis foram criados:

    curl -s --header "PRIVATE-TOKEN:$GITLAB_API_TOKEN" \
    https://gitlab.com/api/v4/projects/$GITLAB_PROJECT_ID/variables | jq
    

    A saída será assim:

    [
      {
        "variable_type": "env_var",
        "key": "GITLAB_API_TOKEN",
        "value": "Ex...n1",
        "protected": false,
        "masked": true,
        "environment_scope": "*"
      },
      {
        "variable_type": "env_var",
        "key": "GITLAB_FINOPS_REVIEWER_ID",
        "value": "88..87",
        "protected": false,
        "masked": false,
        "environment_scope": "*"
      },
      {
        "variable_type": "env_var",
        "key": "GITLAB_FINOPS_COST_USD_THRESHOLD",
        "value": "10",
        "protected": false,
        "masked": false,
        "environment_scope": "*"
      }
    ]
    

    As variáveis configuradas no projeto do GitLab são usadas pelo arquivo ./samples/k8s-cost-estimator-gitlab/templates/.gitlab-ci.yml.tpl para atualizar solicitações de mesclagem e são as seguintes:

    • GITLAB_API_TOKEN: seu token de acesso pessoal do GitLab.
    • GITLAB_FINOPS_REVIEWER_ID: o revisor do código necessário sempre que o custo aumenta acima de um determinado limite. Para simplificar, este tutorial define seu próprio ID de usuário como revisor. No entanto, em um ambiente de produção, recomendamos que você configure uma equipe em vez de uma pessoa individual.
    • GITLAB_FINOPS_COST_USD_THRESHOLD: o limite em USD, neste caso, US$ 10. Quando a diferença entre custos antigos e novos ultrapassar esse limite, uma aprovação extraordinária será aplicada. Também é possível definir limites para outros valores. Para explorar esse recurso, anexe o parâmetro --output ao executar o comando ./bin/k8s-cost-estimator em Como criar e enviar a imagem do estimador de custos do Kubernetes. Um parâmetro gera um arquivo com uma extensão .diff, que permite visualizar as opções disponíveis.

Como configurar o executor do GitLab para ser executado em um cluster do GKE

Nesta seção, você instalará o executor do GitLab no seu próprio cluster do GKE com a Identidade da carga de trabalho, permitindo que a ferramenta Estimator do Kubernetes consulte o catálogo de preços do Google Cloud. O estimador usa preços brutos e não considera VMs preemptivas nem descontos.

  1. No Cloud Shell, crie um cluster do GKE:

    gcloud beta container clusters create gitlab-runners \
        --enable-ip-alias \
        --release-channel=stable \
        --workload-pool=$GCP_PROJECT_ID.svc.id.goog \
        --enable-autoprovisioning --min-cpu 1 --min-memory 1 --max-cpu 4 --max-memory 16 \
        --autoscaling-profile=optimize-utilization \
        --preemptible
    
  2. Consiga o token de registro do executor do GitLab do projeto que você criou:

    export GITLAB_RUNNER_TOKEN=$(curl -s --header "PRIVATE-TOKEN:$GITLAB_API_TOKEN" https://gitlab.com/api/v4/projects/$GITLAB_PROJECT_ID | jq -r '.runners_token')
    [ -z "$GITLAB_RUNNER_TOKEN" ] && echo "GITLAB_RUNNER_TOKEN is not exported" || echo "GITLAB_RUNNER_TOKEN is $GITLAB_RUNNER_TOKEN"
    
  3. Instale o executor do GitLab no cluster do GKE:

    kubectl create namespace gitlab
    
    helm repo add gitlab https://charts.gitlab.io
    
    sed "s/GCP_PROJECT_ID/$GCP_PROJECT_ID/g; s/GITLAB_RUNNER_TOKEN/$GITLAB_RUNNER_TOKEN/g" templates/gitlab-runner-values.yaml.tpl > gitlab-runner-values.yaml
    
    helm install --namespace gitlab --version 0.24.0 gitlab-runner -f gitlab-runner-values.yaml gitlab/gitlab-runner
    
    kubectl -n gitlab wait --for=condition=available deployment gitlab-runner --timeout=5m
    
    gcloud iam service-accounts create gitlab-runner --display-name=gitlab-runner
    gcloud iam service-accounts add-iam-policy-binding \
        --role roles/iam.workloadIdentityUser \
        --member "serviceAccount:$GCP_PROJECT_ID.svc.id.goog[gitlab/gitlab-runner]" \
        gitlab-runner@$GCP_PROJECT_ID.iam.gserviceaccount.com
    
  4. Desative os executores compartilhados no projeto do GitLab:

    curl -s --header "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}" -X PUT "https://gitlab.com/api/v4/projects/$GITLAB_PROJECT_ID" --form "shared_runners_enabled=false"
    
  5. Verifique se o executor implantado está ativado no projeto do GitLab:

    curl -s --header "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}" "https://gitlab.com/api/v4/projects/$GITLAB_PROJECT_ID/runners?status=active" | jq '.[] | select(.is_shared==false)'
    

    A saída será assim:

    {
        "id": 49345561,
        "description": "gitlab-runner-gitlab-runner-788459d488-jlscn",
        "ip_address": "35.178.223.199",
        "active": true,
        "is_shared": false,
        "name": "gitlab-runner",
        "online": true,
        "status": "online"
    }
    

Como enviar o código de exemplo para seu repositório do GitLab

  1. Crie um par de chaves SSH para enviar o código de amostra ao repositório do GitLab:

    mkdir -p ssh && cd ssh
    ssh-keygen -t rsa -b 4096 -N '' -f gitlab-key
    eval `ssh-agent` && ssh-add $(pwd)/gitlab-key
    curl -s --request POST --header "PRIVATE-TOKEN:$GITLAB_API_TOKEN" https://gitlab.com/api/v4/user/keys --form "title=k8s-cost-estimator-key" --form "key=$(cat gitlab-key.pub)"
    cd ..
    
  2. Envie o conteúdo para o novo repositório do GitLab:

    sed "s/GCP_PROJECT_ID/$GCP_PROJECT_ID/g; s/GITLAB_USER/$GITLAB_USER/g; s/GITLAB_EMAIL/$GITLAB_EMAIL/g;" templates/.gitlab-ci.yml.tpl > .gitlab-ci.yml
    
    GITLAB_SSH_URL_REPO=$(curl -s --header "PRIVATE-TOKEN:$GITLAB_API_TOKEN" https://gitlab.com/api/v4/users/$GITLAB_FINOPS_REVIEWER_ID/projects | jq '.[] | select(.name=="k8s-cost-estimator-gitlab")' | jq -r '.ssh_url_to_repo')
    [ -z "$GITLAB_SSH_URL_REPO" ] && echo "GITLAB_PROJECT_SSH_URL is not exported" || echo "GITLAB_PROJECT_SSH_URL is $GITLAB_SSH_URL_REPO"
    
    git init
    git remote add origin $GITLAB_SSH_URL_REPO
    git add -A .
    git commit -m "Initial commit"
    git checkout -b main
    git push -u origin main
    

Como alterar o código e propor uma solicitação de mesclagem para ver a estimativa de custo em ação

  1. No Cloud Shell, consiga o URL do ambiente de desenvolvimento integrado (IDE, na sigla em inglês) do GitLab:

    echo "https://gitlab.com/-/ide/project/$GITLAB_USER/k8s-cost-estimator-gitlab/tree/main/-/wordpress/wordpress_hpa.yaml"
    
  2. Pressione + Ctrl + clique (Cmd + clique no macOS) o URL de saída para navegar no ambiente de desenvolvimento integrado do GitLab na Web.

  3. No ambiente de desenvolvimento integrado da Web do GitLab, edite o arquivo ./wordpress/wordpress_hpa.yaml da seguinte maneira:

    1. Altere o valor minReplicas de 2 para 5.
    2. Clique em Confirmar.
  4. Conforme mostrado na captura de tela a seguir, selecione Criar uma nova ramificação, Iniciar uma nova solicitação de mesclagem e clique em Confirmar.

    Inicie uma solicitação de mesclagem.

  5. Na tela Nova solicitação de mesclagem, clique em Criar solicitação de mesclagem na parte inferior da página.

    Além de criar uma nova solicitação de mesclagem, esta etapa aciona um pipeline de estimativa de custos com base no arquivo .gitlab-ci.yml. Esse pipeline usa a imagem de contêiner que você criou em uma seção anterior. Esse pipeline também determina quando uma aprovação no FinOps é necessária. Para simplificar, .gitlab-ci.yml adiciona aprovações para cada base de solicitação de mesclagem, mas é possível definir e reutilizar regras de aprovações definidas no nível do projeto do GitLab (em inglês).

  6. Aguarde cerca de um minuto para que o pipeline seja concluído. Quando esse processo for concluído, um comentário com detalhes de custo será adicionado à solicitação de mesclagem. Como o aumento no custo do código que você está propondo excede o limite de US $10, um revisor FinOps também é solicitado.

    A saída será assim:

    Comentário com detalhes do custo na solicitação de mesclagem.

    Neste tutorial, a configuração padrão é usada para aprovações de solicitações de mesclagem. É possível selecionar diferentes configurações para suas solicitações de mesclagem no Gitlab. Por exemplo, para impedir que o autor aprove solicitações de mesclagem, acesse Configurações > Geral > Aprovações de solicitação de mesclagem (MR) > Configurações de aprovação.

Limpar

Para evitar cobranças na sua conta do Google Cloud pelos recursos usados neste tutorial, exclua o projeto.

Exclua o projeto

  1. No Console do Google Cloud, acesse a página Gerenciar recursos.

    Acessar "Gerenciar recursos"

  2. Na lista de projetos, selecione o projeto que você quer excluir e clique em Excluir .
  3. Na caixa de diálogo, digite o ID do projeto e clique em Encerrar para excluí-lo.

Excluir o projeto do GitLab

Se você não quiser manter seu projeto do GitLab, faça o seguinte:

  1. No Cloud Shell, exclua seu projeto do GitLab:

     curl -X DELETE -H "content-type:application/json" -H "PRIVATE-TOKEN:$GITLAB_API_TOKEN" https://gitlab.com/api/v4/projects/$GITLAB_PROJECT_ID
    

    A saída será assim: {"message":"202 Accepted"}

    Se você perder a conexão com o Cloud Shell, precisará definir as variáveis a seguir novamente:

    • GITLAB_API_TOKEN
    • GITLAB_PROJECT_ID

A seguir