Using Ansible With Dynamic Inventory in AWS

Ansible is a flexible and powerful configuration management tool. Anyone who has been using it, however, in a large, dynamic environment will probably agree that maintaining a static inventory file can become quite burdensome.

If you are using Ansible to run your playbooks against inventory in AWS, it is important that you take advantage of the AWS EC2 External Inventory Script. Using this script along with a well-planned tagging scheme will allow you to quickly and effectively target inventory in your AWS environment.

Imagine you have created three servers with the following tag in AWS:

Role Web Server

Instead of trying to place the hostnames or IP addresses of these nodes into a static inventory file, you could simply target the three servers in your playbook as follows:

- name: Install, start, and enable httpd
  hosts: tag_Role_Web_Server
  remote_user: centos
  become: true

  roles:
    - install_httpd

For more information on why the tag is formatted that way, please see the Tags section in Ansible's official documentation

You could do a quick sanity/safety check to make sure you are targeting the nodes you intended to target (make sure ec2.py is executable):

ansible -i ec2.py -u centos tag_Role_Web_Server -m ping

Finally, you would run your playbook command calling the inventory script to target the three nodes you just created with the command below (obviously replacing site.yml with the path to your main playbook file):

ansible-playbook -i ec2.py site.yml

Keep in mind that that the ec2.ini file must be in the same directory as the ec2.py script. It contains settings that will allow you to change how you target your inventory (more on that in a moment).

If you do not want to specify the -i flag and would like to just use the ec2.py as the default hosts file, simply place the contents of it in your default hosts file (normally in /etc/ansible/hosts). Again, make sure it is executable. If you do that correctly, you should be able to just run the following command:

ansible-playbook site.yml

Now, let's get back to ec2.ini. This file has a lot of options that allow you to change what your Ansible controller can and cannot see. If you only want your Ansible controller to search us-east-1 (and, yes, if your inventory only sits in us-east-1, you definitely want this because it is much faster), then you can simply make sure the following is present:

regions = us-east-1
#regions_exclude =

Also, Ansible by default will only pick up inventory that has public DNS names and/or IP addresses associated with it. If your inventory only has private DNS and/or IPs, make sure your ec2.ini contains the following:

destination_variable = private_dns_name
vpc_destination_variable = private_ip_address

Finally, remember that you can use commas with the & operation for even greater control over what you target in your environments. For example, let's say you have web servers in both your development and production environments, but you only want to target the web servers in your development environment. Well, you could rename all the tags on your development web servers to "Role Web Server Dev" and target them as such:

- name: Update web servers
  hosts: tag_Role_Web_Server_Dev
  remote_user: centos
  become: true

  roles:
    - modify_httpd

You would then change the tag on your production web servers appropriately. But that's too much work and leaves you with less flexibility/control in the future.

A better idea would be to make sure the inventory in your development environment has the "environment development" tag (the same principle applies toward your other environments). You could then use the & operation to target only the development web servers:

- name: Update web servers
  hosts: 'tag_Role_Web_Server,&tag_environment_development'
  remote_user: centos
  become: true

  roles:
    - modify_httpd

This will make sure you are only targeting the web servers in your development environment. Combining tags in this way will give you much finer precision when it comes to configuring your inventory.