DEV Community

Cover image for AWS na prática - balanceamento de carga via DNS com o Route 53
Rafael Dutra for apsis-cc

Posted on

AWS na prática - balanceamento de carga via DNS com o Route 53

1. Um outro tipo de balanceamento

No artigo anterior desta série, subimos instâncias EC2 e as agrupamos em um target group, prontas para receber tráfego de um balanceador de carga tradicional. Mas existe uma camada de decisão que acontece antes de qualquer pacote chegar a um Application Load Balancer: a resolução de nome. Quando um cliente pergunta "qual é o IP de api.minhaempresa.com?", quem responde pode já estar escolhendo, com base em latência, saúde do destino ou uma política de peso, para qual região ou endpoint mandar esse cliente. É esse balanceamento — feito no Route 53, o serviço de DNS da AWS — que vamos explorar aqui.

2. Por que balancear no DNS, se já existe um load balancer

Um ALB/NLB distribui tráfego entre instâncias dentro de uma região. O Route 53 resolve um problema diferente: distribuir tráfego entre regiões, entre contas ou entre serviços completamente distintos, antes mesmo de uma conexão TCP ser aberta. Os dois não são concorrentes — na prática, é comum que registros no Route 53 apontem justamente para ALBs em regiões diferentes, formando duas camadas de balanceamento:

Cliente → Route 53 (escolhe a região) → ALB da região → Target Group → EC2
Enter fullscreen mode Exit fullscreen mode

A diferença central de mecanismo importa: um ALB decide por requisição, em tempo real, olhando para o estado atual de cada destino. O Route 53 decide por resposta de consulta DNS, e o cliente (ou, mais frequentemente, o resolver DNS dele) fica com essa resposta em cache pelo tempo definido no TTL do registro — o que torna o balanceamento por DNS mais grosseiro, porém indispensável quando o requisito é geográfico ou cruza fronteiras que um load balancer sozinho não alcança.

3. Políticas de roteamento do Route 53

O Route 53 suporta várias políticas de roteamento no mesmo nome, cada uma resolvendo um problema diferente:

  • Simple: um registro, uma resposta fixa (ou uma lista, escolhida aleatoriamente pelo cliente). Sem balanceamento real.
  • Weighted: distribui consultas entre múltiplos endpoints por peso relativo — útil para canary release ou para migrar tráfego gradualmente de um ambiente para outro.
  • Latency-based: responde com o endpoint na região com menor latência medida a partir da localização do resolver que fez a pergunta.
  • Failover: mantém um endpoint primário e um secundário, alternando automaticamente quando o health check do primário falha.
  • Geolocation / Geoproximity: roteia com base na localização geográfica de quem pergunta, útil para requisitos de residência de dados ou conteúdo localizado.
  • Multivalue answer: retorna várias respostas saudáveis por consulta, funcionando como um DNS round-robin com health check embutido.

4. Roteamento ponderado (weighted) na prática

Para migrar tráfego gradualmente entre dois ALBs (por exemplo, uma versão antiga e uma nova da aplicação), dois registros com o mesmo nome e pesos diferentes:

aws route53 change-resource-record-sets \
  --hosted-zone-id Z1234567890ABC \
  --change-batch '{
    "Changes": [{
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "api.minhaempresa.com",
        "Type": "A",
        "SetIdentifier": "versao-atual",
        "Weight": 90,
        "AliasTarget": {
          "HostedZoneId": "Z35SXDOTRQ7X7K",
          "DNSName": "alb-antigo-123456.us-east-1.elb.amazonaws.com",
          "EvaluateTargetHealth": true
        }
      }
    }]
  }'
Enter fullscreen mode Exit fullscreen mode

E o segundo registro, apontando para o novo ALB com 10% do tráfego:

aws route53 change-resource-record-sets \
  --hosted-zone-id Z1234567890ABC \
  --change-batch '{
    "Changes": [{
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "api.minhaempresa.com",
        "Type": "A",
        "SetIdentifier": "versao-nova",
        "Weight": 10,
        "AliasTarget": {
          "HostedZoneId": "Z35SXDOTRQ7X7K",
          "DNSName": "alb-novo-654321.us-east-1.elb.amazonaws.com",
          "EvaluateTargetHealth": true
        }
      }
    }]
  }'
Enter fullscreen mode Exit fullscreen mode

Aumentar gradualmente o peso do "versao-nova" (10 → 50 → 100) e reduzir o do "versao-atual" na mesma proporção é uma forma simples de canary release sem depender de lógica de roteamento na aplicação.

5. O mesmo cenário em Terraform

O provider da AWS modela cada registro ponderado como um aws_route53_record com set_identifier e bloco weighted_routing_policy:

resource "aws_route53_record" "api_atual" {
  zone_id        = aws_route53_zone.principal.zone_id
  name           = "api.minhaempresa.com"
  type           = "A"
  set_identifier = "versao-atual"

  weighted_routing_policy {
    weight = 90
  }

  alias {
    name                   = aws_lb.antigo.dns_name
    zone_id                = aws_lb.antigo.zone_id
    evaluate_target_health = true
  }
}

resource "aws_route53_record" "api_nova" {
  zone_id        = aws_route53_zone.principal.zone_id
  name           = "api.minhaempresa.com"
  type           = "A"
  set_identifier = "versao-nova"

  weighted_routing_policy {
    weight = 10
  }

  alias {
    name                   = aws_lb.novo.dns_name
    zone_id                = aws_lb.novo.zone_id
    evaluate_target_health = true
  }
}
Enter fullscreen mode Exit fullscreen mode

6. Failover automático com health check

Para um cenário de disaster recovery — um ambiente primário e um standby em outra região — o Route 53 monitora o endpoint primário e só resolve para o secundário quando ele falha:

aws route53 create-health-check \
  --caller-reference "hc-api-primario-$(date +%s)" \
  --health-check-config '{
    "IPAddress": "203.0.113.10",
    "Port": 443,
    "Type": "HTTPS",
    "ResourcePath": "/healthz",
    "RequestInterval": 30,
    "FailureThreshold": 3
  }'
Enter fullscreen mode Exit fullscreen mode

O HealthCheckId retornado é referenciado nos dois registros de failover:

resource "aws_route53_record" "primario" {
  zone_id         = aws_route53_zone.principal.zone_id
  name            = "api.minhaempresa.com"
  type            = "A"
  set_identifier  = "primario"
  health_check_id = aws_route53_health_check.primario.id

  failover_routing_policy {
    type = "PRIMARY"
  }

  alias {
    name                   = aws_lb.regiao_principal.dns_name
    zone_id                = aws_lb.regiao_principal.zone_id
    evaluate_target_health = true
  }
}

resource "aws_route53_record" "secundario" {
  zone_id        = aws_route53_zone.principal.zone_id
  name           = "api.minhaempresa.com"
  type           = "A"
  set_identifier = "secundario"

  failover_routing_policy {
    type = "SECONDARY"
  }

  alias {
    name                   = aws_lb.regiao_dr.dns_name
    zone_id                = aws_lb.regiao_dr.zone_id
    evaluate_target_health = true
  }
}
Enter fullscreen mode Exit fullscreen mode

Enquanto o health check do primário estiver saudável, todas as consultas recebem o endpoint principal. Assim que três checagens consecutivas falham, o Route 53 passa a responder com o endpoint secundário — sem nenhuma intervenção manual, embora o efeito completo dependa do TTL do registro e do quanto os resolvers dos clientes respeitam esse cache.

7. Uma ressalva importante: TTL e propagação

Diferente de um ALB, que reage a mudanças de saúde de um destino em segundos, uma mudança de resposta no Route 53 só se propaga para novos clientes conforme o TTL do registro expira em cada resolver intermediário — e alguns resolvers ignoram TTLs muito baixos. Para cenários de failover, é comum usar um TTL de 30 a 60 segundos nos registros críticos, aceitando uma janela de indisponibilidade parcial maior do que a de um balanceador de camada 4/7, em troca da capacidade de rotear entre regiões inteiras.

8. Conclusão

Combinar as duas camadas — instâncias EC2 agrupadas em um target group, como vimos no artigo anterior, e políticas de roteamento no Route 53 por cima delas — cobre tanto o balanceamento fino dentro de uma região quanto decisões de mais alto nível: canary release gradual, redução de latência por geografia e failover entre regiões inteiras. A escolha de política (weighted, latency-based, failover) depende do problema: migração gradual de versão pede weighted, presença global pede latency-based, disaster recovery pede failover — e nada impede combinar mais de uma, já que o Route 53 permite políticas aninhadas apontando um conjunto de registros para outro.


Imagem de capa: Logo da AWS — Wikimedia Commons, marca da Amazon.com, Inc. (convertido para PNG via wsrv.nl)

Referências:

  1. Amazon Route 53 — Developer Guide
  2. Route 53 — Choosing a Routing Policy
  3. Terraform Provider: AWS — aws_route53_record

Top comments (0)