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

Workspaces e Ambientes

Aula 6 de 7

Workspaces na Prática

Workspaces permitem gerenciar múltiplos ambientes (dev/staging/prod) com o mesmo código.

# Usar workspace para diferenças entre ambientes
locals {
  env_config = {
    dev = {
      instance_type = "t3.micro"
      min_size      = 1
      max_size      = 2
    }
    staging = {
      instance_type = "t3.small"
      min_size      = 2
      max_size      = 4
    }
    prod = {
      instance_type = "t3.large"
      min_size      = 3
      max_size      = 10
    }
  }

  config = local.env_config[terraform.workspace]
}

resource "aws_autoscaling_group" "app" {
  min_size = local.config.min_size
  max_size = local.config.max_size
  # ...
}

resource "aws_instance" "app" {
  instance_type = local.config.instance_type
  # ...
}

Estratégia de Nomenclatura

locals {
  name_prefix = "${var.project}-${terraform.workspace}"
}

resource "aws_s3_bucket" "logs" {
  bucket = "${local.name_prefix}-logs"  # "meu-projeto-dev-logs"
}

resource "aws_ecs_service" "app" {
  name = "${local.name_prefix}-app"
  # ...
}

Terragrunt — Gerenciamento de Configuração

Terragrunt é um wrapper que elimina duplicação em ambientes multi-módulo.

# terragrunt.hcl (raiz)
remote_state {
  backend = "s3"
  config = {
    bucket         = "tg-state"
    key            = "${path_relative_to_include()}/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "tg-locks"
    encrypt        = true
  }
}

generate "provider" {
  path      = "provider.tf"
  if_exists = "overwrite_terragrunt"
  contents = <<EOF
provider "aws" {
  region = "us-east-1"
}
EOF
}
# dev/network/terragrunt.hcl
terraform {
  source = "../../modules//network"
}

inputs = {
  vpc_cidr    = "10.0.0.0/16"
  environment = "dev"
}
terragrunt run-all plan
terragrunt run-all apply

Diretório por Ambiente

.
├── modules/
│   ├── vpc/
│   ├── ec2/
│   └── rds/
├── dev/
│   ├── network/
│   │   ├── main.tf
│   │   └── terraform.tfvars
│   ├── app/
│   │   ├── main.tf
│   │   └── terraform.tfvars
│   └── terragrunt.hcl
├── staging/
│   └── ...
└── prod/
    └── ...

CI/CD com Terraform

# .github/workflows/terraform.yml
name: Terraform

on:
  pull_request:
    paths:
      - 'terraform/**'

env:
  TF_WORKSPACE: ${{ github.head_ref == 'main' && 'prod' || 'dev' }}

jobs:
  plan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: hashicorp/setup-terraform@v3

      - run: terraform init

      - run: terraform workspace select $TF_WORKSPACE

      - run: terraform plan -out=tfplan

      - uses: actions/upload-artifact@v4
        with:
          name: tfplan
          path: tfplan

  apply:
    if: github.ref == 'refs/heads/main'
    needs: plan
    runs-on: ubuntu-latest
    steps:
      - uses: actions/download-artifact@v4
        with:
          name: tfplan

      - run: terraform apply tfplan

Cleaning Up

# Destruir workspace específico
terraform workspace select dev
terraform destroy

# Deletar workspace (após destroy)
terraform workspace delete dev

# Listar workspaces
terraform workspace list

Workspaces são ideais para ambientes efêmeros (PR environments). Para ambientes fixos, use diretórios separados ou Terragrunt. Sempre use remote state com locking.