How To Migrate Route 53 to another AWS Account

Migrating a Route 53 Hosted Zone from one AWS account to another involves a few key steps. The process requires careful planning to ensure that the DNS service remains uninterrupted during the transition. Here’s a step-by-step guide to help you through the migration:

Note: any of the code provided on this blog post is for learning purposes only and not recommended to use in a production environment.

  1. Prepare for Migration

    Review DNS Records: Before starting, review the DNS records in the hosted zone to ensure that you are aware of all the configurations that will need to be recreated in the new account. You can export this locally with:

    aws route53 list-resource-record-sets --hosted-zone-id ABCDEFGH12345678 > route53.json
    

    Lower TTL Values: Lower the Time to Live (TTL) values for the DNS records in the current hosted zone. This step ensures that changes propagate quickly during the migration process, minimising potential downtime.

    import boto3
    client = boto3.client('route53')
    
    hosted_zone = input("Enter the hosted zone: ")# Ask user for hosted zone
    
    response = client.list_resource_record_sets(
        HostedZoneId=hosted_zone
    )
    
    # Print all the hosted zones with a TTL value greater than 60
    records_to_change = []
    for record in response['ResourceRecordSets']:
        # If Record TTL not NULL
        if 'TTL' in record:
            if record['TTL'] > 60:
                print(record['Name'], record['TTL'])
                records_to_change.append(record)
    
    print("Changing the TTL of these records to 1 minute...")
    
    # Adjust the TTL of the records to change to 1 minute
    for record in records_to_change:
        print(" Changing record: " + record['Name'] + " to 1 minute")
        response = client.change_resource_record_sets(
            HostedZoneId=hosted_zone,
            ChangeBatch={
                'Comment': 'Changing TTL to 1 minute',
                'Changes': [
                    {
                        'Action': 'UPSERT',
                        'ResourceRecordSet': {
                            'Name': record['Name'],
                            'Type': record['Type'],
                            'TTL': 60,
                            'ResourceRecords': record['ResourceRecords']
                        }
                    }
                ]
            }
        )
    print(response)
    
  2. Create a New Hosted Zone in the Target Account

    Create Hosted Zone: In the target AWS account, create a new hosted zone with the same domain name as the one in the source account. This action will generate a new set of name servers.

    aws route53 create-hosted-zone --name test.com.au --caller-reference NewZonePlz > newzone.json
    

    Record Name Servers: Note down the name servers for the new hosted zone created in the target account. You will need these for delegation purposes later. The command above will output them to newzone.json.

  3. Recreate DNS Records in the New Hosted Zone

    Manually Recreate Records: Manually recreate all the DNS records from the old hosted zone in the new hosted zone in the target AWS account. Ensure that all record sets are an exact match to avoid service disruptions.

    import boto3
    client = boto3.client('route53')
    
    # Recreate DNS Records from old account in new account hosted zone
    
    original_hosted_zone = input("Enter the original hosted zone: ")# Ask user for the original hosted zone
    new_hosted_zone = input("Enter the new hosted zone: ")# Ask user for the new hosted zone
    
    # Get profile for original account
    original_profile = input("Enter the original account profile name: ")
    session = boto3.Session(profile_name=original_profile)
    client = session.client('route53')
    
    # Get the records from the original hosted zone
    response = client.list_resource_record_sets(
        HostedZoneId=original_hosted_zone
    )
    
    # Get profile for new account
    new_profile = input("Enter the new account profile name: ")
    session = boto3.Session(profile_name=new_profile)
    client = session.client('route53')
    
    # Create the records in the new hosted zone
    for record in response['ResourceRecordSets']:
        # If record is not a NS or SOA record
        if record['Type'] != 'NS' and record['Type'] != 'SOA':
            client.change_resource_record_sets(
                HostedZoneId=new_hosted_zone,
                ChangeBatch={
                    'Comment': 'Creating new records',
                    'Changes': [
                        {
                            'Action': 'UPSERT',
                            'ResourceRecordSet': record
                        }
                    ]
                }
            )
    
    print("Records created successfully!")
    
  4. Update Registrar’s Name Server Records

    Update Name Servers: Once all DNS records are recreated in the new hosted zone, update the domain’s name server records at your domain registrar to point to the new name servers provided by the Route 53 hosted zone in the target account. I’m using NameCheap not Route 53 as my registrar so will manually do this.

    Verify Propagation: It may take some time for the changes to propagate across the internet. You can use tools like nslookup or dig to verify that your domain’s DNS queries are being correctly resolved to the new name servers.

    dig @8.8.8.8 +short NS test.com.au
    
  5. Monitor and Validate

    Monitor Traffic: Monitor the DNS traffic to ensure that it is being routed correctly to the services hosted under the domain.

    Validate Configuration: Double-check all DNS configurations in the new hosted zone to ensure they match the original settings. You may wish to update the records TTL to their old TTL you exported at the start of this process.

  6. Decommission the Old Hosted Zone

    Confirm No Traffic: Ensure that there is no traffic being routed through the old hosted zone. This can be verified by monitoring DNS query logs or traffic to the resources still pointing to the old DNS settings.

    NOTE: The Public DNS query logging will need to use a CloudWatch Logs log group in us-east-1.

    Delete Old Hosted Zone: Once you are sure that all traffic is successfully routed through the new hosted zone, and the domain’s name servers have been updated everywhere, you can safely delete the hosted zone in the source account.

This process requires careful attention to detail to avoid service disruption. Always plan and execute the migration during a maintenance window or off-peak hours to minimise impact on end-users.

Blog Post Image by ChatGPT 4