2 minute read

Introducción

AWS Route 53 es un servicio de DNS altamente disponible y escalable. En este artículo, exploraremos cómo implementar y gestionar una infraestructura DNS completa en AWS utilizando Terraform.

Route 53 Architecture

Configuración de Zona Hospedada

# Zona DNS pública
resource "aws_route53_zone" "main" {
  name = "example.com"

  tags = {
    Environment = "Production"
    ManagedBy   = "Terraform"
  }
}

# Zona DNS privada
resource "aws_route53_zone" "private" {
  name = "internal.example.com"

  vpc {
    vpc_id = aws_vpc.main.id
  }

  tags = {
    Environment = "Production"
    Type        = "Private"
  }
}

Gestión de Registros DNS

# Registro A simple
resource "aws_route53_record" "www" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "www.example.com"
  type    = "A"
  ttl     = "300"
  records = ["203.0.113.1"]
}

# Registro ALIAS para ALB
resource "aws_route53_record" "alb" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "app.example.com"
  type    = "A"

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

# Registro de validación ACM
resource "aws_route53_record" "cert_validation" {
  for_each = {
    for dvo in aws_acm_certificate.main.domain_validation_options : dvo.domain_name => {
      name    = dvo.resource_record_name
      record  = dvo.resource_record_value
      type    = dvo.resource_record_type
    }
  }

  allow_overwrite = true
  name            = each.value.name
  records         = [each.value.record]
  ttl             = 60
  type            = each.value.type
  zone_id         = aws_route53_zone.main.zone_id
}

Políticas de Enrutamiento Avanzadas

# Política de latencia
resource "aws_route53_record" "latency" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "api.example.com"
  type    = "A"

  latency_routing_policy {
    region = "us-west-2"
  }

  set_identifier = "us-west-2"
  records        = ["203.0.113.2"]
}

# Política de failover
resource "aws_route53_record" "primary" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "app.example.com"
  type    = "A"

  failover_routing_policy {
    type = "PRIMARY"
  }

  set_identifier = "primary"
  records        = ["203.0.113.3"]
  health_check_id = aws_route53_health_check.primary.id
}

resource "aws_route53_record" "secondary" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "app.example.com"
  type    = "A"

  failover_routing_policy {
    type = "SECONDARY"
  }

  set_identifier = "secondary"
  records        = ["203.0.113.4"]
}

Health Checks

resource "aws_route53_health_check" "primary" {
  fqdn              = "primary.example.com"
  port              = 443
  type              = "HTTPS"
  resource_path     = "/health"
  failure_threshold = "3"
  request_interval  = "30"

  tags = {
    Name = "primary-health-check"
  }
}

Integración con CloudFront

resource "aws_route53_record" "cdn" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "cdn.example.com"
  type    = "A"

  alias {
    name                   = aws_cloudfront_distribution.main.domain_name
    zone_id                = aws_cloudfront_distribution.main.hosted_zone_id
    evaluate_target_health = false
  }
}

Gestión Multi-región

# Política de geolocalización
resource "aws_route53_record" "geo" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "www.example.com"
  type    = "A"

  geolocation_routing_policy {
    country = "ES"
  }

  set_identifier = "spain"
  records        = ["203.0.113.5"]
}

# Política de peso
resource "aws_route53_record" "weighted" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "api.example.com"
  type    = "A"

  weighted_routing_policy {
    weight = 90
  }

  set_identifier = "primary"
  records        = ["203.0.113.6"]
}

Monitorización y Logs

resource "aws_route53_query_log" "main" {
  depends_on = [aws_cloudwatch_log_resource_policy.route53-query-logging]

  cloudwatch_log_group_arn = aws_cloudwatch_log_group.route53.arn
  zone_id                  = aws_route53_zone.main.zone_id
}

resource "aws_cloudwatch_log_group" "route53" {
  name              = "/aws/route53/${aws_route53_zone.main.name}"
  retention_in_days = 30
}

Referencias.