Problema
En muchos proyectos de IA y micro‑servicios en Azure se construye un entorno que funciona perfectamente en la suscripción del autor, pero falla al intentar replicarlo en una cuenta limpia. El patrón típico es que la infraestructura depende de configuraciones implícitas: extensiones de PostgreSQL ya instaladas, nombres de secretos que coinciden con recursos creados manualmente, o rutas de archivos locales que sólo existen en la máquina del desarrollador. Cuando otro equipo o un pipeline de CI/CD intenta desplegar el mismo código, aparecen errores de “resource not found”, “invalid secret name” o “extension not allowed”. El resultado es una solución que no es verdaderamente portable y que requiere intervención manual para cada nueva suscripción.
Causa
-
Suposiciones implícitas en el código
- Scripts de seed que crean secretos vacíos. Azure Key Vault rechaza valores nulos.
- Referencias a extensiones de PostgreSQL (por ejemplo
pgvector) que no están en la lista allow‑list de la suscripción. - Variables de entorno que apuntan a rutas locales (
./config/…) que no existen en el contenedor.
-
Dependencias creadas fuera de Terraform
- Recursos provisionados manualmente (bases de datos, identidades gestionadas) que Terraform no conoce y, por tanto, no controla su estado.
- Identidades con permisos excesivos o insuficientes porque la política de IAM se definió después del despliegue inicial.
-
Naming y seeding inconsistentes
- Nombres de secretos que el script de seed genera de forma dinámica, pero que el código de la aplicación espera con un patrón distinto.
- Uso de prefijos o sufijos diferentes entre entornos (dev‑, prod‑) sin una convención clara.
-
Configuración de red y VNet ocultas
- Servicios que dependen de un Private Endpoint configurado manualmente. En una suscripción nueva, el endpoint no existe y la aplicación no puede resolver el DNS interno.
Solución
Adoptar un enfoque infraestructura‑como‑código (IaC) completo y validación automática. Los pasos clave son:
1. Declarar todo con Terraform
- Resource groups, VNet y Subnets: define la red privada desde el primer módulo.
- Azure Container Apps: usa el recurso
azurerm_container_appconingressconfigurado y asigna una Managed Identity. - Azure Database for PostgreSQL: incluye la extensión
pgvectoren la propiedadextensiondel recursoazurerm_postgresql_flexible_server. Si la extensión no está en la allow‑list, añade una regla deazurerm_postgresql_server_configurationpara habilitarla. - Key Vault: crea el vault y los secretos en el mismo plan. Usa
azurerm_key_vault_secretconvalue = var.secret_value; nunca dejes valores vacíos.
2. Centralizar nombres y convenciones
Define variables en variables.tf para todos los prefijos y sufijos. Por ejemplo:
variable "env_prefix" {
type = string
default = "dev"
}
Luego, construye los nombres con interpolación: "${var.env_prefix}-kv" para el Key Vault, "${var.env_prefix}-pg" para la base de datos, etc. Así el mismo código funciona en cualquier suscripción cambiando solo el valor de env_prefix.
3. Seed de secretos sin valores vacíos
Implementa un pequeño script de bootstrap que genere valores aleatorios cuando el secreto no exista. En Bash:
#!/usr/bin/env bash
set -euo pipefail
VAULT_NAME=$1
SECRET_NAME=$2
VALUE=${3:-$(openssl rand -hex 16)}
az keyvault secret set --vault-name "$VAULT_NAME" --name "$SECRET_NAME" --value "$VALUE"
Ejecuta este script desde un null_resource de Terraform para que la generación sea parte del plan.
4. Validaciones de pre‑despliegue
Añade un módulo de checks que utilice az cli o terraform validate para:
- Verificar que la extensión requerida está allow‑listed (
az postgres server configuration list). - Confirmar que la Managed Identity tiene los permisos
get,listysetsobre el Key Vault. - Comprobar que los Private Endpoints están activos (
az network private-endpoint show).
Si alguna validación falla, el pipeline aborta antes de crear los contenedores.
5. Documentación reproducible
Incluye un walkthrough con capturas de pantalla que muestre:
- Clonar el repo.
- Ejecutar
terraform init && terraform apply -var="env_prefix=prod". - Acceder a la consola web desplegada mediante la URL del Container App.
Mantén los pasos en un archivo README.md y enlázalo desde el Hugo frontmatter.
Cuándo aplicar esta solución
- Síntomas: despliegues que funcionan solo en la suscripción del autor; errores de extensión no permitida; secretos que no se crean automáticamente.
- Entornos: cualquier arquitectura basada en Azure Container Apps, PostgreSQL con extensiones, y Key Vault para gestión de secretos.
- No aplicable: proyectos que usan exclusivamente PaaS sin necesidad de extensiones personalizadas o que dependen de recursos externos a Azure (por ejemplo, bases de datos gestionadas fuera de Azure).
Código
# Inicializar Terraform y aplicar con prefijo de entorno
terraform init
terraform apply -var="env_prefix=dev" -auto-approve
# Bootstrap de secretos (ejemplo para API_KEY)
./scripts/seed_secret.sh my-vault api-key
Verificación
-
Infraestructura
- Ejecuta
az containerapp show --name <app-name> --resource-group <rg>y verifica queproperties.provisioningStateseaSucceeded. - Usa
az postgres flexible-server show --name <db-name>y confirma queproperties.extensionsincluyapgvector.
- Ejecuta
-
Aplicación
- Accede a la URL pública del Container App y comprueba que la consola web carga sin errores de conexión a la base de datos.
- Revisa los logs de la app (
az monitor log-analytics query) para asegurarte de que no haya excepciones de secret not found.
-
Seguridad
- Ejecuta
az keyvault secret list --vault-name <vault>y verifica que los secretos esperados existan y tengan valores no vacíos. - Comprueba que la Managed Identity tiene la política
get, list, seten el vault (az keyvault set-policy).
- Ejecuta
Notas adicionales
- Extensiones de PostgreSQL: la lista allow‑list varía por región. Si
pgvectorno está disponible, habilita la característica de “preview extensions” en la suscripción o usa un servidor de PostgreSQL auto‑gestionado en una VM. - Costos: Azure Container Apps en modo Consumption puede reducir gastos, pero los recursos de PostgreSQL y VNet generan costos fijos. Monitorea con Azure Cost Management para mantener el gasto mensual bajo $100.
- Rotación de secretos: programa una Azure Function que lea la fecha de expiración de cada secreto (
az keyvault secret show) y regenere los valores antes de que caduquen. - CI/CD: integra el plan de Terraform en GitHub Actions o Azure Pipelines. Usa el job
terraform plancomo gate antes deterraform apply. - Versionado: guarda los módulos de Terraform en un repositorio separado y versiona con tags semánticos; así los equipos pueden pinchar versiones estables sin romper dependencias.