Terraform ya describe tu infraestructura, con precisión y bajo control de versiones. Entonces, ¿por qué nadie entiende el sistema a partir del código? Porque un archivo .tf responde a "qué existe y cómo está configurado", mientras que quienes leen un diagrama de arquitectura preguntan otra cosa: por dónde entra el tráfico, qué habla con qué, dónde viven los datos y qué está expuesto.
Esta guía muestra cómo pasar de Terraform a un diagrama que la gente pueda leer: por qué terraform graph no es ese diagrama, cómo asignar recursos a marcos y tarjetas, cuándo usar el plan JSON, qué dejar fuera y cómo aprovechar el resultado en las revisiones de pull requests.
Por qué ni el código ni terraform graph son el diagrama
Un stack de producción pequeño llega fácilmente a cien recursos repartidos en varios archivos y módulos, y muchos de ellos son pegamento: adjuntos de políticas de IAM, asociaciones de tablas de rutas, reglas de grupos de seguridad, adjuntos de grupos de destino. La respuesta a "¿puede internet llegar a la base de datos?" está ahí, pero repartida en una docena de referencias.
terraform graph no lo arregla. Imprime un grafo en el lenguaje DOT y, desde Terraform 1.7, la salida por defecto es un grafo simplificado que, en palabras de la referencia del comando, describe solo el orden de dependencias de los recursos. Opciones como -type=plan muestran una aproximación del grafo más completo que Terraform usa para construir un plan y, desde Terraform 1.16, -format=mermaid imprime Mermaid en lugar de DOT.
Un grafo de dependencias responde a "qué tiene que existir antes de qué". El servicio de ECS depende de un rol de IAM, un grupo de destino y una definición de tarea, así que las flechas van del servicio hacia sus requisitos previos, a menudo en sentido contrario al tráfico, y los recursos de pegamento ocupan tanto espacio como la base de datos. Sirve para depurar un plan. No es un diagrama de arquitectura.
El stack de ejemplo
Una app web típica en AWS: una VPC con subredes públicas y privadas en dos zonas de disponibilidad, un Application Load Balancer, un servicio de ECS sobre Fargate, una base de datos PostgreSQL en RDS y un bucket de S3 para los archivos subidos. Un fragmento de la configuración:
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
}
resource "aws_subnet" "private_a" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.11.0/24"
availability_zone = "eu-west-1a"
}
resource "aws_lb" "web" {
name = "web"
load_balancer_type = "application"
subnets = [aws_subnet.public_a.id, aws_subnet.public_b.id]
security_groups = [aws_security_group.alb.id]
}
resource "aws_ecs_service" "app" {
name = "app"
cluster = aws_ecs_cluster.main.id
task_definition = aws_ecs_task_definition.app.arn
launch_type = "FARGATE"
desired_count = 2
network_configuration {
subnets = [aws_subnet.private_a.id, aws_subnet.private_b.id]
security_groups = [aws_security_group.app.id]
}
load_balancer {
target_group_arn = aws_lb_target_group.app.arn
container_name = "app"
container_port = 8080
}
}
resource "aws_db_instance" "main" {
identifier = "app-db"
engine = "postgres"
instance_class = "db.t4g.medium"
allocated_storage = 50
username = "app"
manage_master_user_password = true
multi_az = true
db_subnet_group_name = aws_db_subnet_group.main.name
vpc_security_group_ids = [aws_security_group.db.id]
}
Cómo pasar Terraform a un diagrama
La mayor parte del trabajo consiste en decidir qué recursos se convierten en elementos del diagrama y cuáles en detalles de otros elementos:
| En Terraform | En el diagrama |
|---|---|
aws_vpc, aws_subnet y las referencias vpc_id / subnet_id |
Marcos: la VPC alrededor de las subredes públicas y privadas |
aws_lb con su listener y su grupo de destino |
Una tarjeta de balanceador de carga; el puerto del listener va en la conexión |
aws_ecs_service con su clúster y su definición de tarea |
Una tarjeta de cómputo, con el número deseado de tareas |
aws_db_instance con su grupo de subredes |
Una tarjeta de base de datos en las subredes privadas, con Multi-AZ anotado |
aws_s3_bucket con versionado y bloqueo de acceso |
Una tarjeta de almacenamiento de objetos |
| Reglas de los grupos de seguridad | Puertos y protocolos en las conexiones |
| Referencias entre recursos | Conexiones, dibujadas en el sentido en que fluye el tráfico |
depends_on |
Una línea discontinua, si dice algo que el lector necesita |
Roles, políticas y adjuntos de IAM; random_*, time_*, null_resource |
Fuera del diagrama, o una nota breve en la tarjeta |
Archivos .tf o plan JSON
Puedes trabajar a partir de la propia configuración o de un plan:
terraform plan -out plan.out
terraform show -json plan.out > plan.json
Los archivos .tf son rápidos y no necesitan ejecutar nada, pero count y for_each no se expanden, las variables son desconocidas y los módulos remotos quedan cerrados. El plan JSON lo tiene todo resuelto, y su lista resource_changes dice qué hará el plan con cada recurso: ["create"], ["update"], ["delete"] o ["delete", "create"] para un reemplazo. Eso lo convierte en la mejor entrada para revisar un cambio. Trata el archivo con cuidado: la documentación de terraform show advierte que los valores sensibles del estado aparecen en texto plano en su salida JSON.
El diagrama
Contenido del diagrama
- Users
- app.example.com
- VPC
- Public subnets · 2 AZs
- Application LB
- Private subnets · 2 AZs
- ECS service ×2
- PostgreSQL, Multi-AZ
- Uploads bucket
- HTTPS 443
- alias record
- HTTP 8080
- PostgreSQL 5432
- HTTPS 443, uploads
Cómo leerlo:
- Entrada. Los usuarios llegan al Application Load Balancer por HTTPS en el puerto 443. El registro de alias DNS apunta a él.
- Límites de red. La VPC contiene dos marcos: subredes públicas para el balanceador de carga y subredes privadas para todo lo demás. Nada de las subredes privadas es accesible desde internet.
- El camino. El balanceador de carga reenvía al servicio de ECS en el puerto 8080. El servicio habla con PostgreSQL en el 5432 y escribe los archivos subidos en S3 por HTTPS.
- La nota. Relaciona cada tarjeta con las direcciones de recursos que hay detrás y enumera lo que se dejó fuera a propósito, para que el lector pueda encontrar el código.
Recorta y luego añade lo que Terraform no sabe
Recorta sin miedo. El pegamento de IAM, las asociaciones de tablas de rutas, los grupos de logs y los recursos de regla por grupo de seguridad pertenecen al código. Una tarjeta por cada cosa desplegable o almacén de datos es el nivel adecuado para la mayoría de los lectores.
Después añade lo que Terraform no te puede decir:
- Quién usa el sistema y por dónde entra el tráfico.
- El sentido del flujo. Las referencias van de un recurso a lo que necesita; el tráfico suele ir al revés.
- Puertos y protocolos sacados de las reglas de los grupos de seguridad, escritos en las conexiones.
- Servicios externos a los que llama la app y que no se gestionan en esta configuración.
- Datos que importan en un incidente: Multi-AZ, copias de seguridad, el número deseado de tareas.
Úsalo en las revisiones de pull requests
Un diagrama generado a partir del plan de una pull request muestra a quienes revisan la forma de un cambio en lugar de un diff largo. Busca en particular unas cuantas cosas:
- Un nuevo punto de entrada público, como un balanceador de carga, una subred pública o un grupo de seguridad abierto a 0.0.0.0/0.
- El reemplazo de un recurso con estado. Un
["delete", "create"]sobre una base de datos o un bucket merece una segunda persona revisando. - Recursos que se mueven entre subredes o salen de la red privada.
- Nuevos almacenes de datos, que necesitan un responsable, copias de seguridad y una entrada en tu mapa de datos.
Mantén separados el diagrama generado y el diagrama de arquitectura cuidado. El generado es una ayuda para revisar un cambio; el cuidado es documentación que explica el sistema.
Mantenlo al día
Trata el diagrama cuidado como código: un responsable, un enlace desde el README del módulo y una actualización cada vez que un cambio añada un punto de entrada, un almacén de datos o un límite de red. Diagramas de arquitectura que no se quedan obsoletos describe un flujo de trabajo justo para eso. Para la parte de red del mismo stack, consulta la guía del diagrama de VPC de AWS y, para ejecutarlo en dos regiones, el diagrama de arquitectura multirregión de AWS.
Constrúyelo en Archboard
- Inicia sesión con Google o GitHub y crea un diagrama.
- Para un primer borrador, pega tus archivos
.tfo tu plan JSON en la herramienta gratuita Terraform a diagrama. Convierte las VPC y subredes en marcos, los recursos en tarjetas y las referencias en conexiones, marca los cambios previstos a partir del plan JSON e integra el pegamento, como los adjuntos de grupos de destino, en las conexiones. Selecciona Abrir en Archboard para seguir editando. - Para dibujarlo a mano, añade un marco VPC del pack Red con dos marcos Subred, un Balanceador de carga en la nube del pack Nube en las subredes públicas, y una Instancia de cómputo y una Base de datos administrada en las subredes privadas.
- Añade un nodo Almacenamiento de objetos del pack Nube para el bucket, un nodo Internet del pack Red para los usuarios y un nodo DNS para el registro de alias.
- Etiqueta las conexiones con puertos y protocolos, y añade un bloque Markdown del pack Básico que relacione las tarjetas con las direcciones de recursos.
El ejemplo usa 10 nodos de diagrama, dentro del plan Free. Si tu stack está definido en CloudFormation, la herramienta CloudFormation a diagrama hace lo mismo con las plantillas.
Preguntas frecuentes
¿Puede terraform graph generar un diagrama de arquitectura? Genera un grafo de dependencias en DOT o, desde Terraform 1.16, en Mermaid. Es útil para depurar planes, pero muestra el orden de construcción en lugar del tráfico e incluye recursos de pegamento, así que hay que depurarlo antes de que la gente pueda leerlo como arquitectura.
¿Dibujo a partir de los archivos .tf o del plan JSON?
Usa los archivos .tf para echar un vistazo rápido a un módulo y el plan JSON para revisar un cambio, porque el plan tiene resueltos los recuentos, los módulos y las acciones previstas.
¿Cómo muestro los grupos de seguridad? Como puertos y protocolos en las conexiones entre los recursos que protegen, no como cajas separadas.
¿Qué debería dejar fuera?
Los adjuntos de IAM, las asociaciones de tablas de rutas, los recursos auxiliares como random_id y todo lo que no cambie cómo entiende el lector el tráfico, los datos o la exposición.
¿Cómo mantengo el diagrama sincronizado con el código? Regenera un borrador cuando un cambio añada un punto de entrada, un almacén de datos o un límite de red, y actualiza el diagrama cuidado en la misma pull request.