AWS Certified CloudOps Engineer - Associate

Grupos de EC2 Auto Scaling

Como um Auto Scaling group mantém uma frota no tamanho que você pediu: os três números de capacidade, os health checks que decidem o que é substituído, o balanço entre zonas e as regras que escolhem qual instância morre no scale in.

Intermediário 26 minutos 5 Objetivos de aprendizado
  1. Explicar como capacidade mínima, desejada e máxima interagem, e qual delas uma política de escala realmente altera
  2. Identificar as fontes de health check que um Auto Scaling group usa e configurar o grace period para que instâncias de boot lento sobrevivam à inicialização
  3. Prever como um Auto Scaling group distribui e reequilibra instâncias entre Availability Zones
  4. Percorrer a política de terminação padrão até a instância específica que ela encerraria
  5. Declarar o que a proteção contra scale in impede e o que ela não impede

Uma empresa de mídia roda 12 instâncias EC2 atrás de um Application Load Balancer. O pico de tráfego dura cerca de 3 horas nas noites de dias úteis. No resto da semana, 3 instâncias dariam conta com folga, mas a frota fica em 12 porque ninguém quer ser a pessoa que reduziu o tamanho na semana anterior a um lançamento. Aí, num sábado, uma instância enche o disco, para de responder e fica ali morta até segunda de manhã, porque nenhum health check estava ligado a algo capaz de agir.

São 2 falhas diferentes, e um Auto Scaling group resolve as duas com o mesmo mecanismo. Ele é um grupo de instâncias EC2 que a AWS mantém no tamanho que você declara, lançando e encerrando instâncias para segurar esse tamanho, e substituindo qualquer instância que pare de parecer saudável. As políticas de escala que fazem o tamanho se mexer vêm na próxima lição. Esta cobre a mecânica embaixo delas, porque quase toda questão de escala que dá errado em produção dá errado aqui, e não na política.

Três números, e a política mexe em apenas um

Um Auto Scaling group é definido por 3 valores de capacidade.

  • Capacidade mínima é um piso. O grupo nunca roda menos instâncias que isso.
  • Capacidade máxima é um teto. O grupo nunca roda mais.
  • Capacidade desejada é o número que o grupo está de fato tentando rodar agora.

Digamos que você defina mínimo 2, desejado 6, máximo 12. O grupo lança 6 instâncias. Se uma política de escala depois calcular que são necessárias 15 instâncias para segurar a CPU no alvo, o grupo vai a 12 e para, porque 15 está acima do teto. Se um cálculo de scale in disser que 1 instância basta, o grupo vai a 2 e para.

A frase que vale memorizar: uma política de escala muda a capacidade desejada, e só ela. Mínimo e máximo são limites que restringem o resultado. É aqui que mora uma leitura errada comum. Definir capacidade máxima 12 não significa que o grupo roda 12 instâncias. Significa que o grupo nunca vai rodar mais que 12. Um grupo parado no máximo porque a capacidade desejada foi levada até lá é uma situação completamente diferente de um grupo em 6 com folga até 12, e a prova gosta de enunciados em que o grupo já bateu no teto e a política de escala parece quebrada.

Também existe valor num grupo sem nenhuma política de escala. Com a capacidade desejada fixa em 6, o grupo continua observando essas 6 instâncias e substituindo qualquer uma que reprove num health check. Manter capacidade e escalar capacidade são recursos separados, e o primeiro é a razão de um grupo valer a pena mesmo para uma frota cujo tamanho nunca muda.

O launch template é a planta

O grupo precisa saber o que lançar. Isso vem de um launch template: AMI ID, tipo de instância, key pair, security groups, IAM instance profile, block device mappings, user data e o resto da superfície de launch do EC2.

Launch templates são versionados. Você cria a versão 3 com uma AMI nova, aponta o grupo para ela, e toda instância lançada a partir daquele momento usa a versão 3 enquanto as existentes seguem rodando o que lançaram. Esse histórico de versões é o que faz a política de terminação padrão e o instance refresh funcionarem, e os dois aparecem mais adiante.

O launch configuration, mais antigo, ainda aparece em material velho e em contas velhas. Ele não é versionado, não pode ser editado (você o substitui) e a AWS não o estende para recursos novos do EC2. Trate "migrar o grupo de launch configuration para launch template" como a resposta esperada sempre que um cenário mencionar Spot e On-Demand no mesmo grupo, múltiplos tipos de instância ou um instance refresh, porque nada disso funciona com launch configuration.

Health checks decidem o que é substituído

Uma instância num Auto Scaling group começa Healthy e continua assim até algo dizer o contrário ao grupo. O grupo escuta várias fontes:

FonteO que reportaLigada por padrão
Status checks do Amazon EC2Falhas de system e instance status check, e qualquer estado diferente de runningSim
Elastic Load BalancingA saúde do target no target group associadoNão, você habilita
VPC LatticeSaúde do target num target group do LatticeNão, você habilita
Amazon EBSUm volume associado está degradadoNão, você habilita
PersonalizadaO que o seu código reportar com set-instance-healthSeu código chama

Essa tabela esconde a configuração errada mais comum do tópico, então vale dizer em voz alta. Por padrão um Auto Scaling group usa apenas os status checks do EC2. Uma instância cuja aplicação devolve HTTP 500 em toda requisição continua passando nos status checks do EC2, porque o hypervisor está bem e o sistema operacional está rodando. O ALB vai perceber, marcar o target como doente e parar de mandar tráfego. O Auto Scaling group não vai substituir a instância, e você termina com um grupo reportando 6 instâncias saudáveis atrás de um target group reportando 5 targets saudáveis, indefinidamente. Habilitar o health check do Elastic Load Balancing no grupo é o que fecha esse buraco.

aws autoscaling update-auto-scaling-group \
  --auto-scaling-group-name web-asg \
  --health-check-type ELB \
  --health-check-grace-period 300

O health check grace period daquele comando é a segunda coisa a acertar. Ele é o tempo mínimo em que uma instância recém-colocada em serviço fica em paz antes que um veredito de doente possa encerrá-la. Os health checks do Elastic Load Balancing começam assim que a instância é registrada, então uma aplicação que precisa de 4 minutos para aquecer caches reprovaria nos primeiros checks e morreria por isso. O grace period compra esse tempo.

Os padrões não são os mesmos em todo lugar, e essa é uma armadilha real:

  • Console: 300 segundos
  • AWS CLI ou SDK: 0 segundos, o que desliga o grace period por completo

Um grupo criado por um template do CloudFormation ou por um script de CLI sem grace period explícito vai portanto julgar as instâncias desde o primeiro segundo, e uma frota de boot lento pode cair num loop em que toda substituta é morta antes de terminar de bootar. Uma exceção vale durante o grace period: se a instância sair do estado running do EC2, por exemplo porque alguém a parou, o grupo a marca Unhealthy e substitui na hora, sem esperar.

Não resolva o problema empurrando o grace period para uma hora. Um grace period alto é tempo morto em que uma instância genuinamente quebrada segue em serviço. O melhor conserto, coberto na lição de lifecycle, é um lifecycle hook de launch que segura a instância fora de serviço até o bootstrap terminar, o que permite deixar o grace period baixo.

Mais 2 comportamentos que vale guardar: a substituição por health check não espera período de cooldown, e uma instância que o grupo já marcou como doente pula inteiramente a avaliação da política de terminação. Instâncias doentes não são escolhidas, elas são simplesmente removidas.

O balanço entre zonas vem antes de tudo

Você entrega subnets ao grupo, e cada subnet vive em exatamente uma Availability Zone. Quando o grupo lança uma instância, ele escolhe a zona habilitada com menos instâncias e, dentro dela, a subnet com mais endereços IP livres. Quando encerra, ele olha primeiro a zona com mais instâncias.

Essa ordem importa mais do que parece. O balanço entre zonas é avaliado antes da política de terminação, sempre. Então um grupo com 5 instâncias em us-east-1a e 3 em us-east-1b vai encerrar em us-east-1a mesmo que a instância mais antiga do grupo esteja em us-east-1b. Quando um cenário diz "a instância mais nova foi encerrada e não entendemos por quê", desequilíbrio entre zonas costuma ser a resposta.

Grupos saem do equilíbrio por motivos comuns: uma zona ficou sem capacidade por um tempo e voltou, você mudou as zonas habilitadas, você colocou instâncias em standby, ou o preço de Spot voltou a ficar abaixo do seu máximo numa zona que estava cara demais. Quando isso acontece, o grupo roda uma atividade de rebalanceamento entre Availability Zones. Ele lança a instância nova primeiro e encerra a antiga depois, então o rebalanceamento nunca derruba sua capacidade.

Lançar antes de encerrar cria um problema óbvio quando o grupo já está na capacidade máxima, e a AWS resolveu com uma exceção documentada: durante uma atividade de rebalanceamento o grupo pode ultrapassar temporariamente a capacidade máxima em 10 por cento ou uma instância, o que for maior. A margem dura só o rebalanceamento, normalmente alguns minutos. Se você não tolera nem esse excesso, uma instance maintenance policy permite definir a faixa de percentual saudável no lugar disso.

Qual instância morre no scale in

Escolhida a zona, a política de terminação padrão percorre as instâncias desprotegidas nesta ordem:

  1. Configurações desatualizadas primeiro. Num grupo com launch templates, isso quer dizer instâncias lançadas por launch configuration, depois instâncias lançadas por um launch template diferente, depois instâncias na versão mais antiga do launch template atual.
  2. Mais próxima da próxima hora de cobrança. Se sobrarem vários candidatos, o grupo pega o mais próximo da próxima hora de cobrança e desempata aleatoriamente. Esse passo importa muito menos do que já importou, já que a maior parte do uso de EC2 é cobrada por segundo.

O objetivo do desenho é aposentar configurações velhas naturalmente conforme o grupo faz scale in, e é por isso que um grupo que sobe e desce ao longo do dia converge devagar para a versão atual do launch template sem ninguém fazer nada.

Grupos de mixed instances acrescentam um passo na frente. O grupo primeiro decide se deve sair uma instância Spot ou uma On-Demand, para a frota voltar à proporção que você configurou, depois verifica se encerrar uma instância específica melhora o alinhamento com sua allocation strategy, e só então cai em configurações desatualizadas e hora de cobrança.

Você pode sobrepor a política quando o padrão não serve ao seu caso:

PolíticaEncerraUse quando
DefaultConfiguração desatualizada, depois mais próxima da próxima hora de cobrançaQuase sempre
OldestInstanceA instância que está no ar há mais tempoRolando a frota para um novo tipo de instância
NewestInstanceA instância lançada mais recentementeTestando uma configuração nova que você quer reverter primeiro
OldestLaunchTemplateTemplates não atuais primeiro, depois a versão mais antigaAposentando uma configuração anterior
OldestLaunchConfigurationO launch configuration mais antigoMigrando para fora de launch configurations
ClosestToNextInstanceHourO mais próximo da fronteira da hora de cobrançaApenas instâncias cobradas por hora
AllocationStrategyInstâncias que afastam a frota da sua allocation strategyPools de Spot ou prioridades de On-Demand mudaram

Qualquer que seja a escolha, o balanço entre zonas continua ganhando primeiro. Uma política de terminação só decide qual instância dentro da zona selecionada vai embora.

Proteger uma instância contra scale in, e o que isso não compra

Algumas instâncias não deveriam ser escolhidas. Um host de contêiner no meio de um job, um build agent 40 minutos dentro de uma compilação, um nó segurando uma sessão longa. A proteção de instância contra scale in marca a instância como inelegível para terminação por um evento de scale in. Você pode ligar isso no grupo para que toda instância nova herde a proteção, e depois limpar por instância quando o trabalho acabar, que é o padrão usado por schedulers de contêiner.

A metade importante desse recurso é o que ele não faz. A proteção contra scale in não impede:

  • Substituição depois de um health check reprovado
  • Interrupção de uma Spot Instance
  • O fim de uma reserva de Capacity Block
  • Terminação manual via terminate-instance-in-auto-scaling-group
  • Terminação manual pelo console, CLI ou API do EC2

Esse último surpreende. Para impedir que uma pessoa encerre a instância pelo console do EC2 você precisa da termination protection do EC2, um ajuste separado, na própria instância. Os 2 nomes parecem o mesmo recurso e não são.

Um caso de borda aparece em incidentes reais: se toda instância do grupo está protegida e um evento de scale in dispara, o grupo decrementa a capacidade desejada mas não consegue encerrar nada. O histórico de atividades registra Could not scale to desired capacity because all remaining instances are protected from scale in, e o grupo roda silenciosamente acima da própria capacidade desejada até a proteção ser limpa em algum lugar.

Desligar partes do grupo enquanto você trabalha

Quando você precisa que o grupo pare de agir por um tempo, suspenda processos individuais em vez de apagar políticas:

ProcessoSuspendê-lo para
LaunchAdicionar instâncias por qualquer motivo, incluindo abastecer warm pool
TerminateRemover instâncias por qualquer motivo
AddToLoadBalancerRegistrar instâncias novas no target group
AlarmNotificationPolíticas de dynamic scaling reagirem aos alarmes do CloudWatch
AZRebalanceRebalanceamento entre Availability Zones
HealthCheckMarcar instâncias como doentes a partir de sinais de EC2 ou ELB
ReplaceUnhealthyEncerrar e substituir instâncias já doentes
InstanceRefreshSubstituições de instance refresh
ScheduledActionsScheduled scaling

Escolher o certo é uma questão de diagnóstico. Suspender Launch para o rodízio mas também bloqueia um scale out agendado que você talvez ainda queira; suspender ReplaceUnhealthy para apenas o loop de substituição. E se um grupo estiver falhando em lançar instâncias por mais de umas 24 horas, a AWS aplica uma suspensão administrativa por conta própria. Quando alguém reportar que um grupo "simplesmente parou de funcionar", verifique os processos suspensos antes de verificar a política.

Dicas para a prova

  • Um cenário em que o grupo se recusa a crescer e a política parece correta é questão de capacidade máxima. Leia os 3 números antes de ler a política.
  • "O load balancer mostra o target doente mas a instância nunca é substituída" é sempre o tipo de health check. O grupo usa apenas status checks do EC2 por padrão.
  • "As instâncias são encerradas e relançadas em loop logo depois do launch" é o health check grace period, e a pista é um grupo criado por CLI ou CloudFormation, onde o padrão é 0 em vez dos 300 do console.
  • Não confunda os 2 timers. Health check grace period é quanto tempo até os health checks poderem matar uma instância nova. Default cooldown, 300 segundos, é uma pausa entre atividades de simple scaling e pertence à próxima lição.
  • "Uma instância mais nova foi encerrada antes de uma mais velha" significa que as zonas estavam desequilibradas. O balanço entre zonas supera a política de terminação.
  • Qualquer coisa sobre Spot mais On-Demand num mesmo grupo, múltiplos tipos de instância ou instance refresh elimina launch configurations. A resposta precisa de launch template.
  • Proteção contra scale in bloqueia apenas scale in. Se o enunciado diz health check, interrupção de Spot ou uma pessoa clicando em Terminate no console, a proteção é a resposta errada.

O modelo para levar à próxima lição é estreito e sustenta tudo: o grupo tem um botão que ele mexe, a capacidade desejada, e um conjunto de regras sobre como as instâncias são criadas, julgadas e escolhidas para remoção em volta dele. Tudo o que vem depois, target tracking, step scaling, predictive scaling, é uma forma diferente de decidir quanto esse único número deveria ser.