How to start and set DNS for an EC2 server using python

In this post, I will show how to start a stopped EC2 server and set a public DNS record for it.

Background:

AWS has a default limit of 5 Elastic IP per region VPC Limits.  This is a soft limit and it can be increased. However, if you are not running your EC2 instance there is a charge for keeping an EIP as described here. I have an EC2 server that does not run 24×7 which needs a public DNS record so I wrote some python code to start my server and set DNS for it.

Code:

Here is a sequence of steps:

  • Start the EC2 server using its id.
  • Wait for state transition of the EC2 instance.
  • Get public IP of the server.
  • Set the DNS record.
start_instance(ec2client, id) 
time.sleep(30)
pubip=get_public_ip(ec2client, id)
if pubip:
response=set_dns(route53, pubip, dns)

Start the EC2 server

def start_instance(ec2client, id):     
return ec2client.start_instances(InstanceIds=[id])

Get its public IP

def get_public_ip(ec2client, id):
iresponse = ec2client.describe_instances(InstanceIds=[id])
for ireservation in iresponse['Reservations']:
for i in ireservation['Instances']:
if 'PublicIpAddress' in i:
ip=i["PublicIpAddress"]
return ip

Pass DNS with the record you wish to set.

def set_dns(route53, ip, dns):
HOSTED_ZONE_ID = 'xxxxxxxxx'
dns_changes = {
'Changes': [
{
'Action': 'UPSERT',
'ResourceRecordSet': {
'Name': dns,
'Type': 'A',
'ResourceRecords': [
{
'Value': ip
}
],
'TTL': 300
}
}
]
}
response = route53.change_resource_record_sets(
HostedZoneId=HOSTED_ZONE_ID,
ChangeBatch=dns_changes
)
return {'status':response['ChangeInfo']['Status']}

This code should be run on a server which has IAM role set to give it access to start EC2 server and set DNS in your Hosted Zone on Route 53.
IAM access that you may need to set could be similar to this:

    {
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"route53:ChangeResourceRecordSets"
],
"Resource": [
"arn:aws:route53:::hostedzone/",
"arn:aws:logs:*:*:*"
]
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"ec2:*"
],
"Resource": "*"
},

The above shows the basic code template that could be used to accomplish this. You may want to add checks to validate the instance id, or find the instance id by its name, or use a waiter instead of a fixed 30 second sleep and other checks you feel to make it production ready.

Photo Credit

Photo by Braden Collum on Unsplash

Further Reading and Improvements:

  • The code described here is sample code and not the complete listing.
  • Add error/exception handling as needed.

Leave a Reply