Migrar o messagebroker compartilhado para Amazon MQ (RabbitMQ)
TLDR: Provisionar um messagebroker compartilhado no Amazon MQ para RabbitMQ (cluster HA, na VPC AWS compartilhada), expô-lo por outputs de remote state para que cada projeto crie o seu próprio vhost/user, e manter o broker antigo no ar até os consumidores validarem.
Contexto
O messagebroker compartilhado rodava num droplet da DigitalOcean, provisionado por user_data + Caddy, com DNS no Cloudflare e firewall do provedor. É infraestrutura compartilhada: cada projeto tem um vhost/user (hoje só marketing/n8n, vhost marketing-automation--staging).
O cluster Kubernetes compartilhado e a camada de dado do marketing (Aurora Postgres, ElastiCache Valkey) já estão na AWS, na VPC compartilhada (10.0.0.0/16, conta shared--production, subnets privadas compartilhadas org-wide via RAM). O messagebroker era a última peça compartilhada fora da AWS.
O Amazon MQ para RabbitMQ é RabbitMQ gerenciado — consistente com a direção de serviço gerenciado já tomada em Aurora e ElastiCache.
Decisões
| Decisão | Escolha | Motivo |
|---|---|---|
| Gerenciado vs. self-hosted | Amazon MQ, não RabbitMQ no EKS | consistência com Aurora/ElastiCache; o provider kubernetes do módulo de messagebroker segue um stub |
| Modo de deploy | CLUSTER_MULTI_AZ (HA) |
é produção; HA evita indisponibilidade em falha ou manutenção de nó. O droplet único não tinha HA nenhuma |
| Topologia | um broker centralizado, multi-vhost | overhead por vhost é desprezível; escala-se por tamanho de instância, não por broker separado |
| Tudo por Terraform | sem local-exec |
vhost/user pelo provider cyrilgdn/rabbitmq onde declarados |
| Nomenclatura | messagebroker em todo lugar |
só as strings impostas pela AWS ficam como são (mq:*, aws_mq_broker) |
O perigo principal: contrato de endereço
Os outputs consumidos hoje assumem IP privado + AMQP 5672 em texto puro e uma API de management em HTTP. O Amazon MQ expõe hostname com TLS: AMQPS na 5671 e management em HTTPS 443. Adaptar isso é o risco central da migração.
Objetivos
- Broker no Amazon MQ (cluster HA) nas subnets privadas da VPC compartilhada, alcançável privadamente pelos workloads do EKS.
- Broker centralizado/multi-vhost, com o vhost, user e permissões do marketing recriados nele.
- Preservar o contrato de output de remote state ao máximo, adaptando para hostname + TLS.
- Cortar o consumidor n8n do marketing para o broker novo.
Fora de escopo
- Recursos específicos de aplicação não vivem aqui. O vhost, o user e as permissões do n8n/marketing pertencem ao projeto marketing (
marketing/automation/.infra), que já os cria via providerrabbitmq. Este stack compartilhado provisiona somente broker + user admin + security group + outputs. - Migrar mensagem enfileirada. O n8n reconstrói o estado da fila; só vhost/user/permissão são recriados.
- Workflows restaurados do n8n que referenciam o hostname antigo — é correção de dado de workflow, em outro lugar.
- Destruir o droplet: fica no ar até o cutover ser validado, e a remoção é spec própria.
Mudanças
Estrutura
Segue o padrão de provider dividido já usado no stack de Kubernetes:
src/shared/messagebroker/
├── digitalocean/terraform/ # stack do droplet, movido para cá sem alteração
└── aws/terraform/ # NOVO — Amazon MQ para RabbitMQ
Os targets de make ganham um switch PROVIDER (default aws, PROVIDER=do para o droplet).
Novo: src/shared/messagebroker/aws/terraform/
- Provider: AWS assumindo a
TerraformRoleda conta shared, mesmo padrão dos outros stacks AWS. Chave de stateshared/messagebroker-aws/terraform.tfstate. aws_mq_broker:engine_type = "RabbitMQ",deployment_mode = "CLUSTER_MULTI_AZ",host_instance_typeparametrizado,publicly_accessible = false,subnet_idsvindos do remote state da rede, security group novo, e o user admin com senha do ward.- Security group: na VPC compartilhada, ingress 5671 (AMQPS) e 443 (management) a partir do CIDR da VPC, egress liberado.
- Outputs: mesmos nomes do stack do droplet, remapeados —
messagebroker_amqp_host(hostname do endpoint AMQPS),messagebroker_amqp_port = 5671,messagebroker_management_host,messagebroker_management_port = 443,messagebroker_admin_password(sensitive), maismessagebroker_amqp_endpointemessagebroker_amqps_tls = true.messagebroker_public_ip/_private_ipdeixam de existir — não há IP.
Consumidor: marketing/automation/.infra/terraform
- Provider
rabbitmqapontado para o endpoint de management do Amazon MQ em HTTPS. RABBITMQ_HOST=messagebroker_amqp_host,RABBITMQ_PORT=5671, eRABBITMQ_TLS = "true"— o n8n precisa conectar por AMQPS.
Pré-requisitos de permissão
A TerraformRole da conta shared tinha EC2/RAM/EKS/ECR/IAM/Logs mas não mq:*. É preciso adicionar a statement mq:* à TerraformPolicy e reaplicar o bootstrap da conta antes de criar o broker. O Amazon MQ também precisa de ec2:*SecurityGroup* e ec2:*NetworkInterface*.
A senha do admin fica no ward (TF_VAR_shared_messagebroker_admin_password) e precisa atender às restrições do Amazon MQ (mínimo 12 caracteres, sem vírgula).
Como verificar
aws mq describe-brokermostra o brokerRUNNING, emCLUSTER_MULTI_AZ, nas subnets privadas.- De dentro de um pod do EKS:
openssl s_client -connect <amqp-host>:5671conecta (alcance privado + TLS). - O vhost do marketing, seu user e permissões existem no broker novo.
kubectl -n marketing-automation--staging logs deploy/n8n-workersemENOTFOUNDnem connection-refused.- Um workflow no n8n publica e consome via RabbitMQ ponta a ponta.
- Os outputs de remote state resolvem e o stack do marketing planeja/aplica limpo contra eles.
Documentação
CLAUDE.md— messagebroker no Amazon MQ, split{digitalocean,aws}e o switchPROVIDER.- Skill
commons:infra— seção de outputs de remote state: AMQPS 5671 + management 443, hostname e não IP,RABBITMQ_TLS=trueobrigatório. - Aprendizado: restrições do Amazon MQ para RabbitMQ em cluster — onde as suposições desta spec de fato quebraram (tipo de instância, contagem de subnet).