Diagrama de arquitectura de Terraform: de los archivos .tf a una imagen que la gente pueda leer

Terraform ya describe tu infraestructura, pero ni el código ni terraform graph son un diagrama de arquitectura. Qué necesita uno legible y qué conviene quitar.

· Fundador y desarrollador

Publicado el

Diagrama de arquitectura de Terraform: de los archivos .tf a una imagen que la gente pueda leer

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

Los usuarios se conectan por HTTPS a un balanceador de carga en las subredes públicas de una VPC. Este reenvía a un servicio de ECS en subredes privadas, que usa PostgreSQL y un bucket de S3. Un alias DNS apunta al balanceador y una nota lista los recursos de Terraform de cada tarjeta.

10 componentes · 5 conexiones

Abrir en Archboard
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
Una app web definida en Terraform, dibujada para personas: los usuarios llegan a un Application Load Balancer en subredes públicas, un servicio de ECS y una base de datos PostgreSQL Multi-AZ están en subredes privadas, y una nota relaciona cada tarjeta con sus direcciones de recursos.

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

  1. Inicia sesión con Google o GitHub y crea un diagrama.
  2. Para un primer borrador, pega tus archivos .tf o 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.
  3. 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.
  4. 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.
  5. 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.

Empieza gratis — un puesto, sin tarjeta de crédito.

Artículos relacionados

← Volver al blog

Abre un lienzo en un minuto

Inicia sesión con Google o GitHub. Gratis para un asiento. Mejora el plan cuando se una el equipo.