Ansible Static Inventory
Introduction
An inventory in Ansible is a collection of hosts (nodes) that Ansible manages. Static inventory is the simplest form of inventory where you manually define hosts and groups in plain text files. This approach is perfect for small to medium-sized environments with relatively stable infrastructure.
In this tutorial, you'll learn how to create, organize, and use static inventory files effectively in your Ansible automation workflows.
Understanding Static Inventory
Static inventory files in Ansible provide a way to categorize and organize the servers you want to manage. They allow you to:
- Define groups of servers based on function, location, or other criteria
- Set variables for individual hosts or entire groups
- Create hierarchical groups (groups of groups)
- Specify connection details for each host
Unlike dynamic inventory (which we'll cover in another tutorial), static inventory requires manual updates when your infrastructure changes.
Basic Inventory File
The simplest inventory file is just a list of hostnames or IP addresses, one per line:
192.168.1.50
192.168.1.51
192.168.1.52
web.example.com
db.example.com
By default, Ansible looks for this file at /etc/ansible/hosts
, but you can specify a different inventory file using the -i
option:
ansible -i inventory_file all -m ping
Organizing Hosts with Groups
Grouping hosts makes it easier to target specific sets of servers. Here's how to define groups in the INI format:
[webservers]
web1.example.com
web2.example.com
192.168.1.100
[dbservers]
db1.example.com
db2.example.com
[development]
dev.example.com
staging.example.com
With this inventory, you can target all webservers with:
ansible webservers -m ping
Or all database servers:
ansible dbservers -m yum -a "name=postgresql state=latest"
Range Patterns
Ansible supports range patterns to make defining multiple similar hosts easier:
[webservers]
web[1:5].example.com
[dbservers]
db-[a:c].example.com
This expands to:
- web1.example.com through web5.example.com
- db-a.example.com, db-b.example.com, and db-c.example.com
Group Variables
You can assign variables to groups using the [group:vars]
section:
[webservers]
web1.example.com
web2.example.com
[webservers:vars]
http_port=80
proxy_timeout=5
These variables will be available to all hosts in the webservers group.
Host Variables
Variables can also be set for individual hosts:
[webservers]
web1.example.com http_port=8080 ansible_user=admin
web2.example.com http_port=8081 ansible_user=deploy
Groups of Groups
You can create hierarchical group structures:
[webservers]
web1.example.com
web2.example.com
[dbservers]
db1.example.com
db2.example.com
[east_datacenter]
web1.example.com
db1.example.com
[west_datacenter]
web2.example.com
db2.example.com
[datacenters:children]
east_datacenter
west_datacenter
Now you can target all hosts in both datacenters with:
ansible datacenters -m ping
Connection Settings in Inventory
You can specify connection details for each host:
[webservers]
web1.example.com ansible_connection=ssh ansible_user=admin ansible_ssh_private_key_file=/path/to/key
web2.example.com ansible_connection=ssh ansible_user=deploy ansible_port=2222
localhost ansible_connection=local
Common connection variables include:
ansible_connection
: Connection type (ssh, local, docker, etc.)ansible_user
: Username for SSH connectionsansible_port
: Port to connect toansible_ssh_private_key_file
: Path to private key fileansible_become
: Whether to use privilege escalationansible_become_method
: Method for privilege escalation (sudo, su, etc.)ansible_become_user
: User to become
YAML Format for Inventory
While the INI format is common, Ansible also supports YAML for inventory files, which can be more readable for complex configurations:
all:
children:
webservers:
hosts:
web1.example.com:
http_port: 8080
ansible_user: admin
web2.example.com:
http_port: 8081
vars:
proxy_timeout: 5
dbservers:
hosts:
db1.example.com:
db2.example.com:
vars:
db_port: 5432
datacenters:
children:
east_datacenter:
hosts:
web1.example.com:
db1.example.com:
west_datacenter:
hosts:
web2.example.com:
db2.example.com:
Multiple Inventory Files
For better organization, you can split your inventory into multiple files within a directory structure:
inventory/
├── group_vars/
│ ├── webservers.yml
│ └── dbservers.yml
├── host_vars/
│ ├── web1.example.com.yml
│ └── db1.example.com.yml
├── production
└── staging
To use this inventory, specify the directory:
ansible -i inventory/ all -m ping
Visualizing Your Inventory
You can see the hosts in your inventory and their group memberships with:
ansible-inventory -i inventory_file --graph
Example output:
@all:
|--@dbservers:
| |--db1.example.com
| |--db2.example.com
|--@webservers:
| |--web1.example.com
| |--web2.example.com
|--@ungrouped:
For more detailed information including variables:
ansible-inventory -i inventory_file --list
Practical Example: Complete Static Inventory
Let's create a complete example for a small web application environment:
# Production environment
[prod_webservers]
prod-web1.example.com
prod-web2.example.com
[prod_dbservers]
prod-db1.example.com
[prod:children]
prod_webservers
prod_dbservers
[prod:vars]
env=production
[email protected]
# Staging environment
[staging_webservers]
staging-web1.example.com
[staging_dbservers]
staging-db1.example.com
[staging:children]
staging_webservers
staging_dbservers
[staging:vars]
env=staging
[email protected]
# Web servers across all environments
[webservers:children]
prod_webservers
staging_webservers
[webservers:vars]
http_port=80
ansible_user=webadmin
firewall_allowed_tcp_ports=[80, 443]
# Database servers across all environments
[dbservers:children]
prod_dbservers
staging_dbservers
[dbservers:vars]
db_port=5432
ansible_user=dbadmin
backup_folder=/var/backups/postgres
With this inventory, you could run a playbook on all production servers:
ansible-playbook -i inventory site.yml --limit prod
Or update all database servers across environments:
ansible-playbook -i inventory db-update.yml --limit dbservers
Inventory Testing and Verification
Before using your inventory in production, it's a good practice to verify it:
-
Check for syntax errors:
bashansible-inventory -i inventory --graph
-
Ensure you can reach all hosts:
bashansible -i inventory all -m ping
-
Check which hosts would be affected by a playbook:
bashansible-playbook playbook.yml -i inventory --list-hosts
Common Inventory Patterns and Best Practices
-
Use meaningful group names: Group names should clearly indicate the purpose or function of the servers.
-
Group by function and environment: Create groups based on server function (web, db, cache) and environment (prod, dev, staging).
-
Use host_vars and group_vars directories: For complex setups, store variables in separate YAML files.
-
Document your inventory: Add comments to explain the purpose of servers and groups.
-
Version control your inventory: Store your inventory files in a version control system like Git.
-
Use vault for sensitive data: Use Ansible Vault to encrypt sensitive variables.
-
Keep it DRY (Don't Repeat Yourself): Use group hierarchies and variable inheritance to avoid duplication.
Workflow Diagram
Here's a simple visualization of how static inventory fits into the Ansible workflow:
Summary
Static inventory in Ansible provides a straightforward way to organize and manage your infrastructure. By defining hosts and groups in simple text files, you gain the ability to effectively target specific sets of servers for configuration management and automation tasks.
In this tutorial, you've learned:
- How to create basic static inventory files
- Ways to organize hosts into meaningful groups
- Methods for setting variables at host and group levels
- Techniques for creating hierarchical group structures
- Best practices for managing your inventory
While static inventory works well for stable environments, as your infrastructure grows or becomes more dynamic, you might want to explore dynamic inventory solutions, which we'll cover in another tutorial.
Exercises
- Create a static inventory file with at least three groups: webservers, dbservers, and monitoring.
- Add variables to specify different SSH users for each group.
- Create a group that includes all servers from other groups.
- Test your inventory by running an ad-hoc ping command against different groups.
- Add range patterns to define 5 web servers (web1 through web5).
Additional Resources
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)