AWS Route 53 ile DNS Yönetimi: Kapsamlı Rehber

DNS yönetimi, bir web altyapısının bel kemiğidir ve bunu yanlış yapınca gecenin üçünde telefon almak kaçınılmaz olur. AWS Route 53, hem basit DNS barındırma hem de gelişmiş trafik yönetimi için güçlü bir çözüm sunuyor. Bu yazıda Route 53’ü sıfırdan kurmaktan karmaşık routing politikalarına kadar her şeyi ele alacağız.

Route 53 Nedir ve Neden Kullanılır?

Route 53, AWS’in hem yetkili DNS sunucusu hem de domain kayıt hizmeti sunan tam yönetimli bir servisidir. İsmini ABD’deki Route 66 karayolundan alıyor, DNS’in kullandığı 53 numaralı portla birleşince Route 53 oluyor.

Neden tercih edilmeli sorusunun cevabı birkaç maddeyle özetlenebilir:

  • %100 SLA garantisi: AWS, Route 53 için endüstride eşi olmayan %100 kullanılabilirlik taahhüdünde bulunuyor
  • Global anycast ağı: 100’den fazla PoP (Point of Presence) üzerinden düşük gecikme süreli DNS yanıtları
  • AWS entegrasyonu: ELB, CloudFront, S3 gibi servislerle alias kayıtları sayesinde sorunsuz entegrasyon
  • Health check: DNS düzeyinde sağlık kontrolü ve otomatik failover
  • Traffic routing politikaları: Coğrafi, ağırlıklı, gecikme bazlı ve daha fazla routing seçeneği

Temel Kavramlar

Route 53 ile çalışmadan önce birkaç kavramı netleştirmek gerekiyor.

Hosted Zone: DNS kayıtlarınızı barındıran konteynerdir. Her domain için bir hosted zone oluşturursunuz. Public ve private olmak üzere iki tipi vardır. Private hosted zone’lar yalnızca VPC içinden erişilebilir, bu sayede iç servisleriniz için özel DNS isimleri kullanabilirsiniz.

Record Set: Hosted zone içindeki bireysel DNS kayıtlarıdır. A, AAAA, CNAME, MX, TXT, NS, SOA gibi standart record tipleri desteklenir.

Alias Record: Route 53’e özgü bir kavramdır. CNAME’e benzer ama zone apex’te (örn. example.com) kullanılabilir ve AWS kaynakları için ücretsizdir. Bir ELB veya CloudFront distribution’a alias record oluşturduğunuzda, IP adresi değiştiğinde kayıt otomatik güncellenir.

TTL (Time to Live): DNS yanıtlarının ne kadar süre cache’leneceğini belirtir. Değişiklik planlıyorsanız önceden TTL’i düşürmek kritik önem taşır.

AWS CLI ile Route 53 Yönetimi

Konsol üzerinden Route 53 yönetimi kolaydır ama tekrarlanabilir ve otomasyon dostu bir altyapı için CLI kullanmak şart. Önce temel komutlara bakalım.

Hosted Zone Oluşturma

# Public hosted zone oluşturma
aws route53 create-hosted-zone 
  --name example.com 
  --caller-reference $(date +%s) 
  --hosted-zone-config Comment="Production DNS zone"

# Private hosted zone oluşturma (VPC'ye bağlı)
aws route53 create-hosted-zone 
  --name internal.example.com 
  --caller-reference $(date +%s) 
  --vpc VPCRegion=eu-west-1,VPCId=vpc-0abc123def456 
  --hosted-zone-config Comment="Internal DNS zone",PrivateZone=true

Hosted zone oluşturulduktan sonra size verilen NS (Name Server) kayıtlarını domain kayıt şirketinizdeki nameserver ayarlarıyla güncellemeniz gerekiyor. Bu adımı atlayan sysadmin’lerin “DNS çalışmıyor” diye panik yaptığını çok gördüm.

Mevcut Zone’ları Listeleme

# Tüm hosted zone'ları listele
aws route53 list-hosted-zones --output table

# Belirli bir zone'un ID'sini bul
aws route53 list-hosted-zones 
  --query 'HostedZones[?Name==`example.com.`].Id' 
  --output text

# Zone ID'yi bir değişkene ata (scriptte kullanışlı)
ZONE_ID=$(aws route53 list-hosted-zones 
  --query 'HostedZones[?Name==`example.com.`].Id' 
  --output text | cut -d'/' -f3)
echo "Zone ID: $ZONE_ID"

DNS Kayıtlarını Yönetme

Route 53’te kayıt oluşturma, güncelleme ve silme işlemleri change batch mekanizmasıyla yapılır. JSON formatında bir değişiklik dosyası hazırlayıp bunu API’ye gönderirsiniz.

# A kaydı oluşturma için change batch dosyası
cat > /tmp/create-a-record.json << 'EOF'
{
  "Changes": [
    {
      "Action": "CREATE",
      "ResourceRecordSet": {
        "Name": "web.example.com",
        "Type": "A",
        "TTL": 300,
        "ResourceRecords": [
          {
            "Value": "203.0.113.10"
          }
        ]
      }
    }
  ]
}
EOF

# Değişikliği uygula
aws route53 change-resource-record-sets 
  --hosted-zone-id $ZONE_ID 
  --change-batch file:///tmp/create-a-record.json

Birden fazla kaydı aynı anda oluşturmak veya güncellemek için change batch içine birden fazla entry ekleyebilirsiniz. Bu hem daha hızlı hem de atomik bir işlem olduğu için tutarlılık açısından tercih edilmesi gereken yöntemdir.

# Birden fazla kayıt tek seferde oluşturma
cat > /tmp/multi-record-batch.json << 'EOF'
{
  "Changes": [
    {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "api.example.com",
        "Type": "A",
        "TTL": 60,
        "ResourceRecords": [{"Value": "203.0.113.20"}]
      }
    },
    {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "mail.example.com",
        "Type": "MX",
        "TTL": 3600,
        "ResourceRecords": [
          {"Value": "10 mail1.example.com"},
          {"Value": "20 mail2.example.com"}
        ]
      }
    },
    {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "example.com",
        "Type": "TXT",
        "TTL": 300,
        "ResourceRecords": [
          {"Value": ""v=spf1 include:_spf.google.com ~all""}
        ]
      }
    }
  ]
}
EOF

aws route53 change-resource-record-sets 
  --hosted-zone-id $ZONE_ID 
  --change-batch file:///tmp/multi-record-batch.json

UPSERT action’ını özellikle seviyorum çünkü kayıt varsa günceller, yoksa oluşturur. Scripte “bu kayıt var mı?” diye kontrol eklemenize gerek kalmaz.

Alias Kayıtları ile AWS Servis Entegrasyonu

Route 53’ün en güçlü özelliklerinden biri alias record desteği. Özellikle ELB ile entegrasyonda bu kritik.

# ELB için alias A kaydı oluşturma
cat > /tmp/elb-alias.json << 'EOF'
{
  "Changes": [
    {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "example.com",
        "Type": "A",
        "AliasTarget": {
          "HostedZoneId": "Z35SXDOTRQ7X7K",
          "DNSName": "my-loadbalancer-1234567890.eu-west-1.elb.amazonaws.com",
          "EvaluateTargetHealth": true
        }
      }
    }
  ]
}
EOF

aws route53 change-resource-record-sets 
  --hosted-zone-id $ZONE_ID 
  --change-batch file:///tmp/elb-alias.json

Buradaki HostedZoneId ELB’ye ait olan Zone ID’dir, kendi hosted zone ID’niz değil. Her AWS servisinin ve region’ın kendine ait bir hosted zone ID’si var, bunları AWS dokümantasyonundan bulabilirsiniz.

EvaluateTargetHealth: true ayarı, ELB’nin sağlık durumunu DNS yanıtlarında dikkate almasını sağlar. Eğer ELB’niz down ise Route 53 o kaydı döndürmez.

Traffic Routing Politikaları

Route 53’ün gerçek gücü routing politikalarında ortaya çıkıyor. Farklı senaryolar için farklı politikalar kullanırsınız.

Weighted Routing (Ağırlıklı Yönlendirme)

Blue-green deployment veya A/B testing için mükemmel. Trafiği yüzdelik dilimlerle bölebilirsiniz.

# %90 production, %10 canary deployment
cat > /tmp/weighted-routing.json << 'EOF'
{
  "Changes": [
    {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "app.example.com",
        "Type": "A",
        "SetIdentifier": "production",
        "Weight": 90,
        "TTL": 60,
        "ResourceRecords": [{"Value": "203.0.113.10"}]
      }
    },
    {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "app.example.com",
        "Type": "A",
        "SetIdentifier": "canary",
        "Weight": 10,
        "TTL": 60,
        "ResourceRecords": [{"Value": "203.0.113.11"}]
      }
    }
  ]
}
EOF

aws route53 change-resource-record-sets 
  --hosted-zone-id $ZONE_ID 
  --change-batch file:///tmp/weighted-routing.json

Canary deployment sırasında sorun çıkarsa weight’i 0 yaparak trafiği anında çekebilirsiniz. Weight 0 olan kayıtlar hiç trafik almaz ama zone’dan silinmez, yeniden aktif etmek için weight değerini güncellemeniz yeterli.

Latency-Based Routing (Gecikme Bazlı)

Multi-region uygulamalarında kullanıcıları en yakın region’a yönlendirmek için kullanılır.

cat > /tmp/latency-routing.json << 'EOF'
{
  "Changes": [
    {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "api.example.com",
        "Type": "A",
        "SetIdentifier": "eu-west-1",
        "Region": "eu-west-1",
        "TTL": 60,
        "ResourceRecords": [{"Value": "203.0.113.10"}]
      }
    },
    {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "api.example.com",
        "Type": "A",
        "SetIdentifier": "us-east-1",
        "Region": "us-east-1",
        "TTL": 60,
        "ResourceRecords": [{"Value": "203.0.113.20"}]
      }
    },
    {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "api.example.com",
        "Type": "A",
        "SetIdentifier": "ap-southeast-1",
        "Region": "ap-southeast-1",
        "TTL": 60,
        "ResourceRecords": [{"Value": "203.0.113.30"}]
      }
    }
  ]
}
EOF

aws route53 change-resource-record-sets 
  --hosted-zone-id $ZONE_ID 
  --change-batch file:///tmp/latency-routing.json

Failover Routing

Active-passive HA senaryoları için. Primary down olursa secondary devreye girer.

cat > /tmp/failover-routing.json << 'EOF'
{
  "Changes": [
    {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "service.example.com",
        "Type": "A",
        "SetIdentifier": "primary",
        "Failover": "PRIMARY",
        "HealthCheckId": "abc12345-1234-1234-1234-abc123456789",
        "AliasTarget": {
          "HostedZoneId": "Z35SXDOTRQ7X7K",
          "DNSName": "primary-lb.eu-west-1.elb.amazonaws.com",
          "EvaluateTargetHealth": true
        }
      }
    },
    {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "service.example.com",
        "Type": "A",
        "SetIdentifier": "secondary",
        "Failover": "SECONDARY",
        "AliasTarget": {
          "HostedZoneId": "Z35SXDOTRQ7X7K",
          "DNSName": "secondary-lb.eu-west-1.elb.amazonaws.com",
          "EvaluateTargetHealth": true
        }
      }
    }
  ]
}
EOF

Health Check Yapılandırması

Failover ve traffic routing politikalarının düzgün çalışması için health check’lerin doğru yapılandırılması kritik.

# HTTP health check oluşturma
aws route53 create-health-check 
  --caller-reference $(date +%s) 
  --health-check-config '{
    "IPAddress": "203.0.113.10",
    "Port": 443,
    "Type": "HTTPS",
    "ResourcePath": "/health",
    "FullyQualifiedDomainName": "web.example.com",
    "RequestInterval": 30,
    "FailureThreshold": 3,
    "MeasureLatency": true,
    "EnableSNI": true
  }'

# Health check durumunu sorgula
HEALTH_CHECK_ID="abc12345-1234-1234-1234-abc123456789"
aws route53 get-health-check-status 
  --health-check-id $HEALTH_CHECK_ID 
  --query 'HealthCheckObservations[*].{Region:Region,Status:StatusReport.Status}' 
  --output table

Health check parametrelerini iyi anlamak önemli:

  • RequestInterval: 10 veya 30 saniye seçenekleri mevcut. 10 saniye daha hızlı failover sağlar ama 3 kat daha pahalıdır
  • FailureThreshold: Kaç ardışık başarısızlıktan sonra unhealthy sayılacağı. Default 3, yani 30 saniyelik interval ile 90 saniye sonra failover başlar
  • EnableSNI: HTTPS health check’lerde SNI desteği, modern setup’larda açık olmalı

Terraform ile Route 53 Yönetimi

Gerçek dünyada DNS kayıtlarını elle yönetmek yerine Infrastructure as Code kullanmak çok daha sağlıklı. İşte temel bir Terraform konfigürasyonu:

# Hosted zone oluşturma
resource "aws_route53_zone" "main" {
  name    = "example.com"
  comment = "Production DNS zone"

  tags = {
    Environment = "production"
    ManagedBy   = "terraform"
  }
}

# A kaydı
resource "aws_route53_record" "web" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "web.example.com"
  type    = "A"
  ttl     = 300
  records = ["203.0.113.10"]
}

# ELB alias kaydı
resource "aws_route53_record" "apex" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "example.com"
  type    = "A"

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

# Health check ile weighted routing
resource "aws_route53_health_check" "api_primary" {
  fqdn              = "api-primary.example.com"
  port              = 443
  type              = "HTTPS"
  resource_path     = "/health"
  failure_threshold = 3
  request_interval  = 30

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

resource "aws_route53_record" "api_weighted_primary" {
  zone_id        = aws_route53_zone.main.zone_id
  name           = "api.example.com"
  type           = "A"
  set_identifier = "primary"
  ttl            = 60
  records        = ["203.0.113.10"]

  weighted_routing_policy {
    weight = 90
  }

  health_check_id = aws_route53_health_check.api_primary.id
}

Gerçek Dünya Senaryosu: Migration Sırasında Zero-Downtime DNS Geçişi

Bir müşterinin hosting’ini değiştirirken yaşanan senaryoyu ele alalım. Eski IP’den yeni IP’ye geçiş yapacaksınız ve kesinti istemiyorsunuz.

İlk adım TTL düşürme. Değişiklikten en az 24-48 saat önce TTL’i düşürün:

# Önce mevcut TTL'i kontrol et
aws route53 list-resource-record-sets 
  --hosted-zone-id $ZONE_ID 
  --query 'ResourceRecordSets[?Name==`example.com.` && Type==`A`]'

# TTL'i 60 saniyeye düşür
cat > /tmp/lower-ttl.json << 'EOF'
{
  "Changes": [
    {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "example.com",
        "Type": "A",
        "TTL": 60,
        "ResourceRecords": [{"Value": "203.0.113.10"}]
      }
    }
  ]
}
EOF

aws route53 change-resource-record-sets 
  --hosted-zone-id $ZONE_ID 
  --change-batch file:///tmp/lower-ttl.json

24 saat sonra (eski TTL süresi dolduğunda) yeni IP’ye geçin. Geçiş sonrası birkaç saat izledikten sonra TTL’i tekrar yükseltin.

Change Propagation’ı İzleme

# Change ID'yi yakala
CHANGE_ID=$(aws route53 change-resource-record-sets 
  --hosted-zone-id $ZONE_ID 
  --change-batch file:///tmp/lower-ttl.json 
  --query 'ChangeInfo.Id' 
  --output text)

# Değişiklik yayılana kadar bekle
aws route53 wait resource-record-sets-changed 
  --id $CHANGE_ID

echo "DNS değişikliği Route 53 nameserver'larına yayıldı"

wait resource-record-sets-changed komutu değişiklik INSYNC durumuna gelene kadar bekler. Bu genellikle 1-2 dakika alır. Ama unutmayın, bu Route 53’ün kendi nameserver’larına yayılma süresidir. DNS resolver cache’lerinde eski TTL süresi kadar eski kayıt kalabilir.

Route 53 Resolver ve DNS Firewall

VPC içindeki EC2 instance’larınızın hem AWS kaynaklarını hem de on-premises sistemleri çözümleyebilmesi için Route 53 Resolver endpoint’leri kullanılır.

Inbound Endpoint: On-premises’ten VPC içindeki DNS isimlerini çözmek için Outbound Endpoint: VPC’den on-premises DNS sunucularına sorgu yönlendirmek için

DNS Firewall özelliği ile zararlı domain’lere erişimi engelleyebilirsiniz. AWS’in yönetilen threat intelligence listelerini kullanabilir veya kendi block list’lerinizi tanımlayabilirsiniz. Özellikle compliance gereksinimleri olan ortamlarda bu özellik ciddi bir güvenlik katmanı ekliyor.

Maliyet Optimizasyonu

Route 53 faturalandırması birkaç bileşenden oluşur:

  • Hosted zone başına: Ayda 0.50 USD (ilk 25 zone için)
  • DNS sorguları: 1 milyon sorgu başına 0.40-0.60 USD (sorgu tipine göre değişir)
  • Health check: Aylık 0.50 USD’den başlıyor, hızlı interval ve ek özelliklerle artıyor

Maliyet optimizasyonu için birkaç pratik öneri:

  • Kullanılmayan hosted zone’ları temizleyin. Her biri ayda 0.50 USD ediyor
  • Aynı domain’in test ortamını ayrı bir hosted zone yerine alt alan adıyla yönetebilirsiniz
  • Alias record’lar CNAME’den daha ucuzdur, AWS kaynakları için alias kullanın
  • Health check interval’lerini dikkatli seçin, 10 saniyelik interval 30 saniyeliğin 3 katı maliyetlidir

Monitoring ve Alerting

Route 53 CloudWatch metrikleri, özellikle health check’ler için çok değerli:

# Health check alarm oluşturma
aws cloudwatch put-metric-alarm 
  --alarm-name "Route53-HealthCheck-Failed" 
  --alarm-description "Route53 health check basarisiz" 
  --metric-name HealthCheckStatus 
  --namespace AWS/Route53 
  --statistic Minimum 
  --period 60 
  --evaluation-periods 1 
  --threshold 1 
  --comparison-operator LessThanThreshold 
  --dimensions Name=HealthCheckId,Value=$HEALTH_CHECK_ID 
  --alarm-actions arn:aws:sns:eu-west-1:123456789:ops-alerts 
  --treat-missing-data breaching

HealthCheckStatus metriği 1 ise healthy, 0 ise unhealthy. treat-missing-data breaching ayarı, metrik verisi gelmediğinde de alarmın tetiklenmesini sağlar ki bu production’da olmazsa olmaz.

Sonuç

Route 53, doğru kullanıldığında DNS yönetimini ciddi ölçüde kolaylaştıran ve güvenilirliği artıran bir servis. Temel A/AAAA/CNAME kayıtlarından karmaşık multi-region failover senaryolarına kadar her ihtiyacı karşılayabiliyor.

Burada ele aldığımız konuları özetlemek gerekirse: hosted zone yönetimi, CLI ile kayıt oluşturma ve güncelleme, alias record’larla AWS servis entegrasyonu, traffic routing politikaları ve health check yapılandırması. Bunları kavradıktan sonra Terraform veya AWS CDK ile Infrastructure as Code’a geçmek sonraki mantıklı adım.

DNS değişikliklerinde sabırlı olmak gerekiyor. TTL’leri önceden düşürmek, change propagation’ı izlemek ve geçiş sırasında her iki IP’nin de çalışır durumda olduğundan emin olmak zero-downtime migration’ın temel kuralları. Bu kurallara uymadığınızda gece yarısı yaşanan “site açılmıyor” krizleriyle karşılaşmak maalesef kaçınılmaz oluyor.

Son bir not: Route 53 değişikliklerini mutlaka bir change management süreciyle takip edin. DNS’te yapılan yanlış bir değişikliğin etkisi anında hissedilir ve geri almak bazen TTL süresi kadar zaman alabilir.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir