We have a situation where we use a lot of transient EC2 instances that are part of an integrated set of demonstration machines. They all refer to each other by DNS name that we have set up in a Route53 domain within AWS. For cost reasons, we shut these machines down any time we are not using them. The problem is, every time we boot the machines, we have to go through the grief of re-associating the Route53 CNAMES with the newly-reacquired public DNS and IP entries. Doing this manually is kind of a pain and my nature is always to automated this with command line scripts. Amazon provides an awkward JSON-based set of command line utilities you can use to automated the process, but it’s painful (at best). So, I fumbled around the interwebs and found a nice post by David Fox about Automated DNS in R53. It refers to a command line utility cli53 that allows you to execute simple commands to updates Route53. Much better.
I made a few modifications to David’s original scripts to streamline it for our environment and shortened some things to act as a good reference for myself in the future.
Some basic assumptions before I get started. I’ll leave it as an exercise to the reader to get this stuff set up. David’s original post has more details if you’re interested.
- IAM user (e.g., svc.r53.updater) created with access keys and policy that allows modifying Route53 records
- Route53 hosted zone is set up for the domain you are using (e.g., dev.secureci.com in our case)
- ‘ec2-metadata’ command line utility is installed on your host.
- Ubuntu: sudo apt-get install cloud-utils
- Amazon linux: pre-installed
- CentOS: sudo yum install ec2-utils
Given all that, you should already be able to manually associate DNS entries with your Route53 domain using the AWS console.
To make this work, do the following (on a CentOS, RHEL, or Amazon Linux box):
1. Install software
sudo yum install python-pip
sudo pip install cli53
Alternate: download the cli53 package from https://github.com/barnybug/cli53 and install it using Python.
2. Create file /etc/route53/config with proper AWS settings. Adjust ZONE and DEFAULT_NAME appropriately. Plug in your ACCESS and SECRET keys from your svc.r53.updater IAM user.
# Shell variables for register-route53.sh
AWS_ACCESS_KEY_ID="AKIA..."
AWS_SECRET_ACCESS_KEY="Mp3KpBCmT..."
ZONE="dev.secureci.com"
HOST_NAME="demo1"
TTL="300"
Make sure you lockdown the config file: "chmod 600 /etc/route53/config"
to make sure people cannot read your keys while on the machine.
Assuming everything is set correctly, You should be able to run the command cli53 rrlist dev.secureci.com
(using your domain name) and get a list of current records. You might need to “. /etc/route53/config” first to get your AWS keys loaded into your environment for the cli53 utility.
3. Create script /etc/route53/register-route53.sh. Note that the paths for the cli53 and ec2-metadata must be specified explicitly because we will run this script during boot in a very stripped environment that does not have much in its path.
#!/bin/sh # Original from David Fox: # https://gist.github.com/dfox/1677405 # # Script to bind a CNAME to our HOST_NAME in ZONE # Make sure only root can run our script if [ "$(id -u)" != "0" ]; then echo "This script must be run as root" 1>&2 exit 1 fi # Defaults TTL=60 HOST_NAME=`hostname` ZONE=NoZoneDefined # Load configuration . /etc/route53/config # Export access key ID and secret for cli53 export AWS_ACCESS_KEY_ID export AWS_SECRET_ACCESS_KEY # Use command line scripts to get instance ID and public hostname #INSTANCE_ID=$(ec2metadata | grep 'instance-id:' | cut -d ' ' -f 2) MY_NAME=$HOST_NAME PUBLIC_HOSTNAME=$(/opt/aws/bin/ec2-metadata | grep 'public-hostname:' | cut -d ' ' -f 2) logger "ROUTE53: Setting DNS CNAME $MY_NAME.$ZONE to $PUBLIC_HOSTNAME" # Create a new CNAME record on Route 53, replacing the old entry if nessesary /usr/bin/cli53 rrcreate "$ZONE" "$MY_NAME" CNAME "$PUBLIC_HOSTNAME" --replace --ttl "$TTL"
You can test this by running it as root on your machine. It should register properly.
4. Link the script so it runs on startup
ln -s /etc/route53/register-route53.sh /etc/rc3.d/S23register-route53
That’s it. Next time the machine boots, it will automatically register itself with our Route53 setup. All of these commands can be adjusted slightly for Ubuntu or other flavors of Linux.
3 thoughts to “Auto-register an EC2 host with Route53 DNS”
Some Notes on getting this running on AWS 14.04 Ubuntu Server
For step two, in addition to creating that config file, a .boto file should be created in the home directory – this will be needed if you ever want to run the cli53 command without this script
[Credentials]
aws_access_key_id = AKI…..
aws_secret_access_key = 9SB0Ki…..
Additionally, I needed to change the aws variable names to lower case to get them recognized
For the register-route53 script, the sources need to be changed for running the two commands
PUBLIC_HOSTNAME=$(/usr/bin/ec2metadata | grep ‘public-ipv4:’ | cut -d ‘ ‘ -f 2)
/usr/local/bin/cli53 rrcreate “$ZONE” “$MY_NAME” CNAME “$PUBLIC_HOSTNAME” –replace –ttl “$TTL”
I also added in a line to remove the old entry before creating a new one
/usr/local/bin/cli53 rrdelete “$ZONE” “$MY_NAME”
Finally, instead of linking to rc3.d, I linked the file into rc0.d and marked the execution in /etc/rc.local
Additionally, because we are adding an IP address, I chanced all of the CNAME references to A.
This might be something that we could throw into some configuration settings
You can also get this script to run on start up by adding an /etc/init.d script for it.
As a simple hack, just add a file called route53 to /etc/init.d with the following contents:
/etc/route53/register-route53.sh
and change its permissions to allow execution:
chmod +x /etc/init.d/route53
Then add the script to the default runlevels:
update-rc.d route53 defaults
You can test to see that it’s working with:
service route53 start
The matching stop command will also just start the script since we didn’t add any logic to /etc/init.d/route53 that handles startup versus stopping.