03 - AWS Auto Scaling Groups (EC2)
video: https://youtu.be/... no frontmatter da nota.AWS Auto Scaling Groups (EC2)
O Auto Scaling Group (ASG) é o recurso da AWS que mantém um conjunto de instâncias EC2 em quantidade e saúde desejadas, adicionando e removendo unidades conforme políticas de escala e verificações de saúde. Ele é o alicerce da elasticidade em workloads de instâncias: aplicações HTTP atrás de um ELB, workers que consomem filas, ambientes de batch e componentes que exigem controle do sistema operacional. O ASG combina três funções que operam juntas: garantia de capacidade, com mínimo, desejado e máximo; auto recuperação, substituindo instâncias não saudáveis; e escala automática, reagindo a políticas de target tracking, step ou agendamento. Em produção, dominar o ASG é dominar a relação entre capacidade, custo e disponibilidade no nível mais básico da nuvem AWS. Este registro cobre o launch template, os parâmetros de capacidade, os health checks, o ciclo de substituição de instâncias, o warm-up e a integração com balanceadores e zonas de disponibilidade.
Conceito e problema que resolve
O problema clássico de infraestrutura tradicional é a capacidade fixa: compras para o pico e paga ociosidade, ou dimensiona para a média e derruba o sistema no pico. O ASG resolve com três mecanismos integrados. Primeiro, o grupo garante a quantidade desejada de instâncias saudáveis, repovoando automaticamente o que falha. Segundo, políticas de escala ajustam a quantidade desejada conforme métricas, horários ou alarmes. Terceiro, a integração com ELB e Target Groups distribui tráfego apenas para instâncias saudáveis e registradas, sem configuração manual.
O resultado operacional é a conversão de uma tarefa de operação em um objeto declarativo. O time não gerencia instâncias individualmente; gerencia um grupo com regras. Instâncias vêm e vão com IDs diferentes, e nada dependente de host deve sobreviver nelas, o que reforça o desenho stateless e imutável: novas instâncias nascem de uma AMI e de user data idênticos, sem configuração manual residual.
Launch template: o molde da instância
O launch template define tudo que uma instância precisa para nascer: AMI, tipo de instância, par de chaves, security groups, user data, bloco de volumes, IAM instance profile e tags. Ele substitui o antigo launch configuration, que era imutável, e passa a ser versionado: cada alteração gera uma nova versão, e o ASG pode apontar para a versão mais recente ou para uma fixa. Esse versionamento é a base de estratégias de atualização controlada, como instance refresh, que substitui gradualmente as instâncias do grupo pela nova versão do template.
| Elemento do template | Função | Cuidado em produção |
|---|---|---|
| AMI | Imagem base do sistema operacional e da aplicação | Construa por pipeline; nunca use AMI manual |
| Instance type | Capacidade de CPU e memória | Diversifique tipos com grupos de capacidade |
| IAM instance profile | Permissões da instância na AWS | Menor privilégio por papel do grupo |
| User data | Bootstrap na inicialização | Idempotente; testado com a AMI |
| Security groups | Regras de rede de entrada e saída | Restrito ao necessário; sem SSH amplo |
| EBS / volumes | Disco raiz e adicionais | Deletar on termination decidido explicitamente |
A AMI merece atenção especial: o padrão saudável é uma esteira de golden images construída no CI, com sistema atualizado, agente de observabilidade instalado e aplicação baked, ou, alternativamente, uma AMI genérica que baixa a aplicação no boot. A primeira abordagem reduz o tempo de boot e o risco de falha externa no provisionamento; a segunda simplifica o pipeline. Ambas funcionam, desde que o template seja tratado como código versionado.
O exemplo a seguir mostra um trecho de launch template típico de produção, com bootstrap idempotente.
{
"LaunchTemplateName": "api-lt",
"ImageId": "ami-0abc123def456",
"InstanceType": "m7g.large",
"IamInstanceProfile": { "Name": "api-instance-profile" },
"SecurityGroupIds": ["sg-api-privado"],
"BlockDeviceMappings": [
{
"DeviceName": "/dev/xvda",
"Ebs": { "VolumeSize": 30, "VolumeType": "gp3", "DeleteOnTermination": true }
}
],
"MetadataOptions": {
"HttpTokens": "required",
"HttpPutResponseHopLimit": 2
},
"UserData": "IyEvYmluL2Jhc2gK# base64 da configuração de bootstrap da aplicação"
}
O detalhamento de segurança importa em produção: exigir IMDSv2 com HttpTokens required elimina a variante antiga de metadados que facilitou ataques de SSRF, e o instance profile com menor privilégio evita que a exploração de uma instância comprometa a conta inteira.
Capacidade desejada, mínima e máxima
Os três parâmetros numéricos definem a moldura de operação do grupo. O mínimo é o piso de disponibilidade, tipicamente duas instâncias para tolerar uma falha. O desejado é o tamanho corrente, alterado pelas políticas de escala e pela restauração automática. O máximo é o teto de custo e de proteção, e deve ser coerente com as cotas de serviço da conta e com a capacidade real do banco e dos serviços downstream.
# Cria o grupo com moldura de capacidade e distribuição em três AZs
aws autoscaling create-auto-scaling-group \
--auto-scaling-group-name api-producao \
--launch-template LaunchTemplateName=api-lt,Version='$Latest' \
--min-size 2 --max-size 12 --desired-capacity 4 \
--vpc-zone-identifier "subnet-a,subnet-b,subnet-c" \
--health-check-type ELB \
--health-check-grace-period 180 \
--target-group-arns arn:aws:elasticloadbalancing:sa-east-1:123456789012:targetgroup/api/abc \
--capacity-rebalance \
--tag Key=Time,Value=pedidos,PropagateAtLaunch=true
# Política de escala mantendo 60% de CPU média
aws autoscaling put-scaling-policy \
--auto-scaling-group-name api-producao \
--policy-name api-cpu-60 \
--policy-type TargetTrackingScaling \
--target-tracking-configuration '{
"TargetValue": 60.0,
"PredefinedMetricSpecification": {
"PredefinedMetricType": "ASGAverageCPUUtilization"
}
}'
# Inspeção do estado atual do grupo e das instâncias
aws autoscaling describe-auto-scaling-groups \
--auto-scaling-group-names api-producao \
--query 'AutoScalingGroups[0].{desejado:DesiredCapacity,instancias:Instances[*].{id:InstanceId,az:AvailabilityZone,saudavel:HealthStatus}}'
A escolha do mínimo merece análise de custo e de disponibilidade: um mínimo de 1 evita custo, mas derruba o serviço quando a única instância falha ou é substituída. Em serviços críticos, o mínimo deve cobrir a perda de uma zona de disponibilidade, e a distribuição das sub-redes no parâmetro de zonas precisa refletir essa intenção.
Health checks e substituição de instância
O ASG determina a saúde de cada instância por checks configuráveis: EC2, que observa apenas o estado do hypervisor, e ELB, que valida se o balanceador consegue alcançar a aplicação nas portas dos Target Groups. O ELB check é o correto para aplicações HTTP, pois captura falhas que o sistema operacional não reporta, como processo travado respondendo conexões recusadas. O health check grace period dá tempo do boot antes de julgar a instância morta; configurá-lo curto demais cria o ciclo de matar instâncias ainda subindo.
Quando uma instância é considerada não saudável, o fluxo automático é: registrar evento, remover a instância do Target Group para cessar tráfego novo, terminar a instância e criar uma substituição a partir do launch template. Com o parâmetro de instance scale-in protection, instâncias críticas podem ser protegidas de remoção durante scale down, e com capacity rebalance, o grupo reage a interrupções de spot antecipando a substituição antes da interrupção efetiva.
O instance refresh completa o ciclo de atualização: em vez de deploys manuais nas instâncias, o time publica uma nova versão do launch template e dispara o refresh, que substitui as instâncias em ondas respeitando um warm-up e um limite de porcentagem pronta, com rollback automático se o health check falhar. É o mecanismo de deploy do próprio ASG, adequado quando a aplicação está baked na AMI.
Hooks de ciclo de vida
Os lifecycle hooks permitem executar ações em pontos de transição do ciclo de vida da instância: antes de entrar em serviço no scale out e antes de ser terminada no scale down. No evento de lançamento, a instância fica em estado pending-wait até o hook ser completado, dando janela para instalar agentes, registrar em service discovery ou aquecer caches. No evento de encerramento, a instância entra em terminating-wait, e o time pode drenar conexões, finalizar tarefas em andamento e enviar métricas de despedida.
# Hook de encerramento: 120 segundos para drenar conexões e finalizar trabalho
aws autoscaling put-lifecycle-hook \
--auto-scaling-group-name api-producao \
--lifecycle-hook-name drenar-conexoes \
--lifecycle-transition autoscaling:EC2_INSTANCE_TERMINATING \
--heartbeat-timeout 120 \
--default-result CONTINUE
# A instância drenada notifica o hook, por exemplo via Lambda no EventBridge,
# e o encerramento prossegue após o timeout ou após complete-lifecycle-action
aws autoscaling complete-lifecycle-action \
--auto-scaling-group-name api-producao \
--lifecycle-hook-name drenar-conexoes \
--lifecycle-action-result CONTINUE \
--instance-id i-0abc123def456
O padrão comum combina o hook com uma função Lambda disparada pelo EventBridge no evento de terminação, que consulta o serviço para decidir se a instância pode ir: fila vazia, requisições em voo concluídas, checkpoints salvos. Sem esse cuidado, o scale down deixa trabalho inacabado, e o sistema fica lento até o retry automático resgatar a tarefa perdida.
Warm-up, cool-down e políticas de escala
A interação entre escala e boot é onde residem os erros mais custosos. O warm-up period informa ao controlador quanto tempo uma instância nova leva para estar pronta, e as métricas dessa instância não são contadas no cálculo das políticas durante esse período. Sem isso, a política lê CPU alta das instâncias em bootstrap, adiciona mais instâncias desnecessárias e encarece o pico. O cool-down, herdado das políticas simples, impede ações em sequência enquanto o sistema absorve a mudança anterior.
A recomendação prática é configurar o warm-up com o valor medido do boot real, não estimado: se a instância leva 90 segundos até o health check passar, warm-up de 120 segundos dá folga. Para workloads spot, o capacity rebalance combinado com diversificação de tipos em duas ou três famílias reduz o risco de interrupções concentradas. As políticas em si seguem o que o arquivo de políticas de escala detalha; aqui, o ponto central é que o comportamento do ASG como um todo depende tanto dos números quanto dos períodos de estabilização.
Integração com ELB e zonas de disponibilidade
A integração com o Elastic Load Balancing é bidirecional: o ASG registra instâncias nos Target Groups especificados, e o ELB alimenta o ASG com sinais de saúde. O atributo de requisições por alvo permite políticas que escalam pelo tráfego efetivo, e o connection draining do ELB, chamado de deregistration delay, garante que instâncias removidas concluam requisições em voo. Sem esse atraso configurado corretamente, o scale down produz erros 502 visíveis ao cliente.
Zonas de disponibilidade entram em dois níveis. No agendamento, o ASG distribui instâncias entre as sub-redes informadas, buscando equilíbrio entre zonas. Em caso de falha de zona, o controlador tenta repor capacidade nas zonas restantes, e a quantidade mínima deve ser dimensionada para sobreviver a esse cenário. Regras adicionais, como instâncias mínimas por zona, protegem serviços sensíveis a latência que precisam estar sempre perto de consumidores em cada região.
Erros comuns e boas práticas
A lista de problemas recorrentes concentra-se em configuração de saúde, custos e desenho stateless.
- Grace period curto demais, gerando loop de substituição de instâncias em aplicações de boot lento; meça o boot e configure com folga.
- Health check do tipo EC2 para aplicações web, que não detecta processo travado; use ELB sempre que houver Target Group.
- Estado em disco local e sessão em memória, quebrando a substituição de instâncias; extraia para serviços compartilhados antes de habilitar escala.
- Falta de diversificação de tipos com spot, concentrando o risco de interrupção; use grupos de capacidade com múltiplas famílias.
- Máximo sem alarme e sem relação com cotas, transformando picos em surpresa de custo ou falha por limite de conta.
- Encerramento sem drenagem, causando erros no cliente; configure deregistration delay e hooks de ciclo de vida para finalizar trabalho em curso.
Boas práticas consolidam a operação madura do grupo. Trate o launch template como código, com esteira de AMI e revisão por pull request; configure mínimo que sobreviva à perda de uma zona; monitore a capacidade atingida com alarmes nos limites; use instance refresh para deploys imutáveis; e valide a elasticidade com testes de carga que percorram a curva completa de crescimento e redução. O ASG é maduro, estável e previsível, e recompensa configuração disciplinada com disponibilidade contínua a custo variável.