Terraform 44: Capstone — un módulo de servicio multi-entorno
easy⏱ 5 mincourseterraform
El módulo: RG + KV + Service Bus + tags
El módulo service toma environment, service, location, topics y extra_tags, y produce todo el footprint por servicio — nombres y tags calculados una vez, topics expandidos con for_each (un toset).
# modules/service/main.tf
locals {
tags = merge({
ManagedBy = "terraform"
Environment = var.environment
Service = var.service
}, var.extra_tags)
}
resource "azurerm_resource_group" "this" {
name = "${var.environment}-${var.service}-rg"
location = var.location
tags = local.tags
}
resource "azurerm_key_vault" "this" {
name = "${var.service}-kv-${var.environment}"
resource_group_name = azurerm_resource_group.this.name
location = azurerm_resource_group.this.location
tenant_id = var.tenant_id
sku_name = "standard"
tags = local.tags
}
resource "azurerm_servicebus_namespace" "this" {
name = "${var.environment}-${var.service}-namespace"
resource_group_name = azurerm_resource_group.this.name
location = azurerm_resource_group.this.location
sku = "Standard"
tags = local.tags
}
resource "azurerm_servicebus_topic" "this" {
for_each = toset(var.topics)
name = each.value
namespace_id = azurerm_servicebus_namespace.this.id
}
Cada entorno es una llamada al módulo
La config raíz llama al mismo módulo tres veces con inputs por entorno. Guardá esos inputs en un mapa locals y manejá las llamadas con for_each para que dev/uat/prod queden sincronizados — un cambio al módulo actualiza los tres.
# environments/main.tf
locals {
environments = {
dev = { location = "westus2", topics = ["orders-events"] }
uat = { location = "westus2", topics = ["orders-events"] }
prod = { location = "eastus2", topics = ["orders-events", "orders-audit"] }
}
}
module "service" {
source = "../modules/service"
for_each = local.environments
environment = each.key
service = "orders"
location = each.value.location
topics = each.value.topics
tenant_id = var.tenant_id
}
Aislá el state por entorno
Aun con un solo módulo, mantené state separado por entorno (distinto key de backend, ej. orders/dev.tfstate vs orders/prod.tfstate, o workspaces separados). Un apply de dev jamás debe poder tocar el state de prod. Promové un cambio dev -> uat -> prod por el pipeline, no editando prod directo.
prod no es solo dev con más réplicas
Los inputs por entorno son donde viven las diferencias reales: prod podría usar otra location, topics extra, un SKU mayor o purge protection activado. Mantenerlos como datos en el mapa environments — no como código bifurcado — es lo que hace al módulo confiable entre tiers.
Calculá el conjunto completo de recursos
Dada la config environments, escribí resourcesFor(env, cfg) que devuelva los nombres de recurso que crea una llamada al módulo: `${env}-orders-rg`, `orders-kv-${env}`, `${env}-orders-namespace`, más un `${env}-orders-topic-${t}` por topic. Logueá el conteo total en los tres entornos — con topics dev(1)+uat(1)+prod(2) debe ser 13.