This tutorial provides an example of a static Ansible inventory and explains how to convert it into a dynamic one. It also provides instructions on how to prepare the equipment and materials, export the logistics, and troubleshoot any issues that may arise. Solutions to troubleshoot issues encountered during the first-time implementation of a dynamic inventory are also provided.
Ansible is one of the most well-known tools for infrastructure engineers to manage and maintain infrastructure, particularly for IT automation. It became my go-to resource when I was a novice System Engineer six years ago, and it remains relevant to this day.
The first time I worked with Ansible was to maintain a small cluster of Hadoop servers. For 1-10 servers, I was able to manage them using the static inventory below:
#sample-for-demo-purpose
[web]
192.168.1.1
192.168.1.2
[api]
192.168.2.1
192.168.2.2
[payment]
192.168.3.1
192.168.3.1
The text above provides an example of a static Ansible inventory, which defines hosts in a .ini-like file format. However, managing 100, 1,000, or even 1 million instances can be challenging. That's why it's necessary to convert your static inventory into a dynamic one. The process is relatively straightforward to implement.
Requirements
To complete this tutorial, you need to meet the following requirements:
AWS IAM Access with minimal access to your instance list and details
EC2 Instances running on top of AWS
Python virtualenv installed on your device
Internet connection (it's impossible to function in today's world without the Internet)
Prepare the Equipment and Materials
You can't begin the battle without a fully loaded gun, so let's prepare the arsenal first. Create a script to generate your inventory from AWS.
ec2.py EC2 external inventory script
ec2.ini Ansible EC2 external inventory script settings
Above scripts were created by the Ansible community. For a faster process, simply clone this repository from my GitHub account:
Export the logistics
To ensure the code above functions as intended, we need to export some environment variables. This won't impact any existing environments, so feel free to proceed with confidence.
~ export AWS_ACCESS_KEY_ID=<your_aws_access_key_id>
~ export AWS_SECRET_ACCESS_KEY=<your_aws_secret_access_key>
Next, you need to install certain pip packages to run Ansible and its scripts. I recommend using virtualenv to maintain a clean environment.
~ virtualenv venv
~ source venv/bin/activate
~ cd to/my/cloned/github/repository
~ pip install -r ansible/requirements.txt
Next, you must set the ANSIBLE_INVENTORY
and EC2_INI_PATH
environment variables to associate them with Ansible.
~ export EC2_INI_PATH=/path/to/my/cloned/github/repository/ansible/inventory/ec2.ini
~ export ANSIBLE_INVENTORY=/path/to/my/cloned/github/repository/ansible/inventory/ec2.py
First, run the script to ensure it is already executable by applying the chmod +x
command to the ec2.py file. Then, execute the following command:
~ ./path/to/my/cloned/github/repository/ansible/inventory/ec2.py
When everything is working as we planned before, the output should look like this:
...
"tag_Name_my_instance_1": [
"192.168.155.53"
],
"tag_Name_my_instance_2": [
"192.168.235.48"
],
"tag_Name_my_instance_3": [
"192.168.12.223"
],
"tag_Name_my_instance_4": [
"192.168.14.83"
],
"tag_Name_my_instance_5": [
"192.168.106.144"
],
"tag_Name_my_instance_6": [
"192.168.210.60"
],
...
This means that your code is working. Now, test your dynamic inventory with Ansible by running the command above.
~ ansible -m ping tag_Name_my_instance_1 -u your_ssh_user
Additionally, the anticipated output should be:
192.168.155.53 | SUCCESS => {
"changed": false,
"ping": "pong"
}
Your first dynamic inventory is now ready for implementation, allowing you more time to rest.
Troubleshooting
The first-time implementation of this dynamic inventory led me to encounter some issues. The solutions are provided below:
Python can’t read the configurations
[WARNING]: * Failed to parse /.../.../.../.../ansible/inventory/ec2.py with script plugin: Inventory script (/.../.../.../.../ansible/inventory/ec2.py) had an execution
error: Traceback (most recent call last): File "/.../.../.../.../ansible/inventory/ec2.py", line 155, in <module> import boto ImportError: No module named boto[WARNING]: * Failed to parse /.../.../.../.../ansible/inventory/ec2.py with ini plugin: /.../.../.../.../ansible/inventory/ec2.py:3: Error parsing host definition ''''': No
closing quotation[WARNING]: Unable to parse /.../.../.../.../ansible/inventory/ec2.py as an inventory source[WARNING]: No inventory was parsed, only implicit localhost is available[WARNING]: Could not match supplied host pattern, ignoring: all[WARNING]: provided hosts list is empty, only localhost is available[WARNING]: Could not match supplied host pattern, ignoring: tag_Name_my_instance_1[WARNING]: No hosts matched, nothing to do
This means that your Python interpreter is reading from the system. Set the PYTHONPATH
to point to your virtual environment's packages.
~ export PYTHONPATH=/.../.../.../venv/lib/python2.7/site-packages
Script can’t read ElasticCache clusters
When you run the ec2.py script for the first time, some users encounter a problem like:
ERROR: "Forbidden", while: getting ElastiCache clusters
To eliminate this problem, uncomment the following line inside the ec2.ini file.:
#elasticache = False