Amazon AWS and making use of dynamic IP addresses

If you ask AWS to give your instance a public address but don’t allocate an “Elastic IP address” then you get a dynamic address from a pool.
That causes problems only when you stop/start (eg NOT when you reboot). So it will only bite you much, much, later.

EIPs are in slightly short supply and if your instance is switched off, you get charged for the time that you aren’t using it.
To avoid using up too many EIPs, we can easily use a dynamic address with a little bit of work.

Set your hostname

This varies a little bit by OS. I recommend either a

supersede host-name "host.domain";

in /etc/dhcp/dhcp.conf or add “fqdn host.domain” to /etc/cloud/cloud.cfg somewhere near the top. That should override the hostname set by AWS metadata.

Give your instance permissions to change DNS

Create a new IAM role that allows your instance to change DNS records.

{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Sid": "Stmt1503315936000",
 "Effect": "Allow",
 "Action": [
 "route53:ChangeResourceRecordSets"
 ],
 "Resource": [
 "arn:aws:route53:::hostedzone/ZJSJ666666666"
 ]
 }
 ]
}

Figure out your Zone ID and replace the one above with your zone in a new role. Name the role appropriately and assign to your instance.

This gives anyone running the aws command line on your instance permission to alter the DNS in the specified zone.

Install the AWS CLI

If it isn’t already installed follow instructions from Amazon: Installing the AWS command line

Add the magic

Put the following into /etc/init.d/update_dns

#!/bin/sh
### BEGIN INIT INFO
# Provides: DNS stuff
# Required-Start: $local_fs $network $remote_fs
# Required-Stop: $local_fs $network $remote_fs
# Default-Start: 2 3 4 5
### END INIT INFO
if [ ${1}a = "starta" ]
then
IP=`curl -s http://169.254.169.254/latest/meta-data/public-ipv4`
HOST=`hostname`
echo "Adding DNS for $HOST at $IP"
cat > $$.json << EOF
{
  "Changes": [{
    "Action": "UPSERT",
    "ResourceRecordSet": {
      "Name": "${HOST}",
      "Type": "A",
      "TTL": 60,
      "ResourceRecords": [ {"Value": "${IP}"} ]
    }
  }]
}
EOF
#more $$.json
aws route53 change-resource-record-sets --hosted-zone-id ZJSJ666666666 --change-batch file://$$.json
rm $$.json
fi

Yes, that really does say “UPSERT”!
Then,

 chmod a+x /etc/init.d/update_dns
 chkconfig update_dns on
 service update_dns start

It should at this point tell you which hostname is having which DNS added to it. If you’ve never used this before, you might want to comment out the aws command and uncomment the more command, to see what it intends to do before it happens. You may be able to badly destroy IP addresses for critical services if you get this wrong!