kb.erickguedes.com
Terraform: Infraestrutura como Código

HCL e Configuração Inicial

Aula 1 de 7

O que é Terraform?

Terraform é uma ferramenta de IaC da HashiCorp que provisiona infraestrutura em múltiplos provedores (AWS, Azure, GCP, etc.) usando HCL (HashiCorp Configuration Language).

terraform {
  required_version = ">= 1.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

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

Primeiro Recurso

resource "aws_s3_bucket" "meu_bucket" {
  bucket = "meu-bucket-terraform-2024"

  tags = {
    Name        = "MeuBucket"
    Environment = "dev"
  }
}

output "bucket_arn" {
  value = aws_s3_bucket.meu_bucket.arn
}
terraform init        # baixa providers
terraform fmt         # formata código
terraform validate    # valida sintaxe
terraform plan        # mostra mudanças
terraform apply       # aplica
terraform destroy     # destrói tudo

Variáveis

# variables.tf
variable "environment" {
  description = "Ambiente (dev/staging/prod)"
  type        = string
  validation {
    condition     = contains(["dev", "staging", "prod"], var.environment)
    error_message = "Ambiente inválido. Use: dev, staging ou prod."
  }
}

variable "instance_type" {
  type    = string
  default = "t3.micro"
}

variable "tags" {
  type = map(string)
  default = {
    ManagedBy = "Terraform"
  }
}

# locals.tf (variáveis locais)
locals {
  name_prefix = "${var.environment}-app"
}
# Passar variáveis
terraform apply -var="environment=prod"
terraform apply -var-file="prod.tfvars"

# Variáveis de ambiente
export TF_VAR_environment=prod

Outputs e Data Sources

# outputs.tf
output "instance_public_ip" {
  value       = aws_instance.web.public_ip
  description = "IP público da instância"
  sensitive   = false
}

output "db_password" {
  value     = random_password.db.result
  sensitive = true  # não aparece no log
}

# data.tf — consultar recursos existentes
data "aws_ami" "ubuntu" {
  most_recent = true
  owners      = ["099720109477"]

  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd-gp3/ubuntu-24.04-amd64-server-*"]
  }
}

State

# Local (padrão): terraform.tfstate
# Remoto (time): S3 + DynamoDB Lock

terraform {
  backend "s3" {
    bucket         = "meu-terraform-state"
    key            = "prod/network/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-locks"
    encrypt        = true
  }
}

Lab: EC2 + Security Group

resource "aws_security_group" "web" {
  name        = "web-sg"
  description = "HTTP + SSH"

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = var.allowed_ssh_ips
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_instance" "web" {
  ami                    = data.aws_ami.ubuntu.id
  instance_type          = var.instance_type
  vpc_security_group_ids = [aws_security_group.web.id]

  user_data = <<-EOF
    #!/bin/bash
    apt update && apt install -y nginx
  EOF

  tags = merge(local.common_tags, {
    Name = "${var.environment}-web"
  })
}

Terraform é declarativo. Você descreve o estado final e o Terraform calcula o plano para chegar lá. O state é seu ativo mais valioso — sempre use backend remoto com lock.