1

We have an autoscaling group with n no. of ec2 instances. We have a route53 record set (multi wieght) created which points to the ip address of autoscaling group. For every ec2 scaling action, i wanted to query the running instances in autoscaling group and update the dns using the userdata script.

I am using aws cli to query the ec2 instances running in the autoscaling group:

aws autoscaling describe-auto-scaling-instances --region us-east-1 --output text --query "AutoScalingInstances[?AutoScalingGroupName=='myapp-asg'].InstanceId" | xargs -n1 aws ec2 describe-instances --instance-ids $ID --region us-east-1 --query "Reservations[].Instances[].PrivateIpAddress" --output text

This gives all the ipaddress in the autoscaling group in below format:

20.91.0.1
20.91.0.2
20.91.0.3
20.91.0.4

Using aws cli i want to update the dns. Below is the command i am using:

aws --region us-east-1 route53 change-resource-record-sets --hosted-zone-id "Zone-id" --change-batch '{"Changes": [{"Action": "UPSERT","ResourceRecordSet": {"Name": "'"myrecord.mydomain.com"'","Type": "A","TTL": 60,"Weight": 200,"SetIdentifier":"myrecord","ResourceRecords": [{"Value": "20.91.0.1"},{"Value": "20.91.0.2"}]}}]}'

How do I automate the ipadress which i get from the first command to update the values for record sets in the second command

samtoddler
  • 8,463
  • 2
  • 26
  • 21

1 Answers1

1

You can just iterate over the values you get from the first command. Roughly like this



AWS_ROUTE53_ZONEID="redacted"

TTL="600"

IPS=$(aws autoscaling describe-auto-scaling-instances --region us-east-1 --output text --query "AutoScalingInstances[?AutoScalingGroupName=='myapp-asg'].InstanceId" | xargs -n1 aws ec2 describe-instances --instance-ids $ID --region us-east-1 --query "Reservations[].Instances[].PrivateIpAddress" --output text)

for IP in $IPS;
for HOSTNAME in  host1 host2 host3
do

aws route53 change-resource-record-sets --hosted-zone-id $AWS_ROUTE53_ZONEID --change-batch "{ \"Changes\": [ { \"Action\": \"UPSERT\", \"ResourceRecordSet\": { \"Name\": \"$HOSTNAME\", \"Type\": \"A\", \"TTL\": $TTL, \"ResourceRecords\": [ { \"Value\": \"$IP\" } ] } } ] }"

echo "Updated the DNS Zone to $IP"

done

I actually will write some python code using boto3 library, because that will give me all kinds of error handling.

 asg_client = boto3.client('autoscaling')
 asg_response = asg_client.describe_auto_scaling_groups(AutoScalingGroupNames=["myasg"])

 instance_ids = []

 for i in asg_response['AutoScalingGroups']:
     for k in i['Instances']:
         instance_ids.append(k['InstanceId'])

Once you get the instances you can simply iterate over the same to update the dns records change_resource_record_sets

def change_record(domain, subdomain, target_ip, action, ttl=900):
    """ Change the record for subdomain """
    zone_id = get_hosted_zone_id(domain)
    name = subdomain + "." + domain
    client.change_resource_record_sets(
        HostedZoneId=zone_id,
        ChangeBatch={
            "Comment": "%s subdomain %s from zone %s" % (action, subdomain, zone_id),
            "Changes": [
                {
                    "Action": action,
                    "ResourceRecordSet": {
                        "Name": name,
                        "Type": "A",
                        "ResourceRecords": [{"Value": target_ip}],
                        "TTL": ttl,
                    },
                }
            ],
        },
    )

This whole thing is static though, As Autoscaling brings down and up instances depending on the requirements. Good idea would be to create a CloudWatch event rule and invoke the lambda. This would even remove stale records and updates the records.

{
{
  "source": [
    "aws.autoscaling"
  ],
  "detail-type": [
    "EC2 Instance Launch Successful",
    "EC2 Instance Terminate Successful"
  ]
}
samtoddler
  • 8,463
  • 2
  • 26
  • 21
  • Thanks for the answer. In my case I wanted to update the route53 dns record for a wieghted value which contains the ip address of all autoscaling group ip address. Below is an example: {"Name": "'"myrecord.mydomain.com"'","Type": "A","TTL": 60,"Weight": 200,"SetIdentifier":"myrecord","ResourceRecords": [{"Value": "20.91.0.1"},{"Value": "20.91.0.2"}]}}]}' Basically i want one record to have multiple ipaddress in dns. Here for the record "myrecord.mydomain.com", i want to have all the asg ip address with wieghted dns – user14907472 Feb 10 '21 at 15:58
  • @user14907472 you still can do it same way `change_record` function you just update the IP addresses there. If you wanna do it via the shell script consider this via building a template and then using the same in the commandline, as described here [How do I create a simple resource record set in Amazon Route 53 using the AWS CLI?](https://aws.amazon.com/premiumsupport/knowledge-center/simple-resource-record-route53-cli/). Because building with in shell will be a tricky. – samtoddler Feb 10 '21 at 16:44