Ansible is a radically simple IT automation engine that doesn’t need any agent infrastructure on the clients that are managed. Ansible only needs a ssh daemon and luckliy that comes installed out of the box on most environments. As such, Ansible is quickly gaining traction compared to frameworks like Puppet and Chef.
Ansible is also great for cloud provisioning, which we will explore in future posts. This post will discuss how to keep track of our manually installed cloud infrastructure when we want to manage those systems with Ansible. We’ll use Amazon’s EC2 as an example.
Ansible uses the term inventory to refer to the set of systems that your Ansible playbooks or commands work against. By default, the static inventory is defined in /etc/ansible/hosts. As I work on test automation and continuous delivery, let’s assume I previously created some build servers & slaves and selenium test grids on EC2. My Ansible hosts file will look something like the following:
When I now want to run a command for all buildslaves, I can refer to the group buildslaves instead of having to mention each and every buildslave individually.
Static inventory and cloud provisioning
An inventory as described above, is what Ansible calls a static inventory, which sounds logical as all systems are statically configured. For cloud infrastructure, however, this does not make much sense. EC2, like most cloud platforms, reassigns a new public ip-address to your instances when it is (re)booted. So, unless you want to keep your ec2 instances up and running indefinitely, putting the ip-addresses in your hosts file is not a lasting option.
Luckily for us, Ansible also supports the concept of a dynamic inventory. Such a dynamic inventory can be used if you want to keep your inventory in a different system, like your cloud provider or your company’s CMDB. Dynamic inventory is fed by using external inventory scripts, provided by Ansible for many cloud infrastructure platforms, like Amazon EC2, Rackspace Cloud and DigitalOcean.
For EC2, we use
https://raw.github.com/ansible/ansible/devel/contrib/inventory/ec2.ini, in combination with boto, the python interface for AWS.
You can see what information is gathered by the inventory script by executing it by itself:
The easiest way to integrate the external inventory script with your Ansible commands and playbooks is to provide it every time you use Ansible:
This command will first collect information about all running instances in all EC2’s regions. Then it will ping all your instances in all EC2’s regions that are up and running, assuming that you have configured boto to use your AWS key and provided some ssh keys to be used by Ansible.
Another way is to replace the /etc/ansible/hosts file with your ec2.py script. Do not forget to mark it as executable and to copy your ec2.ini to the same location. When the hosts file is executable, Ansible will execute it to feed the dynamic inventory automatically.
However, you will lose the opportunity to mix static and dynamic inventories. Therefore, you can also create hosts as a directory, as in:
Every file in this directory will be treated by Ansible as an inventory file: executables feed the dynamic inventory while other files are treated as static inventories.
Until now, all these inventories are centrally configured on your machine. If you use an Ansible server in your company to manage your infrastructure, you will probably have different users accessing this Ansible server and all your Ansible site configurations share the same inventories.
Luckily, Ansible provides the option to configure the location of your inventory in the ansible.cfg file.
Ansible looks in several locations for your ansible.cfg:
It would be nice if you could just create a hosts directory containing your inventory configuration in the directory where you execute your Ansible commands (the root of your playbook configuration for example). However, that is currently not supported. You have to explicitly configure the inventory directory in your ansible.cfg.
Clearly, configuring your inventory in your ansible.cfg looks like the preferred solution. You can have multiple Ansible ec2 configurations on the same Ansible machine as your configuration is not centralized through /etc/ansible. Also, you can easily put your ec2.py and ec2.ini in your version control system with your Ansible playbooks.
Caching the dynamic inventory
One final warning: as interacting with AWS is rather slow, the information is cached. Your ec2.ini file defines the maximum cache age:
The cache can be found in ~/.ansible/tmp and consists of two files. The first file, ansible-ex2.index, provides a short index of the active instances in your aws account. It just provides a list of ip-addresses with region and instance-id:
The second file, ansible-ec2.cache, provides much more elaborate information on your instances. Besides detailed information on each instance, it provides a number of groups based on characteristics as region, tags, vpc, instance-type, etc. For example:
describes all your instances running in the eu-west-1 region (Ireland) of Amazon EC2.
shows which of these instance share the same vpc. Or
shows which of these instances is tagged as buildserver.
Now that we have a way to dynamically gather relevant information from our cloud infrastructure, we’d like to use these in our playbooks. However, as this post is getting long enough as it is, that’s for a next post.
This blog was written by Robert van Vark.