Setting up AWS Dynamic Inventories with Ansible

Clouds like AWS make spinning up IT infrastructure quick and (nearly) painless. Virtual machines (VM’s) can be added at any time within minutes. On the other hand, clouds do little to help IT track and manage the software which is run inside each of those VM’s. As a result, cloud environments can quickly get out of hand. Red Hat Ansible Towers empowers IT teams to take back control with automated host discovery, configuration management, and provisioning.

Red Hat Ansible Tower offers a powerful feature set for managing virtual and physical systems (Linux and Windows), along with a variety of network devices such as load balancers and routers. To help support ever more dynamic, cloud based environments, Ansible Tower includes a dynamic external inventory system which can track hosts from cloud providers, LDAP, Cobbler, and/or enterprise CMDB systems.

In this article, we will take a look at the steps required to set up a dynamic inventory in Ansible Tower which pulls AWS EC2 host information from the AWS API.

Assumptions

  1. Ansible Tower 3.6.x is installed and licensed

  2. Ansible Tower has network connectivity with AWS API endpoints

  3. One or more EC2 instances running Windows or Linux need to be managed

AWS API Authentication

When querying the AWS API, Tower must authenticate itself to query EC2 host information. Authentication can be done using an AWS secret access key. As an alternative, Tower can leverage an AWS IAM role assigned to Tower’s EC2 instance, assuming that Tower itself runs on EC2.

Option 1 - AWS Secret access key

  1. Use the AWS IAM web UI or CLI to create a new secret access key. Record the access key ID and secret access key values in a safe and secure location.

  2. Create a new credential in Ansible Tower with CREDENTIAL TYPE = “Amazon Web Services” using the access key and secret key values from the previous step.

Note: The user account owning the secret access key must have permissions equal to or greater than those listed for the IAM policy shown below, under Option 2.

Option 2 - AWS IAM role

Using the AWS IAM web UI or CLI:

  1. Create a new IAM policy using the JSON below.

{ 
   "Version":"2012-10-17",
   "Statement":[ 
      { 
         "Sid":"Demo201505282045",
         "Effect":"Allow",
         "Action":[ 
            "ec2:Describe*",
            "route53:ListHostedZones",
            "route53:ListResourceRecordSets",
            "rds:Describe*",
            "elasticache:Describe*"
         ],
         "Resource":"*"
      }
   ]
}


2. Create a new AWS IAM EC2 service role and assign the policy created in the previous step.

3. Select the new IAM role when launching the EC2 instance which will run Ansible Tower. If the EC2 instance has already been launched, the IAM role can be attached to it on the fly (Instance Settings → Attach/Replace IAM Role).

Note: With the AWS IAM role authentication option, no Tower credential is required.

Dynamic Inventory Creation

  1. Create a new inventory (Inventories → “plus” button → Inventory).

2. Enter a name (#1) for the new inventory, click “SAVE” (#2), and then click on “SOURCES” (#3).

3. Click on the “plus” button to add a new source.

4. Fill in the fields as follows, then click “SAVE” (#8)

NAME (#1) - Enter a meaningful name

SOURCE (#2) - Select “Amazon EC2” from the drop down menu

CREDENTIAL (#3) - If using an AWS secret access key for AWS API authorization, select the “Amazon Web Services” credential added early. If using an IAM role, leave this field blank.

REGIONS (#4) - Select the region matching EC2 instance location from the drop down menu. Note: Multiple regions can be selected or there is an “All” option.

INSTANCE FILTERS (#5) - Leave blank for initial testing

UPDATE OPTIONS (#6) - Select OVERWRITE checkbox

SOURCE VARIABLES (#7) - If EC2 instances are in a public subnet, leave this field blank for initial testing. If EC2 instances are in a private subnet, see “Private EC2 subnets” section below for required setting.

Start the inventory sync process (#1), then click HOSTS (#2) to see the results.

Example results from Amazon EC2 dynamic inventory source:

Additional Configuration

Instance Filters

You can filter for specific EC2 instances using the INSTANCE FILTER field. This filtering mechanism allows hosts to be selected based on metadata returned for each host by the AWS API. Note that hosts are added to the inventory results if they match ANY of the specified filters. See Amazon DescribeInstances documentation for more information.

ec2.py

Ansible Tower utilizes an inventory script named “ec2.py” to query the AWS API and create the dynamic inventory list. When run at the command line, this script supports a number of options and settings which can be set in a configuration file named “ec2.ini”. When ec2.py is run by Tower, these parameters can be set via in the SOURCE VARIABLES field using YAML syntax.

Private EC2 subnets

Important - EC2 instances that are in a private subnet and that do not have a public IP address assigned will not be listed in the dynamic inventory results until you set the following ec2.ini setting in the SOURCE VARIABLES field:

vpc_destination_variable: private_ip_address

Conclusion

Cloud environments can quickly get out of hand. You may be in a situation where you are dealing with multiple snowflake configurations and systems that may have experienced configuration drift. By using Red Hat Ansible Tower, you can both discover and take back control of AWS with automated host discovery, configuration management, and provisioning.

About the Author

Mike McDonough is Principal Cloud Architect for Stone Door Group, a cloud and DevOps consulting company and team lead for the Ansible Migration Accelerator℠ solution. This offering provides administrators with a comprehensive software, services and training solution that enables administrators to quickly get Ansible deployed to manage their public cloud infrastructure. To learn more, drop us an email at letsdothis@stonedoorgroup.com.

References

https://docs.ansible.com/ansible-tower/latest/html/userguide/inventories.html#amazon-web-services-ec2

https://github.com/ansible/ansible/tree/stable-2.9/contrib/inventory