Ansible Dynamic Inventory
Ansible Dynamic Inventory#
Dynamic inventory is useful when:
- Inventory changes over time as hosts start and stop
- Hosts need to be tracked from different sources
In those cases you probably have, or need, an external dynamic inventory system.
Ansible integrates with dynamic inventory in two ways:
- Inventory plugins
- Inventory scripts
Plugins are recommended over scripts.
Ansible Tower, now AWX or Red Hat Ansible Automation Platform, provides a GUI for handling dynamic inventory and syncing its inventory database with external inventory sources.
Run an ad hoc command#
You need to be able to SSH without a password.
ansible -i root@10.10.10.204, all -a 'uname -a'
To do this for multiple hosts:
ansible -i "root@10.10.10.93, root@10.10.10.92, root@10.200.1.94" all -a 'uptime'
To run a module for multiple hosts:
ansible -i "root@10.10.10.93, root@10.10.10.92, root@10.10.10.94" all -m setup
I have noticed that if one host requires a password, it will fail. If you set -k to ask for the SSH password, they all fail.
$ ansible -i "root@10.10.10.93, root@10.10.10.92, root@10.10.10.94" all -m setup
root@10.10.10.92 | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: root@10.10.10.92: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).\r\n",
"unreachable": true
}
Ensure that Jenkins is started:
ansible -i "root@10.10.10.94," all -m service -a "name=jenkins state=started"
To use an inventory script with an ad hoc command:
ansible -i digital_ocean.py all -a 'uptime'
You can use the ansible-inventory utility to check the hosts visually:
ansible-inventory -i digital_ocean.py --list
Remember to ensure the inventory script is executable with
chmod +x inventory_file.py
What dynamic inventory output should look like#
We want this inventory to know how to connect, so set the following variables:
ansible_connection=ssh
ansible_user=vagrant
ansible_host=10.0.0.1
We need to ensure that the _meta variable is set
It should look like this:
{
"_meta": {
"hostvars": {
"host001": {
"var001": "value"
},
"host002": {
"var002": "value"
}
}
}
}
If you intend to replace an existing static inventory file with an inventory script, it must return a JSON object with an all group that includes every host in the inventory as a member and every group in the inventory as a child.
{
"_meta": {
"hostvars": {}
},
"all": {
"children": [
"ungrouped"
]
},
"ungrouped": {
"children": []
}
}
Other variables we might want are:
- Guest OS or distribution
- Name
- Networks
Inventory scripts#
You can run a Python script to get your hosts.
This can be done by passing in the script as the inventory parameter: -i openstack_inventory.py
If you want to do this implicitly, remember that explicit is better than implicit.
You can place the script at /etc/ansible/hosts
There are existing integrations to check out as scripts for:
There are other existing inventory scripts
Or you can create your own inventory script
Using inventory directories and multiple inventory sources#
Using a directory can let Ansible use multiple inventories at the same time. This also allows mixing static and dynamic inventories.
Files ending in ~, .orig, .bak, .ini, .cfg, .retry, .pyc, .pyo will be ignored
Which you can change to your own with the inventory_ignore_extensions entry in ansible.cfg
More information is available in the documentation on multiple inventory sources.
Build a dynamic inventory#
In previous versions you had to create a script or program that could output JSON in the correct format when invoked with the proper arguments.
Inventory sources#
Inventory sources are what you pass to -i. They can be a path to a file, a script or the raw data for a plugin to use.
host list: comma-separated list of hostsyaml: path to YAML format data fileconstructed: path to YAML config fileini: path to INI formatted data filevirtualbox: path to YAML config filescript plugin: path to executable outputting JSON
Read more about developing plugins.
Inventory plugins normally only execute at the start of a run, before playbooks, plays and roles are loaded. They can be re-executed via the meta: refresh_inventory task, which clears out the existing inventory and rebuilds it.