Boas Práticas em Produção
Aula 7 de 7
Estrutura Recomendada
terraform/
├── environments/
│ ├── dev/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ ├── outputs.tf
│ │ └── terraform.tfvars
│ ├── staging/
│ └── prod/
├── modules/
│ ├── networking/
│ ├── compute/
│ ├── database/
│ └── security/
├── live/
│ ├── global/ # IAM, Route53, CloudTrail
│ ├── us-east-1/
│ │ ├── network/
│ │ ├── services/
│ │ └── monitoring/
│ └── eu-west-1/
└── scripts/
└── ci.sh
Terragrunt para Produção
# prod/terragrunt.hcl
locals {
env_vars = yamldecode(file("${get_terragrunt_dir()}/../env.yaml"))
}
inputs = {
environment = "prod"
vpc_cidr = "10.100.0.0/16"
instance_type = "m6i.xlarge"
min_capacity = 3
max_capacity = 20
}
remote_state {
backend = "s3"
config = {
encrypt = true
bucket = "terraform-state-prod"
key = "${path_relative_to_include()}/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-locks"
}
}
Sentinel — Policy as Code
# Restringir tipos de instância
policy "restrict-instance-type" {
enforcement_level = "advisory"
}
main = rule {
all tfplan.resources_changed as _, instance {
instance.applied.instance_type in ["t3.micro", "t3.small", "m6i.large"]
}
}
Pre-commit Hooks
# .pre-commit-config.yaml
repos:
- repo: https://github.com/antonbabenko/pre-commit-terraform
rev: v1.88.0
hooks:
- id: terraform_fmt
- id: terraform_validate
- id: terraform_tflint
- id: terraform_docs
- id: terraform_tfsec
pre-commit install
TFSec — Security Scanning
tfscan .
# ou
tfsec terraform/
# Exemplo de saída:
# Result: FAIL (critical)
# filename: main.tf:10-15
# Description: AWS S3 bucket has public ACL enabled
Checklist de Produção
- Remote state com S3 + DynamoDB lock
- Backend configurado antes de qualquer apply
- Nenhuma secret hardcoded (use vars/env)
-
prevent_destroyem resources críticos (RDS, S3) -
create_before_destroyonde possível - Workspaces ou diretórios para ambientes
- CI/CD com plan em PR, apply apenas em main
- Formatting com
terraform fmt --checkno CI - Snyk/tfsec scanning de segurança
- Budget alerts nos recursos provisionados
- Pinned provider version (~> x.y)
- Módulos com versão fixa (não usar "latest")
- outputs sensíveis marcados como
sensitive = true - Lifecycle
ignore_changesonde apropriado - Documentação gerada com terraform-docs
Drift Detection Automática
# drift.yaml — GitHub Action semanal
name: Drift Detection
on:
schedule:
- cron: '0 6 * * 1' # Segunda 6h
jobs:
detect:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: |
terraform init
terraform plan -detailed-exitcode
echo "exit=$?" >> $GITHUB_OUTPUT
- if: steps.plan.outputs.exit == 2
run: echo "Drift detectado! Criar issue..."
TFLint
# .tflint.hcl
config {
module = true
}
rule "terraform_unused_declarations" {
enabled = true
}
rule "terraform_comment_syntax" {
enabled = true
}
rule "terraform_documented_outputs" {
enabled = true
}
rule "terraform_documented_variables" {
enabled = true
}
plugin "aws" {
enabled = true
version = "0.30.0"
source = "github.com/terraform-linters/tflint-ruleset-aws"
}
Produção exige rigor: CI/CD, validação automática, scanning de segurança e detecção de drift. Invista em pre-commit hooks e tfsec desde o primeiro dia. Nunca aplique sem revisão.