Introduction
Keeping track of multiple servers is quite similar to solving a complex puzzle, which requires great precision. Remembering all the IP addresses, assigned roles, and relevant environments can quickly become confusing. This is where Ansible comes into action. Ansible is particularly useful and serves as a powerful automation tool. But as with any great tool, there are prerequisites that are: a plan, a schedule, and a directory. For Ansible, this means an inventory. In the automation landscape, Ansible inventory is like the blueprint for Ansible automation.
In this guide, we will walk you through everything you need to know about Ansible inventory, which is often a core part of an ansible and terraform course. You will learn what an Ansible inventory is and why it’s so important. How to create your first inventory in different formats (INI and YAML). The power of organizing your servers with groups and variables. The critical difference between static and dynamic inventories, and when to use each. We will also discuss some advanced tips for managing complex environments like a professional.
Let us first understand what Ansible inventory is.
What is an Ansible Inventory?
Ansible inventory is a plain text file that lists the machines you want to manage. These machines are called managed nodes or “hosts.” The computer you run Ansible from is called the control node. The inventory file acts as the bridge between your control node and your managed nodes.
The primary purpose of the inventory is to define your infrastructure for Ansible. It answers questions like:
- Which servers are part of my infrastructure?
- Which servers are web servers? Which are database servers?
- Are there servers specific to my production environment? What about staging?
- What are the IP addresses or hostnames I should use to connect?
By default, Ansible looks for an inventory file at:
/etc/ansible/hosts
However, it is best practice to have a separate Ansible inventory file for each project you undertake. This is to keep things organized and also to prevent accidental running of a command on the wrong set of servers. You may point Ansible to your custom inventory file with the -i flag.
Now, we have a good understanding of Ansible inventory. Let us move on to the next section, where we will create inventory.
Getting Started: Your First Ansible Inventory File
Let’s create our very first Ansible inventory file. It’s easier than you think. All you need is a text editor. Create a file named inventory. Inside this file, you can simply list the IP addresses or domain names of the servers you want to manage, with one server per line.
# This is our first inventory file. Lines starting with # are comments.
192.168.1.10
192.168.1.11
app-server.yourdomain.com
That’s it! You now have a functional Ansible inventory.
To test that Ansible is using your file and that it can connect to your hosts, you may try out a simple “ad-hoc” command. The ping module in Ansible does not perform a network ping. Instead, it logs into the remote machine and runs a small script that reports back “pong” if successful. It is the perfect way to check connectivity.
In your terminal run the following in the same dir as your inventory file:
ansible all -i inventory -m ping
Let’s break that down:
- ansible: The command to run an ad-hoc task.
- all: A pattern that tells Ansible to run this command on all hosts found in the inventory.
- -i inventory: This -i flag is what you use to point out the path of your inventory file.
- -m ping: the -m option is for which Ansible module you wish to use which in this case is the ping module.
If your setup is correct (which includes that your SSH access to managed nodes is enabled) you should see a successful “pong” response from each server which is listed in your file.
192.168.1.10 | SUCCESS => {
"changed": false,
"ping": "pong"
}
192.168.1.11 | SUCCESS => {
"changed": false,
"ping": "pong"
}
app-server.yourdomain.com | SUCCESS => {
"changed": false,
"ping": "pong"
}
Congratulations! You’ve just used your first Ansible inventory.
Ansible Inventory Formats: INI vs. YAML
Ansible gives you two formats for your server inventory files: INI and YAML. While both are valid, the community standard has largely become YAML for modern projects.
The Classic INI Format
INI is the traditional format for Ansible inventory. It’s simple and uses section headers (like [group_name]) to organize hosts. Here’s an example of an inventory in INI format that defines a few servers and groups them:
# inventory in INI format
[webservers]
web1.example.com
web2.example.com
[dbservers]
db1.example.com
[datacenter:children]
webservers
dbservers
- Pros: It’s very easy to read for simple lists and has been around for a long time.
- Cons: It can become messy for complex inventories with lots of variables. The order in which you define groups can sometimes matter, which can lead to confusing errors.
The Modern YAML Format
YAML (YAML Ain’t Markup Language) is a data serialization format that is popular for configuration files due to its human-readable structure. Ansible uses YAML extensively for playbooks, and you can use it for your inventory as well. Here is the same inventory from above, but written in YAML:
# inventory in YAML format
all:
children:
webservers:
hosts:
web1.example.com:
web2.example.com:
dbservers:
hosts:
db1.example.com:
datacenter:
children:
webservers:
dbservers:
- Pros: The structure is much cleaner, especially when you start adding variables. It’s easier to manage complex, nested groups, and it avoids the parsing issues that can sometimes affect INI files. It provides a much better flow and is easier to manage at scale.
- Cons: Syntax is stricter. Indentation is very important, and an out-of-place space will cause the file to fail.
- Recommendation: It is suggested that for any new project that you think will grow, you start with the YAML format. Its structure and scale ability make it the better choice for modern infrastructure management.
Organizing Your Infrastructure: The Power of Groups
As your server count grows, a flat list of hosts becomes unmanageable. This is where groups come in. Grouping allows you to organize your hosts logically, making it easy to run tasks on specific subsets of your infrastructure. A great way to think about organizing groups is by the “What, Where, and When” of your hosts.
- What: What is the server’s function? (e.g., webservers, dbservers, api_gateways)
- Where: A server may be located very far away (as in a datacenter in the Netherlands) or right on your doorstep on your office network.
- When: Development, staging, and finally production are the stages of the life of a server.
Platforms enable you to add multiple groups to a single host, allowing you to monitor them all at once, whether they’re in your office, on the East Coast, or in staging.
Nested Groups (Metagroups)
You can also create groups of groups. These are often called “metagroups” or “parent groups.” This is useful for creating broader categories. For example, you might have a linux group that contains both your webservers and dbservers groups.
Here’s how you’d do that in YAML:
all:
children:
webservers:
hosts:
web1.prod.example.com:
web2.prod.example.com:
dbservers:
hosts:
db1.prod.example.com:
linux:
children:
webservers:
dbservers:
Now, if you run a playbook against the linux group, it will automatically target all hosts in webservers and dbservers.
Making Your Inventory Smart: Using Variables
Variables are what turn your static inventory into a dynamic configuration powerhouse. They allow you to assign specific settings to hosts or groups, which your playbooks can then use. This is perfect for things like setting user names, connection ports, or application-specific configurations.
Host Variables
Host variables can be defined in the inventory file, but this would make things untidy. Instead, it is more reasonable to prepare such a directory as a host_vars, in the exact location as the inventory file. Within that directory, you can make a YAML file for each host that requires specific variables. The filename must match the hostname in your inventory exactly.
Directory Structure:
Contents of host_vars/web1.prod.example.com.yml:
ansible_user: admin
ansible_port: 2222
app_version: "2.5.1"
Group Variables
Group variables apply to every host within a group. This is incredibly efficient for setting common parameters for a role, like the database port for all your database servers.
The Best Practice: Create a directory named group_vars. Inside, create a YAML file for each group. The filename must match the group name from your inventory.
Directory Structure:
Contents of group_vars/dbservers.yml:
database_port: 5432
ansible_user: db_admin
enable_backups: true
A Note on Precedence: Ansible merges variables from all sources, but there’s a clear order of priority. The most important rule to remember is that host variables always override group variables. This allows you to set a general rule for a group and then create specific exceptions for individual hosts.
Static vs. Dynamic Inventory: Choosing the Right Approach
So far, we’ve been working with static inventories. These are files that you create and update by hand.
Static Inventory
- What it is: A manually maintained text file (INI or YAML).
- When to use it: Ideal for small, stable environments where server configurations rarely change, such as on-premise data centers with a fixed number of machines or a small development setup.
- Pros: Simple to understand and set up.
- Cons: Becomes a major bottleneck in large or cloud-based environments. Manually tracking servers that are constantly being created and destroyed is nearly Impossible.
Dynamic Inventory
This is where things get really exciting. A dynamic inventory is not a file you writeyourself. Instead, it’s a script or plugin that Ansible runs in real-time to fetch a list ofyour infrastructure from an external source.
- Why Use It: Any cloud-based infrastructure would require this type of inventory to know what is launched and running. The same applies to virtualized ones or anything in which the hosts are temporary.
- Pros: The inventory updates in real time, so at any one time, you know what is where and what is running, reducing the number of manual errors made and ensuring that your automation scripts target the correct resources.
- Cons: It is slightly more time-consuming to create initially.
How Dynamic Inventory Works
Ansible provides two ways to implement dynamic inventory: inventory plugins and legacy scripts.
Inventory Plugins (The Modern Way)
Plugins are the recommended method. They are built into Ansible and are highly configurable. Each leading cloud provider has plugins: aws_ec2, azure_rm, and gcp_compute.
In order to use one, you will make a YAML file to configure it. Considering an example, suppose you need all of your EC2 instances in AWS that have the tag environment: production, you will name a file aws_ec2.yml:
# aws_ec2.yml - Dynamic inventory configuration for AWS
plugin: aws_ec2
regions:
- us-east-1
filters:
tag:environment: production
keyed_groups:
# Create groups based on the value of the 'role' tag
- key: tags.role
prefix: role
You then run your playbook using this file as your inventory:
ansible-playbook -i aws_ec2.yml my_playbook.yml
Ansible will now automatically connect to the AWS API, find all matching instances, and group them based on their tags. No manual updates needed, ever!
Advanced Techniques for Professional Users
Once you’ve mastered the basics, these techniques will help you manage even the most complex setups.
Patterns: Targeting with Precision
Patterns are how you tell Ansible which hosts or groups to run a task against. You’ve already used all pattern, but you can get much more specific.
Here are some common patterns:
Use Case | Command Example | Description |
Target a single group | ansible webservers -m ping | Runs on all hosts in the webservers group. |
Target multiple groups (OR) | ansible “webservers:dbservers” -m ping | Runs on hosts that are in webservers OR dbservers. |
Target an intersection (AND) | ansible “webservers:&production” -m ping | Runs on hosts that are in webservers AND production. |
Exclude a group (NOT) | ansible “webservers:! staging” -m ping | Runs on hosts in webservers but NOT in staging. |
Use wildcards | ansible “web*.example.com”-m ping | Runs on all hosts with names starting with web. |
Mastering patterns gives you fine-grained control over your playbook executions
Managing Multiple Environments
Never, ever use a single inventory file for both your production and staging environments. It’s a recipe for disaster. The best practice is to completely isolate your environments. A common and effective way to do this is with a directory structure.
When you want to run a playbook against production, you simply point to the correct inventory:
ansible-playbook -i inventories/production/ site.yml
And for staging:
ansible-playbook -i inventories/staging/ site.yml
This separation is one of the most important practices for safe and reliable automation.
Frequently Asked Questions
Q1 What is an Ansible inventory?
Ansible inventory is a list of servers Ansible manages. Think of it as a contact list for your computers, telling Ansible which machines to work on and how to group them.
Q2 Where is Ansible inventory stored?
By default, Ansible looks for a file at `/etc/ansible/hosts`. However, you are free to create your own inventory file and just tell Ansible where to find it.
Q3 What is the difference between inventory and hosts in Ansible?
Inventory is the entire collection of machines you manage. A host is just one single computer in that collection. The default inventory file itself is often named `hosts`.
Q4 How do you generate an Ansible inventory file?
You can create a text file and list your servers. For dynamic lists, use a script that fetches server data from cloud providers like AWS, keeping it updated automatically.
Conclusion
Ansible inventory file is more than just a list of servers. Ansible inventory is the blueprint to your whole infrastructure. It is a plain text file that defines what nodes Ansible can manage, how to talk to them, and their classification. Once this blueprint is complete, the management of the IT infrastructure is possible. In this blog, we have discussed everything from creating a simple list of hosts to dynamic inventories that dynamically identify servers in the cloud.
Investing time in creating a well-structured inventory will make your automation stand firm, be more predictable and simpler to expand with Ansible in the future.