04 - AWS ECS Auto Scaling (Service Auto Scaling)
video: https://youtu.be/... no frontmatter da nota.AWS ECS Auto Scaling (Service Auto Scaling)
O Service Auto Scaling do ECS ajusta automaticamente o número de tasks de um service conforme métricas de carga, usando o Application Auto Scaling como motor. É o equivalente funcional do HPA no mundo ECS, com a particularidade de operar sobre task count, não sobre pods, e de interagir com o cluster capacity provider para garantir que exista infraestrutura onde as tasks novas rodarão. Em produção, essa peça fecha o circuito da elasticidade em arquiteturas ECS: o ALB distribui tráfego, o service mantém saúde, e a escala reage a CPU, memória, requisições por alvo ou métricas customizadas do CloudWatch. A relevância prática é alta, pois a maioria dos workloads Fargate em produção depende dessa camada para equilibrar custo e disponibilidade em padrões de tráfego variáveis. Este registro cobre a arquitetura do Application Auto Scaling, as métricas predefinidas, a configuração de uma política completa e as interações finas com capacity providers e deploys.
Arquitetura: Application Auto Scaling aplicado ao ECS
O Application Auto Scaling é o serviço genérico de escala da AWS para recursos que não são EC2 nem DynamoDB: serviços ECS, endpoints SageMaker, tabelas DynamoDB e outros. Ele mantém o modelo de três camadas: um Scaling Target, que é o recurso escalável, no caso o service ECS; políticas de escala, que definem como decidir; e ações registradas no CloudWatch, que observam métricas. O controlador lê a métrica, calcula o ajuste desejado e executa a chamada de atualização de task count no service.
A distinção importante para o ECS é que a escala acontece em dois níveis. A escala do service altera o número desejado de tasks; a escala do cluster, conduzida pelos capacity providers, garante que exista EC2 ou capacidade gerenciada para acomodar essas tasks quando o launch type é EC2. No Fargate, a segunda camada é invisível, pois a capacidade é provisionada sob demanda, o que explica por que a combinação Fargate mais service auto scaling é a mais simples de operar.
| Camada | Componente | Função |
|---|---|---|
| Observação | CloudWatch metrics | CPU, memória, requisições por alvo, métricas customizadas |
| Decisão | Application Auto Scaling | Calcula o novo task count a partir do alvo |
| Execução | ECS Service | Atualiza desired count e orquestra tasks |
| Capacidade | Capacity provider / Fargate | Garante infraestrutura para as tasks novas |
| Registro | CloudWatch alarms e eventos | Visibilidade, auditoria e reação a limites |
Métricas predefinidas e alvo
O Application Auto Scaling oferece três métricas predefinidas para serviços ECS. A ECSServiceAverageCPUUtilization mede a utilização média de CPU das tasks do service, calculada pela plataforma. A ECSServiceAverageMemoryUtilization faz o mesmo para memória. E a ALBRequestCountPerTarget usa as requisições do Target Group do ALB por task, sendo a métrica mais fiel a cargas HTTP cuja resposta depende de concorrência, não de processamento.
A escolha segue o mesmo raciocínio do arquivo de políticas gerais: CPU e memória servem quando o trabalho é proporcional a processamento; requisições por alvo serve quando o gargalo é concorrência e a mistura de requisições é estável. Um detalhe prático do ALBRequestCountPerTarget é a exigência do ResourceLabel, que identifica o ALB e o Target Group no formato app/nome/id/targetgroup/nome/id, e a exigência de que o service já esteja registrado no Target Group.
# Registra o service como alvo escalável, com limites mínimos e máximos
aws application-autoscaling register-scalable-target \
--service-namespace ecs \
--scalable-dimension ecs:service:DesiredCount \
--resource-id service/producao/pedidos-api \
--min-capacity 2 \
--max-capacity 20
# Política de target tracking por CPU média do service
aws application-autoscaling put-scaling-policy \
--service-namespace ecs \
--scalable-dimension ecs:service:DesiredCount \
--resource-id service/producao/pedidos-api \
--policy-name pedidos-cpu-60 \
--policy-type TargetTrackingScaling \
--target-tracking-configuration '{
"TargetValue": 60.0,
"PredefinedMetricSpecification": {
"PredefinedMetricType": "ECSServiceAverageCPUUtilization"
},
"ScaleOutCooldown": 60,
"ScaleInCooldown": 180
}'
# Política alternativa por requisições por alvo no ALB
aws application-autoscaling put-scaling-policy \
--service-namespace ecs \
--scalable-dimension ecs:service:DesiredCount \
--resource-id service/producao/pedidos-api \
--policy-name pedidos-req-por-alvo \
--policy-type TargetTrackingScaling \
--target-tracking-configuration '{
"TargetValue": 500.0,
"PredefinedMetricSpecification": {
"PredefinedMetricType": "ALBRequestCountPerTarget",
"ResourceLabel": "app/pedidos-alb/1234567890/targetgroup/pedidos/abc123"
}
}'
Configuração completa via infraestrutura como código
O exemplo em Terraform consolida a configuração típica: scalable target com moldura, política por CPU, e política agendada para a parte previsível da demanda. Em ambientes geridos por IaC, essas definições vivem versionadas junto do serviço, não aplicadas manualmente.
# Alvo escalável: o service ECS com moldura de 2 a 20 tasks
resource "aws_appautoscaling_target" "pedidos" {
max_capacity = 20
min_capacity = 2
resource_id = "service/${aws_ecs_cluster.producao.name}/${aws_ecs_service.pedidos.name}"
scalable_dimension = "ecs:service:DesiredCount"
service_namespace = "ecs"
}
# Target tracking mantendo 60% de CPU, com cool-downs explícitos
resource "aws_appautoscaling_policy" "pedidos_cpu" {
name = "pedidos-cpu-60"
policy_type = "TargetTrackingScaling"
resource_id = aws_appautoscaling_target.pedidos.resource_id
scalable_dimension = aws_appautoscaling_target.pedidos.scalable_dimension
service_namespace = aws_appautoscaling_target.pedidos.service_namespace
target_tracking_scaling_policy_configuration {
target_value = 60.0
scale_in_cooldown = 180 # evita redução apressada após picos
scale_out_cooldown = 60 # reage rápido ao crescimento
predefined_metric_specification {
predefined_metric_type = "ECSServiceAverageCPUUtilization"
}
}
}
# Agendamento: mínimo maior durante o horário comercial conhecido
resource "aws_appautoscaling_scheduled_action" "pedidos_hora_comercial" {
name = "pedidos-hora-comercial"
service_namespace = aws_appautoscaling_target.pedidos.service_namespace
resource_id = aws_appautoscaling_target.pedidos.resource_id
scalable_dimension = aws_appautoscaling_target.pedidos.scalable_dimension
schedule = "cron(0 10 * * MON-FRI *)"
scalable_target_action {
min_capacity = 6
max_capacity = 20
}
}
A leitura do exemplo evidencia o padrão de composição: a moldura define o possível, a política reativa cuida do imprevisível e o agendamento antecipa o conhecido. Cool-downs explícitos são preferíveis aos padrões quando o perfil de boot das tasks é conhecido, pois tasks com inicialização longa precisam de janela maior antes de nova decisão.
Interação com capacity providers e deploys
No launch type EC2 com capacity providers, a escala do service precisa de capacidade física no cluster. O autoscaling do grupo de instâncias, conduzido pelo capacity provider strategy com managed scaling habilitado, observa a utilização de CPU e memória das instâncias e adiciona nós quando o bin packing não couber nas tasks pendentes. Em Fargate, esse nível desaparece, e a escala do service é a única a administrar.
A interação com deploys merece atenção em produção. Durante um rolling update, o service sobe tasks novas mantendo o mínimo saudável; se uma política de escala agir simultaneamente, o task count alvo muda por cima do deploy, e o comportamento pode confundir. Recomenda-se estabilizar janelas de deploy, desativar scale down agressivo durante lançamentos e monitorar métricas por revisão de task quando possível. Outro ponto fino é o scale to zero: serviços em ambientes de baixo uso podem reduzir a uma task mínima, mas não a zero em produção sem estratégia de wake-up, pois o ALB exige alvos saudáveis para encaminhar.
Erros comuns e boas práticas
A lista de problemas recorrentes concentra-se em métricas, cool-downs e interação com a infraestrutura subjacente.
- Definir máximos sem relação com a capacidade do cluster em EC2, gerando tasks em estado pending sem recursos para nascer.
- Usar CPU como alvo em serviços dominados por espera de I/O, mantendo a escala estável enquanto a latência cresce; prefira requisições por alvo.
- Scale in sem cool-down adequado, provocando oscilação e churn de tasks com custo de pull de imagem repetido.
- Métrica de memória como único gatilo em aplicações com heap progressivo, onde o uso cresce por retenção e não por carga; trate memória como alarme de vazamento.
- Ignorar o impacto do deploy simultâneo com escala, causando contagens divergentes durante o rollout.
- Faltarem alarmes nos limites, ocultando o momento em que o service bate no máximo e passa a rejeitar carga.
Boas práticas consolidam a operação. Registre a moldura e as políticas via IaC, com revisão por pull request; valide o comportamento com teste de carga antes da primeira exposição real; monitore o task count junto com a métrica alvo, para distinguir saturação de teto de comportamento saudável; e mantenha os cool-downs coerentes com o tempo de boot das tasks, medido e não estimado. O Service Auto Scaling é simples de configurar e poderoso quando as premissas de métrica e capacidade são respeitadas; os incidentes vêm quase sempre de premissas violadas, e não do mecanismo.