Home Comunidade Eventos YouTube Networks Desafios // produtos Academy News CTI | CVE Contato

04 - AWS ECS Auto Scaling (Service Auto Scaling)

#application auto scaling#auto scaling#ecs#fargate
video explicativo
Video explicativoEspaco reservado para o video desta anotação — adicione 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.