Descobrindo os custos da sua infraestrutura utilizando Infracost

Descobrindo os custos da sua infraestrutura utilizando Infracost

Introdução

Um dos maiores problemas na jornada de uma empresa quando decide migrar seu ambiente e aplicações para a Cloud é: Quanto vai custar? 💸

Temos algumas formas de calcular e ter uma previsão dos gastos em nuvem utilizado as calculadoras dos próprios providers, porém, na minha visão a forma mais interessante de ter uma previsão de custos é utilizando o infracost.io.

O que é o Infracost? 💰

O Infracost é uma ferramenta utilizada junto com o seu Terraform, ou seja, você terá uma previsão de quanto a sua infraestrutura vai custar assim que executar o terraform plan no seu projeto.

Alguns benefícios ao utilizar o Infracost:

  • Maior conscientização sobre custos: Os engenheiros recebem antecipadamente o custo estimado da infraestrutura, antes que quaisquer recursos sejam lançados ou alterados. Eles podem fazer escolhas econômicas enquanto mantêm a velocidade de entrega de software.
  • Visibilidade de custo para equipes de plataforma: O impacto de custo de módulos compartilhados que são usados em muitas equipes pode ser avaliado pelas equipes de plataforma.
  • Retrabalho de infraestrutura reduzido: O Infracost integrado a sua pipeline CI/CD fornece as informações necessárias para tomar as decisões corretas. Os orçamentos não são quebrados e menos retrabalho é necessário para consertar a infraestrutura para alinhar com os orçamentos após o lançamento.
  • Orçamentos e custos alinhados: Se as mudanças na infraestrutura ou o lançamento de um novo produto quebrarem os orçamentos, a comunicação pode acontecer antecipadamente, não após a chegada da fatura.

Mão na massa 💻

Neste laboratório vamos utilizar o projeto que criamos no artigo: Pipeline IaC com Terraform e GitHub Actions. Se você não acompanhou o post anterior faça o clone do projeto: git clone https://github.com/santospedroh/iac-pipeline.git.

Vamos alterar o workflow do GitHub Action para adicionar os recursos do Infracost, assim vamos poder analisar quando o terraform plan for executado quais os custos da nossa infraestrutura.

##Instalação e configuração do CLI 🛠 O Infracost tem uma documentação bem completa e simples com Get started super legal. No meu caso estou utilizando um MacOS e vou fazer a instalação utilizando o gerenciador de pacotes Homebrew.

➜  iac-pipeline git:(main) brew install infracost

Após a instalação você precisa criar uma API KEY para o Infracost gerar os custos estimados da infraestrutura, será necessário executar o comando infracost register e informa seu nome e e-mail para gerar a API KEY.

➜  iac-pipeline git:(main) infracost register
Please enter your name and email address to get an API key.
See our FAQ (https://www.infracost.io/docs/faq) for more details.
Name: Pedro Santos
Email: santos.pedroh@gmail.com

Thanks Pedro Santos! Your API key is: <SUA_API_KEY_VAI_APARECER_AQUI>
This was saved to /Users/santospedroh/.config/infracost/credentials.yml

Follow https://infracost.io/docs to use Infracost.

Agora já podemos executar o Infracost e verificar a estimativa de custos do projeto Terraform utilizando o comando infracost breakdown --path . para gerar a estimativa de custos direto no terminal.

➜  iac-pipeline git:(main) ✗ infracost breakdown --path .
Evaluating Terraform directory at .
  ✔ Downloading Terraform modules 
  ✔ Evaluating Terraform directory 
  ✔ Retrieving cloud prices to calculate costs 

Project: santospedroh/iac-pipeline/.

 Name                                                 Monthly Qty  Unit   Monthly Cost 

 module.ec2_instance.aws_instance.this[0]                                              
 ├─ Instance usage (Linux/UNIX, on-demand, t3.micro)          730  hours         $7.59 
 └─ root_block_device                                                                  
    └─ Storage (general purpose SSD, gp2)                       8  GB            $0.80 

 OVERALL TOTAL                                                                   $8.39 
──────────────────────────────────
10 cloud resources were detected:
∙ 1 was estimated, it includes usage-based costs, see https://infracost.io/usage-file
∙ 9 were free, rerun with --show-skipped to see details

Também podemos alterar o formato o qual as informações de custos são exibidas. Para gerar um arquivo html por exemplo, utilize o comando infracost breakdown --path . --format html > infracost.html um arquivo html vai ser criado.

Mais detalhes sobre os formatos pode ser verificados na documentação.

➜  iac-pipeline git:(main) infracost breakdown --path . --format html > infracost.html
Evaluating Terraform directory at .
  ✔ Downloading Terraform modules 
  ✔ Evaluating Terraform directory 
  ✔ Retrieving cloud prices to calculate costs

➜  iac-pipeline git:(main) ✗ ls -ltr *.html
-rw-r--r--  1 santospedroh  staff  16269  6 Jul 16:09 infracost.html

Arquivo HTML com a previsão de custos do projeto.

Infracost html Podemos ver que o custo da infraestrutura atual utilizando uma instância t3.micro é de $8.39

Integração com o GitHub Action 🤖

Agora chegou o momento de integrarmos o Infracost com o nosso workflow no GitHub Action para recebemos os valores estimados direto nas Pull Request's que forem criadas. O primeiro passo para a integração é criar uma secret da sua API KEY do Infracost no repositório do projeto, assim como fizemos no artigo anterior.

Infracost secret Vamos utilizar o Infracost Actions oficial como referência para editar o nosso workflow plan.yml que já temos em nosso projeto.

name: "Plan"

on:
  pull_request:

env:
  AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
  AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

jobs:
  terraform:
    name: "Terraform"
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v1
        with:
          terraform_version: 0.15.5

      - name: Terraform Init
        id: init
        run: terraform init

      - name: Terraform Validate
        id: validate
        run: terraform validate -no-color

       # Aqui vamos gerar o terraform plan em arquivo para passar para o infracost
      - name: Terraform Plan
        id: plan
        run: terraform plan -out tfplan.binary

      - name: Terraform show
        id: show
        run: terraform show -json tfplan.binary > plan.json
        working-directory: ${{ env.working-directory }}

      - uses: actions/github-script@v6
        if: github.event_name == 'pull_request'
        env:
          PLAN: "terraform\n${{ steps.plan.outputs.stdout }}"
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const output = `#### Terraform Format and Style 🖌\`${{ steps.fmt.outcome }}\`
            #### Terraform Initialization ⚙️\`${{ steps.init.outcome }}\`
            #### Terraform Validation 🤖\`${{ steps.validate.outcome }}\`
            #### Terraform Plan 📖\`${{ steps.plan.outcome }}\`
            <details><summary>Show Plan</summary>
            \`\`\`\n
            ${process.env.PLAN}
            \`\`\`
            </details>
            *Pushed by: @${{ github.actor }}, Action: \`${{ github.event_name }}\`*`;
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: output
            })
      - name: Terraform Plan Status
        if: steps.plan.outcome == 'failure'
        run: exit 1

      # Chamar a action do infracost passando a nossa secret
      - name: Setup Infracost
        uses: infracost/actions/setup@v1
        with:
          api-key: ${{ secrets.INFRACOST_API_KEY }}

      # Passar o arquivo plan.json para o infracost gerar os custos
      - name: Generate Infracost JSON
        run: infracost breakdown --path plan.json --format json --out-file /tmp/infracost.json

      - name: Infracost Actions
        uses: infracost/actions/comment@v1
        with:
          path: /tmp/infracost.json
          behavior: update

Enviando um Pull Request para alteração da infraestrutura 📈

Agora vamos simular um aumento da capacidade computacional com 2 instâncias EC2, atualmente estamos utilizando apenas uma instância do tipo t3.micro que tem 2 vCPU e 1GB de memória RAM e vamos para 2 instâncias do tipo m5.large que tem 2 vCPU e 4GB de memória RAM.

Vamos criar uma nova branch no projeto com o nome infracost para fazer as alterações e enviar o Pull Request.

➜  iac-pipeline git:(main) git checkout -b infracost
Switched to a new branch 'infracost'
➜  iac-pipeline git:(infracost)

Atualizar o arquivo main.ft com as novas instâncias do tipo m5.large

module "ec2_instance" {
  source = "terraform-aws-modules/ec2-instance/aws"

  for_each = toset(["server-01", "server-02"]) # Duas instâncias ec2

  name                   = "snake-game-${each.key}"
  ami                    = "ami-0cff7528ff583bf9a"
  instance_type          = "m5.large" # Tipo das instâncias m5.large
  vpc_security_group_ids = [aws_security_group.game_snake_sg.id]
  subnet_id              = module.vpc.public_subnets[0]
  user_data              = file("userdata.sh")
  tags = {
    Name = "snake-game-ec2"
    Terraform = "true"
    Environment = "prod"
    Team = "gamer-development"
    Application = "snake-game"
    Language = "javascript"
  }
}

Vamos fazer o commit e o push e criar o Pull Request no GitHub

➜  iac-pipeline git:(infracost)  git add .
➜  iac-pipeline git:(infracost)  git commit -m "Infra com 2 instancias do tipo m5.large"
[infracost 1d900e7] Infra com 2 instancias do tipo m5.large
 4 files changed, 28 insertions(+), 10 deletions(-)
 create mode 100644 .terraform.lock.hcl
➜  iac-pipeline git:(infracost) git push origin infracost                              
Enumerating objects: 14, done.
Counting objects: 100% (14/14), done.
Delta compression using up to 12 threads
Compressing objects: 100% (7/7), done.
Writing objects: 100% (8/8), 1.59 KiB | 1.59 MiB/s, done.
Total 8 (delta 4), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (4/4), completed with 4 local objects.
To github.com:santospedroh/iac-pipeline.git
   8e2c8e8..1d900e7  infracost -> infracost

Após a execução do workflow plan podemos ver nos comentários do Pull Request a estimativa de custo do Infracost.

Infracost PR O valor da nova infra ficou estimado em $142

Conclusão

Utilizando o Infracost dificilmente você vai ter surpresas ao receber a fatura do seu cloud provider, podemos saber a estimativa de custo de cada projeto Terraform, podemos avaliar e discutir os valores em cada Pull Request enviada podendo aprovar ou não o Merge para a branch principal do projeto antes de qualquer mudança ser aplicada.

Todos esses benefícios ajudam bastante no dia a dia de um time que utiliza as práticas DevOps e FinOps.

Espero que tenha gostado desse hands-on, aproveitem bem o Infracost, até a próxima! ✌🏼