Beanstalk Cluster Mode: o postmortem que escrevi antes do incidente
Ouvir artigo
gerado ao ouvirGerado apenas no primeiro play
Com tecnologia Amazon Polly + OmniVoice
O Elastic Beanstalk ganhou um modo em que ambientes com o mesmo conjunto de subnets compartilham um cluster EKS operado pelo serviço. Isso muda o raio de explosão: um ajuste manual no cluster deixa todos os ambientes dele sem deploy até alguém reverter. Escrevi o postmortem desse incidente antes de ele acontecer, só com comportamento documentado, e listo o que configurar no dia zero.
O Cluster Mode do Elastic Beanstalk tem um dia de vida — foi anunciado em 17 de setembro de 2026 — e o incidente abaixo ainda não aconteceu com ninguém que eu conheça. Escrevi o postmortem mesmo assim, porque tudo que ele contém está na documentação: ambientes que usam o mesmo conjunto de subnets vão para o mesmo cluster EKS, o serviço detecta drift quando alguém mexe no cluster por fora, e enquanto o drift durar toda atualização de todo ambiente daquele cluster falha. Depois de 16 anos operando plataforma financeira, aprendi que a pergunta não é 'isso reduz custo?' — é 'quantos serviços param de aceitar hotfix quando uma pessoa erra às 17h de sexta?'.
O que aconteceu (no ensaio)
O cenário: uma equipe de pagamentos com nove serviços em ambientes Standard separados migra todos para Cluster Mode nas mesmas três subnets privadas. O primeiro create-environment cria a stack beanstalk-cluster-{uuid} em cerca de dez minutos; os outros oito entram no mesmo cluster sem criar nada. A conta de EC2 cai porque o EKS Auto Mode empacota os containers, e a equipe comemora.
O gatilho: um engenheiro com eks:* na role de administrador nota um node pool que parece ocioso e o edita direto no EKS, como faria em qualquer cluster da empresa. O Beanstalk compara o cluster com a configuração service-managed que ele espera, registra ERROR Cluster drift detected no evento do ambiente e pausa a manutenção daquele cluster.
A consequência: a partir desse momento, o serviço não coloca ambiente novo nesse cluster, não aplica atualização de add-on e — o ponto que dói — rejeita qualquer update-environment dos nove ambientes. Os replicas continuam rodando; o tráfego continua chegando pelo ALB. O que morre é a capacidade de mudar. Duas horas depois, um bug no serviço de conciliação exige hotfix e o deploy falha com uma mensagem que ninguém do plantão tinha visto.
O retro que segue não procura culpado. Procura a fronteira que faltou.
Linha do tempo
- 1
T-14d — Consolidação
Nove ambientes criados com o mesmo conjunto de subnets e as mesmas
cluster-role,node-roleeobservability-role. Um cluster, um control plane, Kubernetes na versão que o Beanstalk escolheu e que fica fixa pela vida do cluster. - 2
T-0 17:05 — Edição manual
Node pool alterado no console do EKS. Nenhum alarme dispara: o cluster está saudável do ponto de vista do Kubernetes.
- 3
T+0h20 — Drift detectado
O próximo
update-environmentfaz o Beanstalk reavaliar o cluster e emitirCluster drift detected ... Service will skip cluster maintenance. O evento fica na lista de eventos do ambiente — ninguém assina esse fluxo. - 4
T+2h10 — Hotfix bloqueado
Deploy do serviço de conciliação falha. O plantão tenta em outro ambiente do mesmo cluster: falha igual. Nove serviços sem caminho de mudança.
- 5
T+3h40 — Recuperação
A mensagem de drift diz o que mudou; a equipe reverte a edição do node pool. A próxima operação de ambiente reavalia o cluster, o Beanstalk retoma a gestão e o deploy que falhou é repetido. Recuperação é por cluster, não por ambiente.
Causa raiz
A causa raiz não foi a edição do node pool — foi tratar o conjunto de subnets como decisão de rede quando ele é, no Cluster Mode, a decisão de raio de explosão. A documentação é explícita: mesmo conjunto de subnets, mesmo cluster; falha de cluster afeta todo ambiente nele; subnets e roles não podem ser trocadas depois de criar o ambiente. A equipe consolidou nove serviços com SLOs diferentes numa única fronteira de falha e deixou humanos com permissão de escrita no EKS que o serviço considera dele.
Subnets escolhem o cluster, o cluster define o raio de explosão
Dois conjuntos de subnets geram dois clusters service-managed. O drift congela só o cluster onde a edição manual aconteceu; o segundo segue aceitando deploy.
- Beanstalk · agrupa por subnet set
- Detector de drift · config esperada vs real
- EKS Auto Mode · beanstalk-cluster-a
- eb-payments-api · 3 replicas
- eb-reconciliation · hotfix bloqueado
- Node pool · editado à mão
- EKS Auto Mode · beanstalk-cluster-b
- eb-ledger · node-pool dedicado
- CloudWatch · 4 log groups sem retenção
Remediação: desenhar a fronteira antes do primeiro ambiente
Subnets por domínio de falha, não por VPC: a decisão mais barata do dia zero é a mais cara de corrigir depois — mudar subnet de ambiente existente é rejeitado, e a saída é criar ambiente novo e trocar CNAME em blue/green. Eu alocaria um conjunto de subnets por regime de SLO e de compliance: um cluster para o que está no escopo do PCI DSS e carrega dados de cartão, outro para o que pode ficar duas horas sem hotfix, outro para dev. Separar produção de desenvolvimento já é o caso que a própria documentação cita como comum.
Humanos sem escrita no EKS do serviço: o drift só existe porque alguém pôde editar. Uma SCP ou uma policy de permissão com Deny em eks:Update, eks:Delete e eks:Create condicionada a aws:ResourceTag das stacks beanstalk-cluster- deixa o caminho de mudança passando obrigatoriamente pelo update-environment. Leitura pode ficar liberada; é o que o runbook de verificação de deleção precisa.
node-pool para o que não pode disputar CPU: sem ele, replicas de ambientes diferentes dividem o mesmo nó. Dar ao serviço de ledger um valor de node-pool que nenhum outro ambiente usa tira o vizinho barulhento do caminho, mas mudar esse valor reinicia todos os replicas — decida na criação.
Um application-role por ambiente: a rede entre ambientes é bloqueada por padrão, mas a saída não é restrita e credencial compartilhada anula a separação. Role por ambiente, escopada ao que ele acessa, é o mínimo.
Três fronteiras, três raios de explosão
| Como obter | O que separa | O que não separa | Quando usar | |
|---|---|---|---|---|
| Cluster compartilhado (padrão) | Mesmo conjunto de subnets | Namespace eb-<env> próprio; tráfego entre ambientes bloqueado | Control plane, nós, versão do Kubernetes, drift, saída de rede | Serviços de uma mesma aplicação, mesmo time, mesmo SLO |
| Nós dedicados | node-pool com valor único | CPU e memória do nó; vizinho barulhento | Control plane e drift continuam compartilhados | Serviço sensível a latência dentro de um cluster de confiança |
| Clusters separados | Conjuntos de subnets diferentes | Tudo: control plane, nós, rede, drift | Nada — mas cada cluster custa US$ 0,10/h a mais | Clientes distintos, código que você não controla, escopo regulatório |
Os padrões que só aparecem às 2h da manhã
O retro do drift escondia um segundo incidente esperando a vez. Os padrões dos namespaces aws:elasticbeanstalk:eks:* são razoáveis para demo e perigosos para produção financeira.
Probes desligadas: readiness, liveness e startup vêm com enabled=false. Sem readiness, um replica novo recebe tráfego do ALB antes de abrir o pool de conexões; sem liveness, um processo travado fica no ar até alguém notar. Ligue as três, com period-seconds abaixo do padrão de 30 e failure-threshold de 3 — o que dá 90 segundos de detecção no pior caso.
cpu de 250m sem cpu-limit: a reserva é pequena e o teto não existe. Um replica com vazamento de CPU disputa o nó com quem estiver do lado. Defina cpu-limit e memory-limit (o padrão de memória é 1Gi) por serviço, medidos.
Escala por CPU a 80%: sem trigger explícito, o serviço escala entre min-replica=1 e max-replica=10 por utilização de CPU. Para fila de pagamentos, scaler-type=metrics-api lendo o backlog do seu endpoint é a métrica que importa; min-replica=1 em produção é um único ponto de falha com nome bonito.
Secrets sem application-role: a opção secrets e a scaler-auth-secret montam via identidade do pod, que só existe com application-role definido. Sem ele, a montagem falha e os replicas nunca sobem — silenciosamente, no primeiro deploy.
Log groups sem retenção: os quatro /aws/elasticbeanstalk/* são compartilhados por conta e região e nascem sem política de expiração; cada deploy cria stream novo. Defina retenção no dia um.
A conta que justifica — ou não — o cluster compartilhado
O argumento do Cluster Mode é custo por aplicação caindo conforme o número de aplicações sobe. A conta tem três parcelas fixas que o Standard não tinha.
Control plane: US$ 0,10 por cluster por hora, cerca de US$ 73 por mês por conjunto de subnets. Cada fronteira de falha que eu recomendei acima custa isso. Passado o período de suporte padrão do Kubernetes, o suporte estendido sobe para US$ 0,60/h — e como a versão fica fixa pela vida do cluster, esse relógio corre desde a criação.
EKS Auto Mode: taxa de gestão por instância além do EC2. No exemplo da página de preços, uma m5a.xlarge custa US$ 0,172/h de EC2 mais US$ 0,02064/h de Auto Mode — 12% em cima do compute.
Métricas custom: o Standard publica em AWS/ElasticBeanstalk, gratuito. O Cluster Mode publica em ElasticBeanstalk/Infrastructure, /System e /Application, namespaces custom cobrados por métrica, e as duas métricas de container saem por replica. Vinte replicas viram dezenas de métricas pagas antes de a aplicação emitir a primeira delas.
O próprio post de lançamento cita a régua: abaixo de cerca de US$ 500 por mês de carga, o overhead do EKS supera a economia e o Standard continua melhor. Minha leitura: o modo compensa quando você tem de seis a oito serviços do mesmo domínio, cada um subutilizando uma instância dedicada hoje, e uma plataforma disposta a pagar US$ 73 por fronteira de falha extra. Com dois serviços, é uma migração para pagar mais e mudar menos.
Lentes do Well-Architected
Segurança
Rede entre ambientes bloqueada por padrão; abra só com ingress-groups ou allowlist no receptor. Saída não é restrita — trate no subnet. Cluster compartilhado é soft multi-tenancy; escopo PCI DSS ou cliente distinto pede subnets próprias. application-role por ambiente e wafv2-acl-arn no ALB.
Confiabilidade
Raio de explosão é decidido pelo conjunto de subnets e é imutável por ambiente. Ligue as três probes, defina min-replica ≥ 2 e max-unavailable=0 no rolling update, e assine os eventos do ambiente para alertar em Cluster drift detected — o evento existe, ninguém o lê por padrão.
Anti-padrões
- Uma VPC, um conjunto de subnets, todos os serviços: transforma a conta inteira num único domínio de falha que só se desfaz recriando ambiente por ambiente.
- Operar o cluster com
kubectlporque 'é EKS': é EKS, mas é do serviço; a primeira edição congela deploy de todos os vizinhos. - **Passar namespaces clássicos (
aws:autoscaling:) no.ebextensionsmigrado:* o Cluster Mode devolveInvalidParameterValueExceptionem vez de ignorar — o pipeline quebra no primeiro deploy. GetSecretValuesemDescribeSecretno role da observabilidade custom: o ambiente sobe, e cada refresh agendado da credencial falha depois — o Datadog para de receber dados sem erro no deploy.- Consolidar para economizar com dois serviços: o control plane e a taxa do Auto Mode custam mais que a instância dedicada que você deixou de pagar.
Eu adotaria o Cluster Mode para o conjunto de serviços internos de uma mesma equipe — os que hoje pagam instância dedicada para servir 200 requisições por minuto — e não para nada que carregue dado de cartão nos primeiros seis meses. Antes do primeiro ambiente, desenharia o mapa de subnets como desenho um mapa de contas: cada conjunto é um cluster, cada cluster é o que para junto. Negaria escrita no EKS para todo humano, ligaria alarme no evento de drift e colocaria retenção nos log groups no mesmo commit. A lição dura por trás disso: uma plataforma que esconde o Kubernetes não esconde o raio de explosão — ela só muda o nome do botão que o define.
Veredito
Use o Cluster Mode quando: os serviços pertencem ao mesmo time e ao mesmo SLO, somam mais de US$ 500 por mês em compute subutilizado, e a plataforma aceita pagar US$ 73 por mês por cada fronteira de falha adicional. Fique no Standard quando: são um ou dois serviços, a aplicação guarda estado em disco local, ou o escopo regulatório exige separação de infraestrutura que você não vai pagar em clusters separados. Em qualquer dos casos, a decisão que não tem volta é o conjunto de subnets — trate-a como decisão de arquitetura, com ADR, e não como campo de formulário.
Referências
Deep dives de arquitetura, AWS, IA e mercado — direto no seu email. Grátis.
Sem spam · cancele quando quiser
Pergunte ao Fernando sobre isto
Receba uma resposta focada sobre este artigo do meu assistente de IA, baseada no meu trabalho.
Participe da conversa
Entre para comentar
Confirme seu e-mail para participar — você também recebe a newsletter. Sem senha.
Continue lendo
Inteligência de arquitetura, na sua caixa de entrada
Sinais curados e análises originais sobre AWS, IA, sistemas distribuídos e mercado — do jeito que um arquiteto de soluções lê.
- Curadoria de AWS · IA · arquitetura · mercado
- Novos estudos de arquitetura e deep-dives quando saem
- Sínteses diretas — profundidade sem ruído
- Sem spam · double opt-in · cancele quando quiser