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.

  1. IAM user (e.g., svc.r53.updater) created with access keys and policy that allows modifying Route53 records
  2. Route53 hosted zone is set up for the domain you are using (e.g., dev.secureci.com in our case)
  3. ‘ec2-metadata’ command line utility is installed on your host.
    1. Ubuntu: sudo apt-get install cloud-utils
    2. Amazon linux: pre-installed
    3. 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

  • Max Saperstone
    Max Saperstone

    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

    Reply
  • Max Saperstone
    Max Saperstone

    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

    Reply
  • Avatar
    Arjun Comar

    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.

    Reply

Leave a comment

Your email address will not be published. Required fields are marked *

X