If you’re implementing a dev-build-deploy cycle that uses EC2 instances in AWS, you’ll need an automated way to start, stop and terminate instances. It’s neither realistic nor scalable to go to the EC2 dashboard each time an instance’s state needs to be changed.
Some folks like to use Cloud Formation scripts, which is a reasonable approach if you only use AWS cloud services. The moment you need to manage non-AWS resources, CF isn’t an option.
Using Ansible, you can manage instance state with a few very similar tasks. As long as you tagged the instances at creation with something meaningful, subsequent runs of your ansible playbook can manage all instances that possess that tag.
You first use the
ec2_remote_facts module to gather facts of all the instances in the region you specify (using vars) that are then filtered on the tag name. In this case,
instance_tag is the name we’ll pass to this playbook as an
–extra-vars variable when it is run.
Beware of Greedy Pattern Matching
When I wrote this playbook, I thought I would combine all the state controls into a single task - start, stop and terminate are similar and so shouldn’t require separate tasks. While this is generally true, the pattern matching that you need in place to ensure that you aren’t sending a terminate command to an instance that you don’t intend to terminate must be rock-solid. I hit edge cases during development where I accidently term’d (junk) instances. I decided that I would rather use separate tasks than try to be more clever than the EC2 API.
To stop all instances in your region tagged with Name:subsystem_123_build, run this:
ansible-playbook aws.yml --tags "gather-ec2-facts,print-ec2-facts,stop-instance" --extra-vars "instance_tag=subsystem_123_build"
It isn’t necessary to run the
print-ec2-facts task, but it does provide super clear console or log feedback about the instances that about to be changed.
Here’s the code.