Skip to content

Inventory Management

Inventory Basics

Static Inventory

# inventory/production
[webservers]
web1.example.com ansible_host=192.168.1.10
web2.example.com

[dbservers]
db[01:03].example.com

[loadbalancers]
lb01.example.com
lb02.example.com

[webservers:vars]
http_port=80
proxy_timeout=5

[all:vars]
ansible_user=deploy
ansible_ssh_private_key_file=~/.ssh/id_rsa

YAML Format

# inventory/production.yml
all:
  children:
    webservers:
      hosts:
        web1.example.com:
          ansible_host: 192.168.1.10
        web2.example.com:
      vars:
        http_port: 80
        proxy_timeout: 5

    dbservers:
      hosts:
        db[01:03].example.com:

    loadbalancers:
      hosts:
        lb01.example.com:
        lb02.example.com:

  vars:
    ansible_user: deploy
    ansible_ssh_private_key_file: ~/.ssh/id_rsa

Dynamic Inventory

Dynamic Inventory (continued)

AWS Dynamic Inventory

#!/usr/bin/env python3

import boto3
import json

def get_ec2_instances():
    ec2 = boto3.client('ec2')
    instances = ec2.describe_instances()

    inventory = {
        'aws_ec2': {
            'hosts': []
        },
        '_meta': {
            'hostvars': {}
        }
    }

    for reservation in instances['Reservations']:
        for instance in reservation['Instances']:
            if instance['State']['Name'] == 'running':
                dns_name = instance['PublicDnsName']
                inventory['aws_ec2']['hosts'].append(dns_name)
                inventory['_meta']['hostvars'][dns_name] = {
                    'ansible_host': instance['PublicIpAddress'],
                    'instance_id': instance['InstanceId'],
                    'instance_type': instance['InstanceType']
                }

    return inventory

if __name__ == '__main__':
    print(json.dumps(get_ec2_instances(), indent=2))

Using Dynamic Inventory

# Make script executable
chmod +x inventory/aws_dynamic.py

# Test inventory script
./inventory/aws_dynamic.py --list

# Use with ansible
ansible-playbook -i inventory/aws_dynamic.py site.yml

Inventory Patterns

Using Patterns

# All hosts
ansible all -i inventory -m ping

# Specific group
ansible webservers -i inventory -m ping

# Multiple groups
ansible webservers:dbservers -i inventory -m ping

# Excluding groups
ansible all:!webservers -i inventory -m ping

# Using wildcards
ansible "*.example.com" -i inventory -m ping

# Using regex
ansible "~web[0-9]+" -i inventory -m ping

Inventory Variables

Host and Group Variables

# host_vars/web1.example.com.yml
---
http_port: 8080
app_env: production
ssl_enabled: true

# group_vars/webservers.yml
---
nginx_version: stable
php_version: "8.1"
max_clients: 200

Directory Structure

inventory/
├── production/
│   ├── hosts
│   ├── group_vars/
│   │   ├── all.yml
│   │   ├── webservers.yml
│   │   └── dbservers.yml
│   └── host_vars/
│       ├── web1.example.com.yml
│       └── db1.example.com.yml
└── staging/
    ├── hosts
    ├── group_vars/
    └── host_vars/

Connection Methods

SSH Configuration

[webservers]
web1.example.com ansible_connection=ssh ansible_user=deploy
web2.example.com ansible_port=2222 ansible_ssh_private_key_file=~/.ssh/web2.pem

[windows]
win1.example.com ansible_connection=winrm ansible_winrm_transport=basic

Connection Variables

# Group level connection settings
[production:vars]
ansible_connection=ssh
ansible_user=deploy
ansible_port=22
ansible_ssh_private_key_file=~/.ssh/id_rsa
ansible_ssh_common_args='-o StrictHostKeyChecking=no'

Inventory Plugins

Using Built-in Plugins

# aws_ec2.yml
plugin: aws_ec2
regions:
  - us-east-1
  - us-west-2
keyed_groups:
  - prefix: tag
    key: tags
  - prefix: instance_type
    key: instance_type
filters:
  instance-state-name: running

Custom Inventory Plugin

from ansible.plugins.inventory import BaseInventoryPlugin

class InventoryModule(BaseInventoryPlugin):
    NAME = 'custom_inventory'

    def verify_file(self, path):
        return True

    def parse(self, inventory, loader, path, cache):
        super(InventoryModule, self).parse(inventory, loader, path, cache)

        self.inventory.add_host('custom_host')
        self.inventory.set_variable('custom_host', 'custom_var', 'value')

Inventory Validation

Testing Inventory

# List all hosts
ansible-inventory -i inventory --list

# List host variables
ansible-inventory -i inventory --host web1.example.com

# Graph inventory
ansible-inventory -i inventory --graph

# YAML output
ansible-inventory -i inventory --list -y

Inventory Verification

- name: Verify inventory connectivity
  hosts: all
  gather_facts: no
  tasks:
    - name: Ping all hosts
      ping:
      register: ping_result

    - name: Display unreachable hosts
      debug:
        msg: "Host {{ inventory_hostname }} is unreachable"
      when: ping_result.unreachable is defined

Best Practices

Organization

inventory/
├── production/
│   ├── hosts                  # Production inventory file
│   ├── group_vars/           # Production group variables
│   └── host_vars/            # Production host variables
├── staging/
│   ├── hosts                 # Staging inventory file
│   ├── group_vars/           # Staging group variables
│   └── host_vars/            # Staging host variables
└── testing/
    ├── hosts                 # Testing inventory file
    ├── group_vars/           # Testing group variables
    └── host_vars/            # Testing host variables

Security

# Vault-encrypted group variables
---
db_credentials:
  user: !vault |
    $ANSIBLE_VAULT;1.1;AES256
    ...
  password: !vault |
    $ANSIBLE_VAULT;1.1;AES256
    ...

Documentation

# inventory/production/hosts
# Production Environment Inventory
# Last Updated: 2024-03-15
# Contact: [email protected]

[webservers]
# Frontend web servers
web1.example.com  # Primary web server
web2.example.com  # Secondary web server

[dbservers]
# Database servers
db1.example.com   # Primary database
db2.example.com   # Replica database

Troubleshooting

Common Issues

# Test SSH connection
ssh -v [email protected]

# Check inventory membership
ansible-inventory -i inventory --graph

# Verify variables
ansible -i inventory web1.example.com -m debug -a "var=hostvars[inventory_hostname]"

# Test connection with verbose output
ansible -i inventory web1.example.com -m ping -vvv

Debug Configuration

[defaults]
inventory_plugins = ~/.ansible/plugins/inventory:/usr/share/ansible/plugins/inventory
host_key_checking = False
timeout = 30

[inventory]
enable_plugins = host_list, script, auto, yaml, ini, toml

Maintenance

Version Control

# .gitignore
*.retry
.vault_pass
inventory/**/vault.yml

Inventory Updates

# Export current inventory
ansible-inventory -i inventory --list --yaml > inventory_snapshot.yml

# Compare inventories
diff inventory_snapshot.yml new_inventory.yml

# Validate new inventory
ansible-inventory -i new_inventory.yml --graph