2

I have two AWS accounts old and new.

I have a hosted ZONE on old account under Route 53 service.

I want to migrate it completely from old to new.

How can I do it ? Are there any predefined steps for such case ?

Please note that the hosted zone is being used in a live environment. I can not risk too much trial and error.

2
  • Why not manually create the records, else use the CLI? Aug 4, 2014 at 12:18
  • Duplicate all the records (if you have a lot, use the API) then cut over to the new set of nameservers.
    – ceejayoz
    Aug 4, 2014 at 14:10

4 Answers 4

10

You can also use jq ("sed for JSON") to convert the JSON output of list-resource-record-sets to the JSON input to change-resource-record-sets:

jq '.ResourceRecordSets 
  |{"Changes":[.[] 
  |select(.Type!="SOA") 
  |select(.Type!="NS") 
  |{"Action":"CREATE","ResourceRecordSet":.}]}' 

This assumes you have already created the new hosted zone and that it is empty except for the SOA and NS records, which are therefore removed from the JSON file. (The line breaks are for readability; remove them to use the command.)

3

This is trivial using the AWS CLI. First, get your hosted zone id:

$ aws route53 list-hosted-zones
{
    "HostedZones": [
         {
            "ResourceRecordSetCount": 15,
            "CallerReference": "A5A5A3AF-C239-39FB-DA4C-556BA9FD1767",
            "Config": {},
            "Id": "/hostedzone/Z1LVCQHJBJUCM5",
            "Name": "example.com."
        }
    ]
}

Then export the list of resources for that hosted zone:

$ aws route53 list-resource-record-sets --hosted-zone Z1LVCQHJBJUCM5

This will output a json blob of your records, which is very close to the format you'll need to re-import into the new zone, using the change-resource-record-sets command. Look through the documentation, examining the output format of list-resource-record-sets and the input format of change-resource-record-sets and it'll be clear what you need to do to import the records.

Once you have the records in place in the new zone, update your domain registrar to point to the set of Route53 nameservers for this zone.

2
1

I just created a tool for this very problem.

https://github.com/andersjanmyr/route53copy

$ route53copy Usage: route53copy-linux <source_profile> <dest_profile> <domain>

1

A more updated answer. This is how I did it without external tools, just aws and a text editor.

First, according to the CLI docs: "You can't create a hosted zone for a top-level domain (TLD) such as .com" (or .org, .net etc.).

No biggie, go to the new account and create it manually, it's a concise thing:

enter image description here

Now that you have created a Hosted Zone, it's just a matter of fill it with records. So, get the records from the old account into a .json file for comfort:

$ aws route53 list-resource-record-sets --hosted-zone YOURHOSTZONEID --output json --profile account1 > records.json

You can get your YOURHOSTZONEID directly from the web console ("Hosted Zone ID" column in the previous image) or from your terminal: $ aws route53 list-hosted-zones --profile account1.

This --profile account1 option is a reference to the potentially multiple account configuration, originally stored in ~/.aws folder: files config and credentials. If you haven't configured them, you can edit the two files manually (adding all the accounts you want, including IAMs), but I recommend using $ aws configure explained here.

Now, when you use any aws command with a particular --profile, it will know what account you want to use.

The JSON we downloaded needs to be "adapted" to the actual JSON structure the change-resource-record-sets is expecting. For some reason, using the --generate-cli-skeleton should give you an exemplar to know what structure is expected. Still, in this case, it's different (and therefore wrong), don't know why, from what is expected (which you can find here, first JSON example). This is a reduced and a bit concealed version, but with the right structure:

{
  "Comment": "",
  "Changes": [
    {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "domain.org.",
        "Type": "A",
        "TTL": 300,
        "ResourceRecords": [
          {
            "Value": "11.111.111.111"
          }
        ]
      }
    },
    {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "domain.org.",
        "Type": "MX",
        "TTL": 300,
        "ResourceRecords": [
          {
            "Value": "20 mx1.domain.com"
          },
          {
            "Value": "10 mx2.domain.com"
          },
          {
            "Value": "50 mx3.domain.com"
          }
        ]
      }
    },
    {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "domain.org.",
        "Type": "NS",
        "TTL": 172800,
        "ResourceRecords": [
          {
            "Value": "number.awsdns-28.com."
          },
          {
            "Value": "number.awsdns-23.org."
          },
          {
            "Value": "number.awsdns-31.co.uk."
          },
          {
            "Value": "number.awsdns-49.net."
          }
        ]
      }
    }
  ]
}

As you can see, you have to insert each ResourceRecordSets' JSON from the account1 into each object, starting with "Action" in the JSON to send to the account2. Then we send it like so:

$ aws route53 change-resource-record-sets --hosted-zone-id Z3IVB20ZV4QU6O --change-batch file://adaptedfile.json --profile account2

Notice that files in aws CLI are referenced with the file:// schema.

Bonus tip: if you encounter errors, you can add a --debug option that may help you figure out what's wrong.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .