Simple EC2 Instance + Route53 DNS

If you have a multi-environment AWS setup, and want a easy way to resolve all EC2 instance using Route53 DNS, look no further!

Currently I’m maintaining a production and staging environment on Amazon Web Services across multiple regions. We tend to not use ElasticIPs as that just increases cost, plus internally we resolve using Consul . There is one drawback with not using ElasticIPs, when ever the instance restarts they will be offered a new dynamic IP (we will solve this with automation).

Our EC2 instances are deployed using Saltstack and salt-cloud , so adding to our base SLS made sense, below is a snippet of the states salt/base.sls

include:
 - cli53

#
# Update AWS Route53 with our hostname
#

/opt/update\_route53.sh:
 file.managed:
 - source: salt://base/templates/update\_route53.sh
 - mode: 775

update\_route53:
 cmd.run:
 - name: /opt/update\_route53.sh update {{ pillar['environment'] }}
 - unless: /opt/update\_route53.sh check {{ pillar['environment'] }}
 - require:
 - pip: cli53
 - file: /opt/update\_route53.sh

This state places a new script at /opt/update_route53.sh, then below it runs the update

unless

the check shows no change. This script requires cli53 so we have another SLS that handles that install.

The script is merely a bash shell script with a case statement:

/opt/update_route53.sh

#!/bin/bash

#
# Simple script for updating Route53 with instance IPs
#
# How to get public ip for EC2 instance
# http://stackoverflow.com/a/7536318/4635050
#

ENVIORNMENT=$2 # either prod or dev
HOSTNAME=$(hostname)
PUBLIC\_IP=$(curl -s http://instance-data/latest/meta-data/public-ipv4)
DNS\_IP=$(dig $HOSTNAME.$ENVIORNMENT.youdomain.com +short)

case "$1" in

 check)
 if [[ "$DNS\_IP" == "" ]] ; then
 exit 1
 elif [[ "$PUBLIC\_IP" != "$DNS\_IP" ]] ; then
 exit 1
 fi
 exit 0
 ;;

 update)
 if [[ "$DNS\_IP" == "" ]] ; then
 echo "Did not find record for $HOSTNAME.$ENVIORNMENT, Creating.."
 cli53 rrcreate yourdomain.com $HOSTNAME.$ENVIORNMENT A $PUBLIC\_IP
 elif [[ "$PUBLIC\_IP" != "$DNS\_IP" ]] ; then
 echo "Found IP $DNS\_IP for $HOSTNAME.$ENVIORNMENT, Updating to $PUBLIC\_IP"
 cli53 rrdelete yourdomain.com $HOSTNAME.$ENVIORNMENT
 sleep 30 # give AWS some time to delete
 cli53 rrcreate yourdomain.com $HOSTNAME.$ENVIORNMENT A $PUBLIC\_IP
 else
 echo "No need to update. passing.."
 fi
 ;;
esac

Assuming you have set your NS records to Route53 for your domain, and the salt state or script has been ran, you should be able to resolve your instances like below:

$ dig salt-master.prod.yourdomain.com +short
1.2.3.4
$ dig webapp.dev.yourdomain.com +short
4.3.2.1

Happy hacking!