Provisionamento de bancos com Terraform (IaC)
Sintoma
Objetivo: definir a infraestrutura do banco (instância, parameter group, rede) como código (Infrastructure as Code) com Terraform; montar o fluxo plan/apply, o remote state e o gerenciamento de drift.
1. Escolha e configure o provider (aws / google / azurerm)
Defina o provider da nuvem em que você roda e fixe sua versão. Trave o provider hashicorp/aws para AWS, hashicorp/google para GCP e hashicorp/azurerm para Azure no bloco required_providers. Fixar a versão garante um comportamento consistente em toda a equipe.
PostgreSQL
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "eu-central-1"
}2. Configure o remote state e o locking
Não mantenha o arquivo de state localmente; use um backend remoto para trabalho em equipe e segurança. As escolhas comuns são o backend S3 + uma tabela de lock no DynamoDB na AWS, o backend gcs no GCP e o backend azurerm (Storage Account) no Azure. O remote state evita applies simultâneos por meio do locking e faz do state a única fonte da verdade. Como senhas podem ficar no state em texto puro, mantenha o backend criptografado e com acesso restrito.
PostgreSQL
terraform {
backend "s3" {
bucket = "company-tfstate"
key = "db/terraform.tfstate"
region = "eu-central-1"
dynamodb_table = "tf-lock"
encrypt = true
}
}3. Defina o recurso do banco
Escreva o recurso principal para o seu engine e nuvem: aws_db_instance na AWS (ou aws_rds_cluster para Aurora), google_sql_database_instance no GCP, azurerm_mssql_database no Azure (para SQL Server, sob um azurerm_mssql_server). Especifique aqui engine, versão, classe, armazenamento e janela de backup.
PostgreSQL
resource "aws_db_instance" "pg" {
identifier = "app-db"
engine = "postgres"
engine_version = "16"
instance_class = "db.t3.medium"
allocated_storage = 50
db_name = "appdb"
username = "pgadmin"
password = var.db_password
backup_retention_period = 7
}SQL Server
resource "azurerm_mssql_database" "db" {
name = "appdb"
server_id = azurerm_mssql_server.srv.id
sku_name = "S1"
}4. Escreva o parameter group como código
Defina as configurações do banco (max_connections, work_mem, conjunto de caracteres) com um recurso de parâmetros, não manualmente no console. Use aws_db_parameter_group na AWS, settings.database_flags dentro de google_sql_database_instance no GCP e o recurso de configuração do servidor no Azure. Assim as configurações ficam versionadas e reproduzíveis.
PostgreSQL
resource "aws_db_parameter_group" "pg" {
name = "app-pg16"
family = "postgres16"
parameter {
name = "max_connections"
value = "200"
}
}
# inside aws_db_instance:
# parameter_group_name = aws_db_parameter_group.pg.name5. Passe segredos por variáveis e um secrets manager
Não coloque a senha fixa em um arquivo .tf; defina-a como variável sensível (variable ... sensitive = true) e forneça o valor por uma variável de ambiente TF_VAR_, um secrets manager (AWS Secrets Manager, Vault) ou um segredo de CI. Lembre-se: o valor é gravado no arquivo de state, então o remote state precisa ser criptografado. A abordagem mais limpa é nunca passar a senha ao Terraform e lê-la de um recurso de secrets manager.
PostgreSQL
variable "db_password" {
type = string
sensitive = true
}
# CI/shell:
export TF_VAR_db_password="$(vault kv get -field=pw secret/db)"6. Execute o fluxo plan e apply
Primeiro prepare o provider/backend com terraform init, veja o que vai mudar com terraform plan, aprove e aplique com terraform apply. Não aplique sem revisar a saída do plan; o fluxo seguro em CI é postar o 'plan' como comentário no PR e aplicar após aprovação humana. Identifique mudanças destrutivas (ex.: recriação da instância) pelo marcador -/+ na saída do plan.
PostgreSQL
terraform init
terraform plan -out=plan.tfplan
terraform apply plan.tfplan7. Detecte e corrija o drift
Se alguém fizer uma alteração manual no console, a infraestrutura real e o state divergem (drift). Diferenças que aparecem no terraform plan 'quando nada deveria ter mudado' revelam o drift; a diferença é lida com terraform refresh/plan. Ou leve a alteração de volta para o código, ou traga a infraestrutura de volta ao código com apply. Proíba alterações manuais como regra; o código deve ser a única fonte da verdade.
PostgreSQL
# drift check (when no changes are expected):
terraform plan
# expect 'No changes'; any diff means drift
# bring an existing resource into state with import:
terraform import aws_db_instance.pg app-db