O problema que o Terraform resolve
Você consegue recriar toda a infraestrutura da sua empresa do zero em menos de uma hora? Se a resposta for não — ou "sim, mas seria um processo estressante e manual" — você tem o problema que o Terraform resolve.
Terraform é uma ferramenta de Infrastructure as Code (IaC) da HashiCorp. A ideia central: você descreve a infraestrutura que quer ter em arquivos de texto, e o Terraform se encarrega de criar, modificar ou destruir recursos na nuvem para corresponder à sua descrição.
O resultado: infraestrutura versionada no Git, reproduzível, auditável e que pode ser revisada em code review como qualquer outro código.
Conceitos fundamentais
Providers
Terraform se comunica com APIs de cloud através de plugins chamados providers. O provider AWS é o mais usado:
terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } } }
provider “aws” { region = “us-east-1” }
Resources
Resources são os blocos de infraestrutura que você quer criar — uma instância EC2, um bucket S3, um banco RDS. Cada resource tem um tipo e um nome local:
resource "aws_s3_bucket" "uploads" { bucket = "minha-empresa-uploads-prod"
tags = { Environment = “production” ManagedBy = “terraform” } }
Variables e Outputs
Variables tornam os módulos reutilizáveis. Outputs expõem valores para outros módulos ou para o terminal:
# variables.tf variable "environment" { description = "Ambiente (dev, staging, prod)" type = string default = "dev" }variable “instance_type” { description = “Tipo da instância EC2” type = string default = “t3.micro” }
outputs.tf
output “bucket_url” { value = aws_s3_bucket.uploads.bucket_domain_name description = “URL pública do bucket de uploads” }
State
O Terraform mantém um arquivo de estado (terraform.tfstate) que mapeia seus recursos declarados para os recursos reais na AWS. É o "mapa" que permite ao Terraform saber o que já existe e o que precisa ser criado ou modificado.
Nunca commite o tfstate no Git. Em equipes, use um backend remoto para armazenar o estado com controle de acesso e lock:
terraform {
backend "s3" {
bucket = "minha-empresa-terraform-state"
key = "prod/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-lock" # evita conflitos concorrentes
}
}
Workflow básico do Terraform
# 1. Inicializa o projeto (baixa providers, configura backend) terraform init2. Valida a sintaxe dos arquivos
terraform validate
3. Mostra o que será criado/modificado/destruído (sem aplicar)
terraform plan
4. Aplica as mudanças na AWS
terraform apply
5. Destroi toda a infraestrutura (cuidado em produção!)
terraform destroy
O terraform plan é seu melhor amigo — sempre revise o output antes de aplicar. Ele mostra exatamente o que vai mudar, com recursos novos marcados com +, modificações com ~ e deleções com -.
Exemplo prático: aplicação web na AWS
Vamos criar uma stack básica: VPC, subnet pública, security group, instância EC2 e Elastic IP.
# vpc.tf resource "aws_vpc" "main" { cidr_block = "10.0.0.0/16" enable_dns_hostnames = truetags = { Name = “main-vpc-${var.environment}” } }
resource “aws_subnet” “public” { vpc_id = aws_vpc.main.id cidr_block = “10.0.1.0/24” availability_zone = “us-east-1a” map_public_ip_on_launch = true
tags = { Name = “public-subnet-${var.environment}” } }
resource “aws_internet_gateway” “main” { vpc_id = aws_vpc.main.id tags = { Name = “igw-${var.environment}” } }
resource “aws_route_table” “public” { vpc_id = aws_vpc.main.id
route { cidr_block = “0.0.0.0/0” gateway_id = aws_internet_gateway.main.id } }
resource “aws_route_table_association” “public” { subnet_id = aws_subnet.public.id route_table_id = aws_route_table.public.id }
# ec2.tf
resource "aws_security_group" "app" {
name = "app-sg-${var.environment}"
vpc_id = aws_vpc.main.id
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_instance" "app" {
ami = "ami-0c02fb55956c7d316" # Amazon Linux 2023
instance_type = var.instance_type
subnet_id = aws_subnet.public.id
vpc_security_group_ids = [aws_security_group.app.id]
user_data = <<-EOF
#!/bin/bash
yum update -y
yum install -y docker
systemctl start docker
systemctl enable docker
EOF
tags = { Name = "app-server-${var.environment}" }
}
resource "aws_eip" "app" {
instance = aws_instance.app.id
domain = "vpc"
}
Módulos: reutilizando infraestrutura
Módulos são o mecanismo de reuso do Terraform — como funções em programação. Você pode criar módulos internos ou usar módulos públicos do Terraform Registry:
# Usando módulo público para VPC module "vpc" { source = "terraform-aws-modules/vpc/aws" version = "~> 5.0"name = “main-vpc” cidr = “10.0.0.0/16”
azs = [“us-east-1a”, “us-east-1b”] private_subnets = [“10.0.1.0/24”, “10.0.2.0/24”] public_subnets = [“10.0.101.0/24”, “10.0.102.0/24”]
enable_nat_gateway = true single_nat_gateway = true # economiza custo em dev
tags = { Environment = var.environment } }
Boas práticas essenciais
Estrutura de diretórios
infra/
├── modules/
│ ├── ec2/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ └── rds/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
├── environments/
│ ├── dev/
│ │ ├── main.tf
│ │ └── terraform.tfvars
│ ├── staging/
│ │ ├── main.tf
│ │ └── terraform.tfvars
│ └── prod/
│ ├── main.tf
│ └── terraform.tfvars
Nunca aplique manualmente em produção
Configure o Terraform para rodar via CI/CD. A cada merge na branch principal, o pipeline executa terraform plan para revisão e, após aprovação, terraform apply. Isso cria um histórico auditável de quem mudou o quê e quando.
Use workspaces para ambientes
# Criar workspace por ambiente terraform workspace new dev terraform workspace new staging terraform workspace new prodSelecionar ambiente
terraform workspace select prod
Referenciar no código
locals { is_prod = terraform.workspace == “prod” }
resource “aws_instance” “app” { instance_type = local.is_prod ? “t3.large” : “t3.micro”
…
}
Por onde começar
O caminho mais seguro para adotar Terraform em um ambiente existente:
- Não tente importar tudo de uma vez. Comece pela infraestrutura nova — qualquer recurso novo que for criar, crie via Terraform.
- Use
terraform importseletivamente para trazer recursos existentes críticos para o state. - Configure o backend remoto desde o início. Tfstate local é o erro mais comum de quem começa.
- Crie um ambiente de dev completo primeiro e valide que o Terraform consegue criar e destruir tudo corretamente antes de aplicar em produção.
Conclusão
Terraform transforma infraestrutura de algo frágil e documentado em Word para algo versionado, testável e reproduzível. O investimento inicial de aprendizado paga dividendos imediatos: onboarding de novos membros mais rápido, disaster recovery confiável e audibilidade completa de mudanças.
Se você está iniciando a jornada de infraestrutura como código ou quer revisar uma implementação Terraform existente, a Neryx tem experiência com Terraform e Terragrunt em ambientes AWS de produção. A consultoria técnica inicial é gratuita.