Terraform para iniciantes: infraestrutura como código na prática

1. Introdução ao Terraform e Infraestrutura como Código

Infraestrutura como Código (IaC) é a prática de gerenciar e provisionar recursos de infraestrutura por meio de arquivos de configuração, em vez de processos manuais. O Terraform, desenvolvido pela HashiCorp, é uma ferramenta open-source que adota uma abordagem declarativa: você descreve o estado desejado da infraestrutura, e o Terraform determina as ações necessárias para atingi-lo.

Diferente de ferramentas imperativas (como scripts Ansible ou Shell), onde você especifica cada passo, no Terraform você declara o que quer, não como fazer. Os conceitos fundamentais incluem:

  • Estado (state): arquivo que mapeia os recursos reais para sua configuração
  • Provedores (providers): plugins que permitem interagir com APIs de cloud (AWS, Azure, GCP)
  • Recursos (resources): componentes de infraestrutura que você gerencia (VMs, bancos, redes)

Para instalar, baixe o binário do site oficial da HashiCorp e adicione ao PATH. A autenticação básica na AWS, por exemplo, pode ser feita via variáveis de ambiente:

export AWS_ACCESS_KEY_ID="sua-chave"
export AWS_SECRET_ACCESS_KEY="sua-chave-secreta"

2. Primeiros Passos: Escrevendo e Executando Configurações

Um arquivo .tf segue uma estrutura simples com blocks, arguments e expressões. Veja a estrutura básica:

provider "aws" {
  region = "us-east-1"
}

resource "aws_instance" "meu_servidor" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  tags = {
    Name = "ExemploIniciante"
  }
}

Os comandos essenciais do Terraform são:

  1. terraform init: inicializa o diretório de trabalho, baixa providers
  2. terraform plan: mostra o que será criado/modificado/destruído
  3. terraform apply: executa as mudanças descritas no plano

Exemplo prático: provisionar uma instância EC2 na AWS. Após criar o arquivo main.tf com o conteúdo acima, execute:

terraform init
terraform plan
terraform apply

O Terraform solicitará confirmação. Digite yes e a instância será criada. Para destruir tudo, use terraform destroy.

3. Gerenciamento de Estado e Versionamento

O arquivo de estado (terraform.tfstate) é o coração do Terraform. Ele contém um mapeamento completo dos recursos gerenciados e seus atributos atuais. Esse arquivo é crítico e nunca deve ser editado manualmente.

Para trabalho em equipe, o estado remoto é essencial. No AWS S3, por exemplo:

terraform {
  backend "s3" {
    bucket = "meu-bucket-estado"
    key    = "infra/terraform.tfstate"
    region = "us-east-1"
  }
}

Isso permite que múltiplos membros da equipe compartilhem o mesmo estado, evitando conflitos. O Terraform usa bloqueio de estado (via DynamoDB) para impedir operações simultâneas.

Comandos úteis para gerenciamento de estado:

terraform state list           # Lista todos os recursos no estado
terraform state show <nome>    # Mostra detalhes de um recurso
terraform state rm <nome>      # Remove recurso do estado (não destrói)

4. Variáveis, Outputs e Modularização

Variáveis tornam suas configurações reutilizáveis e flexíveis. Defina variáveis de entrada:

variable "ambiente" {
  description = "Ambiente de deploy"
  type        = string
  default     = "dev"
}

variable "tipo_instancia" {
  type = string
}

Os outputs expõem informações úteis após o apply:

output "ip_publico" {
  value = aws_instance.meu_servidor.public_ip
  description = "IP público da instância"
}

Para ambientes diferentes, use arquivos terraform.tfvars:

# dev.tfvars
ambiente       = "dev"
tipo_instancia = "t2.micro"

# prod.tfvars
ambiente       = "prod"
tipo_instancia = "t2.large"

Execute com: terraform apply -var-file="dev.tfvars"

Módulos permitem organizar infraestrutura complexa. Crie um diretório modules/ e referencie:

module "vpc" {
  source = "./modules/vpc"
  cidr   = "10.0.0.0/16"
  nome   = "minha-vpc"
}

5. Ciclo de Vida e Dependências entre Recursos

O Terraform gerencia automaticamente dependências implícitas quando você referencia um atributo de outro recurso:

resource "aws_vpc" "principal" {
  cidr_block = "10.0.0.0/16"
}

resource "aws_subnet" "publica" {
  vpc_id     = aws_vpc.principal.id   # Dependência implícita
  cidr_block = "10.0.1.0/24"
}

Para dependências explícitas, use depends_on:

resource "aws_instance" "servidor" {
  # ...
  depends_on = [aws_subnet.publica]
}

O bloco lifecycle controla o comportamento durante atualizações:

resource "aws_instance" "critico" {
  # ...
  lifecycle {
    create_before_destroy = true   # Cria novo antes de destruir antigo
    prevent_destroy       = true   # Impede destruição acidental
  }
}

Exemplo completo provisionando VPC, sub-rede e instância:

provider "aws" {
  region = "us-east-1"
}

resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"
  tags = { Name = "VPC-Principal" }
}

resource "aws_subnet" "main" {
  vpc_id     = aws_vpc.main.id
  cidr_block = "10.0.1.0/24"
  tags = { Name = "Subnet-Publica" }
}

resource "aws_instance" "web" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  subnet_id     = aws_subnet.main.id
  tags = { Name = "Servidor-Web" }
}

6. Debugging, Segurança e Boas Práticas

Comandos de depuração essenciais:

terraform validate     # Verifica sintaxe e validade
terraform fmt          # Formata código automaticamente
terraform graph        # Gera grafo de dependências (visualizável com Graphviz)

Para segurança, evite hardcoding de segredos. Use variáveis sensíveis:

variable "db_password" {
  type      = string
  sensitive = true
}

Ou integre com AWS Secrets Manager:

data "aws_secretsmanager_secret" "db" {
  name = "meu-banco"
}

data "aws_secretsmanager_secret_version" "atual" {
  secret_id = data.aws_secretsmanager_secret.db.id
}

Boas práticas incluem:
- Versionar todo código .tf em Git
- Usar workspaces para isolar ambientes: terraform workspace new dev
- Evitar hardcoding de valores (use variáveis)
- Bloquear versões de providers: required_providers com versão fixa

7. Próximos Passos e Integração com CI/CD

Para automatizar deploys, integre o Terraform com pipelines CI/CD. Exemplo com GitHub Actions:

name: Deploy Infraestrutura

on:
  push:
    branches: [ main ]

jobs:
  terraform:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v2
      - name: Terraform Init
        run: terraform init
      - name: Terraform Apply
        run: terraform apply -auto-approve

O comando terraform import permite trazer recursos existentes para o gerenciamento do Terraform:

terraform import aws_instance.existente i-1234567890abcdef0

Para aprofundamento, explore:
- Terraform Cloud: serviço gerenciado com estado remoto, políticas e runs automatizados
- Terraform Registry: repositório oficial de módulos e providers
- HashiCorp Learn: tutoriais interativos gratuitos

O Terraform transforma a maneira como você gerencia infraestrutura, trazendo consistência, rastreabilidade e automação. Comece pequeno, com um recurso simples, e gradualmente expanda para ambientes completos e complexos.

Referências