Reputation: 818
Running a system designed with CloudFormation that experienced a series of unfortunate hardware failures recently. For cost-effectiveness of this not heavily used system, it is backed by only a single instance and does not use a load balancer. I want to add an auto-scaling group to it to make sure that at least no manual intervention is necessary to react to similar faults in the future. However, since the system is publicly accessible the instance needs to have an elastic IP associated, which is where I'm struggling. My idea was that the IP will simply be re-associated to a new instance after it started up. No need to care about user sessions, etc here.
As far as I'm aware it's not possible to configure a single elastic IP to be reused in an auto-scaling group (which I understand, I know that this is a niche use-case). Therefore I ended up trying to re-associate the IP during CloudFormation::Init. Is there a more elegant solution?
Upvotes: 1
Views: 572
Reputation: 269111
As you point out, you can use a User Data script to the Launch Configuration so that, when Auto Scaling launches a new instance, the script re-attaches the Elastic IP address or updates a Route 53 DNS name.
To attach an Elastic IP address, the script would need to obtain its own Instance ID, then run the attach command:
#!/bin/bash
INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id/)
aws ec2 associate-address --allocation-id xxx --instance-id $INSTANCE_ID
Alternatively, you could have a DNS Name associated with the instance and, when the instance launches, update the DNS Name to point to the instance.
From Amazon Route 53: How to automatically update IP addresses without using Elastic IPs - DEV Community:
#!/bin/bash
# Extract information about the Instance
INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id/)
AZ=$(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone/)
MY_IP=$(curl -s http://169.254.169.254/latest/meta-data/public-ipv4/)
# Extract tags associated with instance
ZONE_TAG=$(aws ec2 describe-tags --region ${AZ::-1} --filters "Name=resource-id,Values=${INSTANCE_ID}" --query 'Tags[?Key==`AUTO_DNS_ZONE`].Value' --output text)
NAME_TAG=$(aws ec2 describe-tags --region ${AZ::-1} --filters "Name=resource-id,Values=${INSTANCE_ID}" --query 'Tags[?Key==`AUTO_DNS_NAME`].Value' --output text)
# Update Route 53 Record Set based on the Name tag to the current Public IP address of the Instance
aws route53 change-resource-record-sets --hosted-zone-id $ZONE_TAG --change-batch '{"Changes":[{"Action":"UPSERT","ResourceRecordSet":{"Name":"'$NAME_TAG'","Type":"A","TTL":300,"ResourceRecords":[{"Value":"'$MY_IP'"}]}}]}'
There is no "elegant" way to automatically do this type of operation for an Auto Scaling group.
Upvotes: 3