Semi-Auto Scaling

In those days, I had my first experience with auto-scaling of AWS EC2 instances. And, as everything in AWS, it has been a PITA to give a sense to the many obscure option and possibilities.

The main issue with auto-scaling is deploying updates of the software. Due the requirements and the expected flow, and my unwillingness to deal with Ansible, Capistrano or similar devil's tools, I've organized the following setup:

  • a reference instance for each type of server I have to auto-scale
  • the manually inited auto-scaling groups, with related launch configurations and load balancers
  • the following bash script

When I have to deploy a new update (it happens once a month, in average), I start up the reference instance, provide to git pull the new code and/or modify the common configurations, and launch the script which itself generates a new AMI, creates a new launch configuration, updates the auto-scaling group, and shuts down the old instances.

The script depends on aws and jq, both installable with apt.

#!/bin/bash

export IFS=$'
'

# The name of your auto scaling group.
# This parameter will be used to generate the launch configuration's name.
group=tool

# Your Instance ID reference
instanceid="i-1234567890abcdefg"

# The security group(s) for your instances.
# Use here the Group ID, not the Group Name, or it will complain.
securitygroup="sg-12345678"

# Usual instance type desired for scaled instances.
instancetype="t2.medium"

# For convenience: if you already have an up-to-dated AMI, put here the AMI ID.
# Otherwise, a new one will be created and used.
# imageid="ami-12345678"
imageid=""

confname=$group-`date +"%Y.%m.%d"`-`shuf -i1-100 -n1`

if [ -z "$imageid" ]
then
	echo "I'm going to generate a new AMI"
	sleep 5

	imageid=`aws ec2 create-image --instance-id $instanceid --name $confname --reboot | jq '.ImageId' -r`
	aws ec2 wait image-available --image-ids $imageid
	echo "AMI Created: $imageid"
	sleep 1
else
	echo "I'm going to use existing AMI $imageid"
	sleep 5
fi

aws autoscaling create-launch-configuration \
	--launch-configuration-name $confname \
	--image-id $imageid \
	--instance-type $instancetype \
	--instance-monitoring Enabled=false \
	--security-groups $securitygroup

echo "Configuration Created"
sleep 5

aws autoscaling update-auto-scaling-group \
	--auto-scaling-group-name $group \
	--launch-configuration-name $confname

echo "Group Updated"

old=`aws autoscaling describe-auto-scaling-instances | jq -r ".AutoScalingInstances[] | select(.AutoScalingGroupName | contains(\"$group\")) | .InstanceId"`
for i in $old
do
	aws autoscaling terminate-instance-in-auto-scaling-group \
		--no-should-decrement-desired-capacity \
		--instance-id $i
done

echo "Old Instances Terminated"

echo "Reference instance is going to be shut down..."
sleep 5

aws ec2 stop-instances --instance-ids $instanceid
echo "Instance Stopped"

Hammer-powered DevOps...