Introdução ao Terraform, terragrunt e Atlantis

Introdução ao Terraform, terragrunt e Atlantis

Uma apresentação introdutória ao Infrastructure As A Code (IaaC), Atlantis, HCL, Terragrunt e outros.

Hi!

Comecei a usar o terraform em 2018, em sua versão 0.10.algumacoisa, ano seguinte, desenvolvi um curso (pensei em colocar em alguma plataforma online, a venda), mas com a mudança da syntax que viria, acabei deixando de lado essa ideia... Veio a versão 0.12, tempo passou e desisti por falta de tempo.

Porém, tempos atrás (2022) fiz um treinamento de 1 hora introdutório para Terraform, contemplando no final um breve apanhado sobre as ferramentas Terragrunt e Atlantis. Infelizmente, não posso subir o treinamento (youtube) devido ter sido apenas interno e usado/discutido pontos particulares dos times e do ambiente em especifico como exemplo.

Deixo aqui o PDF e o PPTX usado nos treinamentos, bem como o link para download ;-)

Edite-o, use-o livremente.

Não está 100% explicativo, pois são os slides que eu seguia durante as explicações, mas para usar num material complementar é excelente.

Infra como código

A infraestrutura como código (IaC) configura e gerencia a infraestrutura por meio de um modelo descritivo. Trata-se de tratar a configuração e o provisionamento de sua infraestrutura da mesma maneira que você trata o código-fonte do aplicativo.

Os módulos de configuração são normalmente armazenados em sistemas de controle de versão em formatos de código bem documentados, proporcionando maior precisão, reduzindo erros e aumentando a velocidade e a consistência.

A IaC é uma das práticas de DevOps mais importantes usadas com entrega contínua. Os benefícios que levam muitas empresas a migrar para o IAC são infraestrutura imutável, aumento na velocidade de entrega, escalabilidade, economia de custos e mitigação de riscos.

Alguns nomes:

Terraform
Ansible
AWS CDK
Chef
Puppet
SaltStack
(R)?ex
Vagrant
Crossplane
Juju
CFEngine
Pallet
NixOS
Dagger
Packer

"Alternativas" ao Terraform:

  • Attune

  • Pulumi

Alternativas para ambientes específicos:

  • AWS CloudFormation

  • Azure Resource Manager

  • Google Cloud Deployment Manager

Libs para criar infra usando SDK/API e sua linguagem favorita (The Hard Way):

  • Boto (python)

  • Fog (Ruby)

Terraform

É uma ferramenta de IaaC open-source criada pela HashiCorp usando uma linguagem de configuração declarativa conhecida como HashiCorp Configuration Language (HCL) e JSON.

  • Escrito em Go

  • Declarativo

https://github.com/hashicorp/terraform

O Terraform possui quatro comandos principais:

terraform init

terraform plan

terraform apply

terraform destroy

Usage: terraform [global options] <subcommand> [args]


Main commands:
 init          Prepare your working directory for other commands
 validate      Check whether the configuration is valid
 plan          Show changes required by the current configuration
 apply         Create or update infrastructure
 destroy       Destroy previously-created infrastructure

All other commands:
 console       Try Terraform expressions at an interactive command prompt
 fmt           Reformat your configuration in the standard style
 force-unlock  Release a stuck lock on the current workspace
 get           Install or upgrade remote Terraform modules
 graph         Generate a Graphviz graph of the steps in an operation
 import        Associate existing infrastructure with a Terraform resource
 login         Obtain and save credentials for a remote host
 logout        Remove locally-stored credentials for a remote host
 output        Show output values from your root module
 providers     Show the providers required for this configuration
 refresh       Update the state to match remote systems
 show          Show the current state or a saved plan
 state         Advanced state management
 taint         Mark a resource instance as not fully functional
 test          Experimental support for module integration testing
 untaint       Remove the 'tainted' state from a resource instance
 version       Show the current Terraform version
 workspace     Workspace management

Problemas resolvidos:

Infraestrutura como código

regra n1 - 12factor: Uma base de código com rastreamento utilizando controle de revisão

Estado remoto

Um time consegue trabalhar simultaneamente no desenvolvimento da Infra.

Lock no Apply

Não irá ocorrer conflitos ao executar em paralelo.

https://registry.terraform.io/browse/providers - + 2000 providers no registry público (Oficial, verificado e community).

Terraform’s Configuration Language

A linguagem do Terraform é declarativa, descrevendo um objetivo pretendido em vez das etapas para atingir esse objetivo.

No paradigma de programação declarativo, declaro o que eu quero como resultado final ao invés de escrever como eu quero (o passo-a-passo para obtê-lo).

Declarativo: Erlang, Haskell, SQL - abstrato - Linguagem Funcional

Imperativo: C, C++, Java - concreto - Linguagem Procedural

Ambos: Python, C#, JavaScript - Linguagem Orientada a Objeto

A ordenação dos blocos e os arquivos em que são organizados geralmente não são significativos;

O Terraform considera apenas relacionamentos implícitos e explícitos entre recursos ao determinar a ordem de operações.

Os blocos são contêineres para outros conteúdos e geralmente representam a configuração de algum tipo de objeto, como um recurso (resource).

Os blocos têm um type, podem ter zero ou mais labels e um corpo que contém argumentos e blocos aninhados.

A maioria dos recursos do Terraform são controlados por blocos de nível superior em um arquivo de configuração.

Os argumentos atribuem um valor a um nome.

As expressões representam um valor, literalmente ou referenciando e combinando outros valores. Eles aparecem como valores para argumentos ou dentro de outras expressões.

terraform {
    backend "s3" {
        bucket = "iaac-terraform"
        key = "tfstates/project-iaac/terraform.tfstate"
        region = "sa-east-1"
        profile = "default"
        dynamodb_table = "terraform_state_table"
       encrypt = "true"
    }


  provider "aws" {
        credential= "~/.aws/credentials"
        region= "sa-east-1"
   }

}

resource "aws_route53_record" "www" {
  zone_id = Z001753YB9D130HADG3
  name    = "www.example.com"
  type    = "A"
  ttl     = "300"
  records = example.alb.us-east-1.amazonaws.com
}

Separando os valores/variáveis do exemplo acima (route53.tf):

resource "aws_route53_record" "www" {
  zone_id = var.zone_id
  name    = var.name
  type    = "A"
  ttl     = "300"
  records = var.records
}

Arquivo de variáveis (variables.tf):

variables "name" {
  default = "www.example.com"
}

variables "zone_id" {
  default = "Z001753YB9D130HADG3"
}

variables "records" {
  default = "example.alb.us-east-1.amazonaws.com"
}

Ou, separando mais ainda, em 3 arquivos:

Modules

Com o módulo, o bloco com o resource já está escrito e versionado no git.

Apenas será necessário escrever as variáveis e apontar para o terraform, onde está o source do módulo.

Pode ser local (outro diretório), registry do terraform, git, bucket S3, …/

module "instance" {
  source = "git@github.com:cloudposse/ec2-instance.git"

  ssh_key_pair                = var.ssh_key_pair
  instance_type               = var.instance_type
  vpc_id                      = var.vpc_id
  security_groups             = var.security_groups
  subnet                      = var.subnet
  name                        = "ec2"
  namespace                   = "eg"
  stage                       = "dev"
}

Modules (usar ou não)? DRY - Don't Repeat Yourself

Sem modules:

resource "aws_route53_record" "www" {
  zone_id = var.zone_id
  name    = var.name
  type    = "A"
  ttl     = "300"
  records = var.records
}
variables "name" {
  default = "www.example.com"
}

variables "zone_id" {
  default = "Z001753YB9D130HADG3"
}

variables "records" {
  default = "example.alb.us-east-1.amazonaws.com"
}

Mesmo recurso, sendo criado usando modulo já pronto, centralizado num git:

module "route53" {
  source = "git@github.com:Esl1h/tfmodules/r53.git"

  name    = "www.example.com"
  zone_id = "Z001753YB9D130HADG3"
  records = "example.alb.us-east-1.amazonaws.com"
}

Usando modulos, se resolve mais um problema:

Não reinventa a roda e Padroniza!

Usar módulos não gasta tempo escrevendo um resource que já foi feito em outros momentos.

Workspace

Na execução do terraform, para cada backend, será criado dados persistentes. Eles são armazenados e consultados.

Como, numa segunda execução (development e depois production) os dados não são sobrescritos?

Estes dados persistentes pertencem a um environment (chamado de workspace)

Para production, por exemplo, podemos criar o workspace:

terraform workspace new production terraform workspace select production

Para posteriormente executar o init/plan/apply:

terraform init --backend-config=backend.production.tfvars --var-file=dev.tfvars

terraform plan --var-file=production.tfvars terraform apply --var-file=production.tfvars

Poderia criar uma pasta para cada ambiente? E ter um código terraform para cada um?

Sim, mas....

Regra número 10 do 12factor: Mantenha o desenvolvimento, teste, produção o mais semelhante possível.

Links e referências:

Did you find this article valuable?

Support Esli Silva by becoming a sponsor. Any amount is appreciated!