O Terraform é uma ferramenta de infraestrutura como código (IaC) que permite definir e provisionar infraestrutura de forma declarativa. Nesta aula, vamos nos aprofundar nos conceitos de recursos, variáveis e outputs, que são a base para qualquer configuração do Terraform. Você aprenderá a criar recursos, parametrizar suas configurações com variáveis e expor informações úteis com outputs. Além disso, teremos uma visão geral de módulos e boas práticas para manter seu código limpo e reutilizável.

Vamos explorar cada tópico com exemplos práticos, focando em provedores como AWS, mas os conceitos se aplicam a qualquer provedor suportado. Ao final, você terá uma base sólida para criar seus próprios projetos com Terraform.

Recursos

Recursos são os blocos fundamentais do Terraform. Eles representam componentes de infraestrutura, como máquinas virtuais, redes, bancos de dados, etc. Cada recurso é declarado com o tipo e um nome lógico, e possui argumentos que configuram suas propriedades. A sintaxe básica é:

resource "tipo" "nome" {
argumento1 = valor1
argumento2 = valor2
# ...
}

Por exemplo, para criar uma instância EC2 na AWS, usamos o recurso aws_instance. O nome lógico é usado para referenciar o recurso em outros lugares da configuração. O Terraform mantém um estado que mapeia os recursos declarados com os recursos reais na infraestrutura.

Os argumentos podem ser simples, como strings e números, ou podem ser blocos aninhados (como tags). É importante entender que alguns argumentos são obrigatórios e outros opcionais, dependendo do tipo de recurso. A documentação de cada provedor lista todos os argumentos suportados.

Exemplo de recurso:

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

Quando você executa terraform apply, o Terraform cria esse recurso no provedor. Se você modificar o código e aplicar novamente, o Terraform atualiza o recurso para refletir o novo estado desejado. Isso é chamado de gerenciamento de ciclo de vida.

Além de recursos, o Terraform também possui data sources (fontes de dados) que permitem consultar informações existentes, mas isso está fora do escopo desta aula.

Variáveis e outputs

Variáveis tornam suas configurações parametrizáveis e reutilizáveis. Em vez de hardcodar valores, você define variáveis que podem ser fornecidas de diferentes formas: via arquivo terraform.tfvars, variáveis de ambiente, linha de comando ou interativamente. Isso facilita o uso da mesma configuração em diferentes ambientes (dev, staging, prod).

A declaração de uma variável usa o bloco variable:

variable "instance_type" {
description = "Tipo da instância EC2"
type = string
default = "t2.micro"
}

Você pode definir o tipo (string, number, bool, list, map, etc.) e um valor padrão. Se não houver padrão, o usuário deve fornecer o valor. Para usar a variável em um recurso, basta referenciá-la com var.<nome>:

resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = var.instance_type
}

Outputs servem para expor informações sobre sua infraestrutura após a aplicação, como IPs, IDs, endpoints. Isso é útil para passar informações a outros sistemas ou para o usuário visualizar. A sintaxe é:

output "public_ip" {
value = aws_instance.web.public_ip
}

Após o terraform apply, o output aparece no console e pode ser consultado com terraform output. Outputs também podem ser usados por módulos para expor valores.

Exemplo completo com variável e output:

variable "instance_type" {
default = "t2.micro"
}

resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = var.instance_type
}

output "instance_id" {
value = aws_instance.web.id
}

Para fornecer valores às variáveis, você pode criar um arquivo terraform.tfvars com o conteúdo:

instance_type = "t3.small"

Ou usar a flag -var no comando: terraform apply -var="instance_type=t3.small".

Módulos (visão geral)

Módulos são contêineres para múltiplos recursos que são usados juntos. Eles permitem organizar seu código em partes reutilizáveis, facilitando a manutenção e a colaboração. Um módulo pode ser local (uma pasta com arquivos .tf) ou remoto (de um registro público como o Terraform Registry).

A estrutura básica de um módulo é um diretório contendo arquivos de configuração. O módulo pode ter variáveis de entrada, outputs e recursos. Para usá-lo, você declara um bloco module na configuração raiz:

module "web" {
source = "./modules/web"
instance_type = "t2.micro"
}

O Terraform baixa o módulo (se remoto) e cria todos os recursos definidos nele. Módulos são uma ótima maneira de compartilhar infraestrutura comum entre projetos e equipes.

Nesta aula, focamos na visão geral; em aulas futuras, você aprenderá a criar seus próprios módulos em detalhes.

Boas práticas

Escrever código Terraform de qualidade envolve seguir algumas boas práticas. Primeiro, use variáveis para valores que mudam entre ambientes e evite hardcodar. Isso torna a configuração flexível e segura, pois evita expor dados sensíveis no código.

Segundo, organize seus arquivos de forma lógica. Você pode dividir a configuração em vários arquivos .tf, como main.tf, variables.tf, outputs.tf. Isso melhora a legibilidade e a manutenção.

Terceiro, utilize módulos para encapsular componentes comuns, como redes ou clusters. Isso reduz duplicação e promove consistência.

Quarto, sempre documente suas variáveis e outputs com descrições. Isso ajuda outros usuários a entender o propósito de cada item.

Quinto, use o comando terraform fmt para formatar o código automaticamente e terraform validate para verificar a sintaxe. Essas ferramentas mantêm o código padronizado.

Por fim, considere usar o backend remoto para armazenar o estado, permitindo colaboração em equipe e bloqueio de concorrência.

Exercícios

  1. Crie um recurso aws_s3_bucket com o nome meu-bucket-teste e tags de ambiente. Use uma variável para o nome do bucket.
  2. Defina uma variável regiao do tipo string com valor padrão us-east-1 e use-a no provedor AWS.
  3. Crie um output que exiba o ARN de uma instância EC2 que você criou.
  4. Escreva um módulo local simples que cria uma instância EC2 com uma variável de entrada ami e um output id.
  5. Explique a diferença entre terraform plan e terraform apply no contexto de variáveis.

✓ Resposta:
variable "bucket_name" {
description = "Nome do bucket S3"
type = string
}

resource "aws_s3_bucket" "meu_bucket" {
bucket = var.bucket_name
tags = {
Ambiente = "dev"
}
}

✓ Resposta:
variable "regiao" {
description = "Região da AWS"
type = string
default = "us-east-1"
}

provider "aws" {
region = var.regiao
}

✓ Resposta:
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
}

output "instance_arn" {
value = aws_instance.web.arn
}

✓ Resposta: Estrutura do módulo em ./modules/web:
# variables.tf
variable "ami" {
description = "AMI da instância"
type = string
}

# main.tf
resource "aws_instance" "this" {
ami = var.ami
instance_type = "t2.micro"
}

# outputs.tf
output "id" {
value = aws_instance.this.id
}

Na raiz:
module "web" {
source = "./modules/web"
ami = "ami-0c55b159cbfafe1f0"
}

output "web_id" {
value = module.web.id
}

✓ Resposta: terraform plan mostra as mudanças que serão feitas sem aplicá-las, permitindo revisar o que será criado, modificado ou destruído. Ele usa as variáveis fornecidas para calcular o plano. terraform apply executa o plano, criando ou atualizando a infraestrutura. As variáveis são usadas da mesma forma, mas o apply pode pedir confirmação antes de prosseguir.

Referências