Zero-Downtime DNS Migration: Switching from A Record to CNAME for AWS ELB


2 views

When migrating infrastructure to AWS EC2 with Elastic Load Balancing (ELB), you'll encounter an important DNS configuration requirement: ELBs require CNAME records rather than A records because their IP addresses can change dynamically. The standard approach of deleting the A record before creating the CNAME introduces potential downtime during DNS propagation.

The most reliable zero-downtime approach involves temporarily maintaining both records during the transition:

example.com.   300   IN   A       192.0.2.1
www.example.com. 300 IN   CNAME   example-elb-1234567890.us-west-2.elb.amazonaws.com.

Here's why this works:

  • The A record continues serving production traffic
  • The CNAME record propagates gradually
  • Clients will use whichever record they receive first
  • After TTL expiration (300 seconds in this case), all clients should be using the CNAME

1. Prepare your DNS zone file:

; Before change
@       3600    IN    A    192.0.2.1

; Transition phase
@       300     IN    A    192.0.2.1
@       300     IN    CNAME   example-elb-1234567890.us-west-2.elb.amazonaws.com.

2. AWS ELB configuration example:

aws elb create-load-balancer \
    --load-balancer-name example-elb \
    --listeners "Protocol=HTTP,LoadBalancerPort=80,InstanceProtocol=HTTP,InstancePort=80" \
    --availability-zones us-west-2a us-west-2b

Use these commands to verify the transition:

dig example.com +short
# Should show both records during transition

aws elb describe-load-balancers --load-balancer-names example-elb
# Verify ELB health

If using AWS Route 53, Alias records provide a better alternative:

aws route53 change-resource-record-sets --hosted-zone-id ZXYZ12345678 \
--change-batch '{
  "Changes": [{
    "Action": "UPSERT",
    "ResourceRecordSet": {
      "Name": "example.com",
      "Type": "A",
      "AliasTarget": {
        "HostedZoneId": "ZABC12345678",
        "DNSName": "dualstack.example-elb-1234567890.us-west-2.elb.amazonaws.com",
        "EvaluateTargetHealth": false
      }
    }
  }]
}'

Key benefits of Alias records:

  • Function like A records at the zone apex
  • Automatically resolve to current ELB IPs
  • No propagation delay

1. TTL too high: Keep TTL low (300 seconds) during transition
2. Mixed record types: Some DNS providers don't allow A and CNAME for same name
3. ELB health checks: Ensure your instances pass ELB health checks before cutover

For Dyn DNS specifically, use their API for atomic changes:

curl -X PUT "https://api.dynect.net/REST/Zone/example.com/" \
     -H "Content-Type: application/json" \
     -d '{
           "rdata": {
             "cname": "example-elb-1234567890.us-west-2.elb.amazonaws.com"
           },
           "ttl": 300,
           "fqdn": "www.example.com",
           "record_type": "CNAME"
         }'

When migrating infrastructure to AWS EC2 with Elastic Load Balancers (ELB), administrators often face the classic DNS dilemma. The ELB's dynamic IP addresses make A records problematic, while traditional DNS management interfaces enforce sequential operations that can cause service interruption.

Most DNS providers implement validation rules preventing simultaneous A and CNAME records for the same hostname. This stems from RFC compliance, not technical limitations. Dyn.com's interface follows this pattern:

# Current DNS configuration example
example.com.   300   IN   A      192.0.2.45

Before any migration attempt, verify your current A record's TTL value. For production systems, a TTL of 300 seconds (5 minutes) or lower is recommended for rapid propagation.

dig +noall +answer example.com
;; example.com.    300    IN    A    192.0.2.45

We'll implement a phased approach using DNS responses' hierarchical nature:

  1. Create the CNAME record pointing to your ELB endpoint (e.g., my-elb-1234567890.us-west-2.elb.amazonaws.com)
  2. Immediately reduce the A record's TTL to 60 seconds
  3. Wait 2x the original TTL period (e.g., 10 minutes for a 300-second TTL)
  4. Remove the A record

For critical systems, implement traffic weighting using Route 53 or advanced DNS providers:

# AWS CLI example for Route 53 weighted records
aws route53 change-resource-record-sets --hosted-zone-id Z1PA6795UKMFR9 \
--change-batch '{
  "Changes": [{
    "Action": "CREATE",
    "ResourceRecordSet": {
      "Name": "example.com",
      "Type": "CNAME",
      "SetIdentifier": "NewELB",
      "Weight": 1,
      "TTL": 60,
      "ResourceRecords": [{"Value": "my-elb-1234567890.us-west-2.elb.amazonaws.com"}]
    }
  }]
}'

Use parallel DNS lookups to monitor propagation:

for i in {1..10}; do 
  dig @8.8.8.8 example.com +short &
  dig @1.1.1.1 example.com +short &
  sleep 60
done
  • CloudFront distributions require A record aliases (special CNAMEs)
  • Some SMTP servers reject mail from CNAME domains
  • DNSSEC-signed zones require additional steps