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:
Terraform em 15 minutos [EN] https://youtu.be/l5k1ai_GBDE
Curso Terraform - Automatize sua Infra em Cloud AWS [EN] 2h30m https://youtu.be/SLB_c_ayRMo
Curso completo para certificação - HashiCorp Terraform Associate Certification [EN] 13h10m https://youtu.be/V4waklkBC38
Terraform: https://www.terraform.io
Terragrunt: https://terragrunt.gruntwork.io
Atlantis: https://runatlantis.io