Diagrama de arquitetura do Terraform: dos arquivos .tf a uma imagem que as pessoas conseguem ler

O Terraform já descreve sua infraestrutura, mas nem o código nem o terraform graph são um diagrama de arquitetura. O que um diagrama legível precisa e o que cortar.

· Fundador e desenvolvedor

Publicado em

Diagrama de arquitetura do Terraform: dos arquivos .tf a uma imagem que as pessoas conseguem ler

O Terraform já descreve sua infraestrutura, com precisão e sob controle de versão. Então por que ninguém entende o sistema a partir do código? Porque um arquivo .tf responde "o que existe e como está configurado", enquanto quem lê um diagrama de arquitetura pergunta outra coisa: por onde o tráfego entra, o que fala com o quê, onde os dados ficam e o que está exposto.

Este guia mostra como ir do Terraform a um diagrama que as pessoas conseguem ler: por que o terraform graph não é esse diagrama, como mapear recursos para molduras e cards, quando usar o plan JSON, o que deixar de fora e como usar o resultado em revisões de pull requests.

Por que nem o código nem o terraform graph são o diagrama

Uma stack de produção pequena chega facilmente a cem recursos espalhados por vários arquivos e módulos, e muitos deles são cola: anexos de políticas do IAM, associações de tabelas de rotas, regras de grupos de segurança, anexos de grupos de destino. A resposta para "a internet consegue chegar ao banco de dados?" está ali, mas espalhada por uma dúzia de referências.

O terraform graph não resolve isso. Ele imprime um grafo na linguagem DOT e, desde o Terraform 1.7, a saída padrão é um grafo simplificado que, nas palavras da referência do comando, descreve apenas a ordem de dependência dos recursos. Opções como -type=plan mostram uma aproximação do grafo mais completo que o Terraform usa para montar um plano e, desde o Terraform 1.16, -format=mermaid imprime Mermaid em vez de DOT.

Um grafo de dependências responde "o que precisa existir antes de quê". O serviço do ECS depende de uma role do IAM, de um grupo de destino e de uma definição de tarefa, então as setas vão do serviço para os seus pré-requisitos, muitas vezes no sentido oposto ao do tráfego, e os recursos de cola ocupam tanto espaço quanto o banco de dados. Isso é útil para depurar um plano. Não é um diagrama de arquitetura.

A stack de exemplo

Uma aplicação web típica na AWS: uma VPC com sub-redes públicas e privadas em duas zonas de disponibilidade, um Application Load Balancer, um serviço do ECS no Fargate, um banco PostgreSQL no RDS e um bucket do S3 para uploads. Um trecho da configuração:

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]
}

Mapeando o Terraform para um diagrama

A maior parte do trabalho é decidir quais recursos viram elementos do diagrama e quais viram detalhes de outros elementos:

No Terraform No diagrama
aws_vpc, aws_subnet e as referências vpc_id / subnet_id Molduras: a VPC em volta das sub-redes públicas e privadas
aws_lb com o listener e o grupo de destino Um card de balanceador de carga; a porta do listener vai na conexão
aws_ecs_service com o cluster e a definição de tarefa Um card de computação, com a quantidade desejada
aws_db_instance com o grupo de sub-redes Um card de banco de dados nas sub-redes privadas, com Multi-AZ anotado
aws_s3_bucket com versionamento e bloqueio de acesso Um card de armazenamento de objetos
Regras de grupos de segurança Portas e protocolos nas conexões
Referências entre recursos Conexões, desenhadas no sentido em que o tráfego flui
depends_on Uma linha tracejada, se disser algo que o leitor precisa saber
Roles, políticas e anexos do IAM; random_*, time_*, null_resource Fora do diagrama, ou uma nota curta no card

Arquivos .tf ou plan JSON

Você pode trabalhar a partir da própria configuração ou de um plano:

terraform plan -out plan.out
terraform show -json plan.out > plan.json

Os arquivos .tf são rápidos e não exigem rodar nada, mas count e for_each não são expandidos, as variáveis são desconhecidas e os módulos remotos continuam fechados. O plan JSON tem tudo isso resolvido, e a lista resource_changes diz o que o plano vai fazer com cada recurso: ["create"], ["update"], ["delete"] ou ["delete", "create"] para uma substituição. Isso faz dele a melhor entrada para revisar uma mudança. Trate o arquivo com cuidado: a documentação do terraform show avisa que valores sensíveis do state aparecem em texto puro na saída JSON.

O diagrama

Os usuários se conectam por HTTPS a um balanceador de carga nas sub-redes públicas de uma VPC. Ele encaminha para um serviço do ECS em sub-redes privadas, que usa PostgreSQL e um bucket do S3. Um alias de DNS aponta para o balanceador, e uma nota lista os recursos do Terraform dos cards.

10 componentes · 5 conexões

Abrir no Archboard
Conteúdo do 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
Uma aplicação web definida em Terraform, desenhada para pessoas: os usuários chegam a um Application Load Balancer em sub-redes públicas, um serviço do ECS e um banco PostgreSQL Multi-AZ ficam em sub-redes privadas, e uma nota liga cada card aos seus endereços de recurso.

Como ler:

  • Entrada. Os usuários chegam ao Application Load Balancer por HTTPS na porta 443. O registro de alias de DNS aponta para ele.
  • Limites de rede. A VPC contém duas molduras: sub-redes públicas para o balanceador de carga e sub-redes privadas para todo o resto. Nada nas sub-redes privadas pode ser acessado pela internet.
  • O caminho. O balanceador de carga encaminha para o serviço do ECS na porta 8080. O serviço fala com o PostgreSQL na 5432 e grava os uploads no S3 por HTTPS.
  • A nota. Ela liga cada card aos endereços de recurso por trás dele e lista o que ficou de fora de propósito, para que o leitor encontre o código.

Corte e depois acrescente o que o Terraform não sabe

Corte sem dó. A cola do IAM, as associações de tabelas de rotas, os grupos de logs e os recursos de regra por grupo de segurança pertencem ao código. Um card por coisa implantável ou armazenamento de dados é o nível certo para a maioria dos leitores.

Depois acrescente o que o Terraform não consegue dizer:

  • Quem usa o sistema e por onde o tráfego entra.
  • O sentido do fluxo. As referências vão de um recurso para aquilo de que ele precisa; o tráfego muitas vezes corre no sentido contrário.
  • Portas e protocolos tirados das regras dos grupos de segurança, escritos nas conexões.
  • Serviços externos que a aplicação chama e que não são gerenciados nesta configuração.
  • Fatos que importam durante um incidente: Multi-AZ, backups, a quantidade desejada.

Use nas revisões de pull requests

Um diagrama gerado a partir do plano de um pull request mostra a quem revisa o formato de uma mudança em vez de um diff longo. Procure algumas coisas em particular:

  • Um novo ponto de entrada público, como um balanceador de carga, uma sub-rede pública ou um grupo de segurança aberto para 0.0.0.0/0.
  • A substituição de um recurso com estado. Um ["delete", "create"] em um banco de dados ou bucket merece uma segunda pessoa revisando.
  • Recursos que mudam de sub-rede ou saem da rede privada.
  • Novos armazenamentos de dados, que precisam de um responsável, de backups e de uma entrada no seu mapa de dados.

Mantenha separados o diagrama gerado e o diagrama de arquitetura curado. O gerado é uma ajuda para revisar uma mudança; o curado é a documentação que explica o sistema.

Mantenha atualizado

Trate o diagrama curado como código: um responsável, um link no README do módulo e uma atualização sempre que uma mudança adicionar um ponto de entrada, um armazenamento de dados ou um limite de rede. Diagramas de arquitetura que não envelhecem descreve um fluxo de trabalho exatamente para isso. Para o lado de rede da mesma stack, veja o guia do diagrama de VPC da AWS e, para rodar em duas regiões, o diagrama de arquitetura multirregião da AWS.

Monte no Archboard

  1. Entre com Google ou GitHub e crie um diagrama.
  2. Para um primeiro rascunho, cole seus arquivos .tf ou seu plan JSON na ferramenta gratuita Terraform para diagrama. Ela transforma VPCs e sub-redes em molduras, recursos em cards e referências em conexões, marca as mudanças planejadas a partir do plan JSON e incorpora a cola, como anexos de grupos de destino, às conexões. Selecione Abrir no Archboard para continuar editando.
  3. Para desenhar à mão, adicione uma moldura VPC do pack Rede com duas molduras Sub-rede, um Balanceador de carga na nuvem do pack Nuvem nas sub-redes públicas e uma Instância de computação e um Banco de dados gerenciado nas sub-redes privadas.
  4. Adicione um nó Armazenamento de objetos do pack Nuvem para o bucket, um nó Internet do pack Rede para os usuários e um nó DNS para o registro de alias.
  5. Rotule as conexões com portas e protocolos e adicione um bloco Markdown do pack Básico que ligue os cards aos endereços de recurso.

O exemplo usa 10 nós de diagrama e fica dentro do plano Free. Se a sua stack é definida em CloudFormation, a ferramenta CloudFormation para diagrama faz o mesmo com templates.

Perguntas frequentes

O terraform graph consegue gerar um diagrama de arquitetura? Ele gera um grafo de dependências em DOT ou, desde o Terraform 1.16, em Mermaid. Isso ajuda a depurar planos, mas mostra a ordem de construção em vez do tráfego e inclui recursos de cola, então precisa de curadoria antes que as pessoas consigam lê-lo como arquitetura.

Devo desenhar a partir dos arquivos .tf ou do plan JSON? Use os arquivos .tf para uma olhada rápida em um módulo e o plan JSON para revisar uma mudança, porque o plano tem as contagens, os módulos e as ações planejadas resolvidos.

Como mostro os grupos de segurança? Como portas e protocolos nas conexões entre os recursos que eles protegem, não como caixas separadas.

O que devo deixar de fora? Anexos do IAM, associações de tabelas de rotas, recursos auxiliares como random_id e tudo o que não muda a forma como o leitor entende o tráfego, os dados ou a exposição.

Como mantenho o diagrama em sincronia com o código? Gere um novo rascunho quando uma mudança adicionar um ponto de entrada, um armazenamento de dados ou um limite de rede, e atualize o diagrama curado no mesmo pull request.

Comece grátis — um assento, sem cartão de crédito.

Artigos relacionados

← Voltar ao blog

Abra um canvas em um minuto

Entre com Google ou GitHub. Grátis para um assento. Faça upgrade quando a equipe entrar.