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

[code]
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
[/code]

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

[bash]
#!/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
[/bash]

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:

[code]
$ dig salt-master.prod.yourdomain.com +short
1.2.3.4
[/code]

[code]
$ dig webapp.dev.yourdomain.com +short
4.3.2.1
[/code]

Happy hacking!