Разберёмся, как описать узлы, собрать их в группы, навесить переменные и проверить, что Ansible видит ровно то, что ты задумал. Это фундамент - на экзамене RHCE (EX294) с инвентаря начинается почти любая задача, и если ты ошибся тут, дальше можно не стараться.
Файл inventory ansible: форматы INI и YAML
Статический инвентарь - это просто текстовый файл, который ты пишешь руками. Самый частый формат - INI, его исторически зовут файлом hosts (по имени старого /etc/ansible/hosts). Минимальный ansible inventory hosts выглядит так:
Код: Выделить всё
# файл inventory
web1.example.com
web2.example.com
db1.example.com
192.168.10.50
Код: Выделить всё
[webservers]
web1.example.com
web2.example.com
[dbservers]
db1.example.com
db2.example.com
Код: Выделить всё
# файл inventory.yml
all:
children:
webservers:
hosts:
web1.example.com:
web2.example.com:
dbservers:
hosts:
db1.example.com:
db2.example.com:

Вложенные группы, диапазоны и спецгруппы all/ungrouped
Группы можно вкладывать друг в друга. В INI это делается через суффикс :children - так создаётся группа групп. Допустим, у нас есть площадки в двух городах, и обе входят в общую группу production:
Код: Выделить всё
[msk_web]
web01.msk.example.com
web02.msk.example.com
[spb_web]
web01.spb.example.com
[production:children]
msk_web
spb_web
Когда хостов много и имена идут по шаблону, руками их перечислять глупо. Ansible умеет диапазоны хостов: запись web[01:05] разворачивается в web01, web02, web03, web04, web05. Работают и числовые, и буквенные диапазоны:
Код: Выделить всё
[webservers]
web[01:05].example.com
[dbservers]
db-[a:c].example.com
Есть две группы, которые Ansible создаёт сам, ты их нигде не объявляешь. all - это вообще все узлы из инвентаря, скопом. ungrouped - те узлы, что не попали ни в одну твою группу (кроме all). Поэтому шаблон hosts: all в плейбуке означает "выполни везде" - и это, кстати, классический способ случайно зацепить прод. Привыкай явно указывать группу.
Переменные хоста и группы прямо в инвентаре
Инвентарь умеет хранить переменные. Их два вида. Переменные хоста пишутся в той же строке, что и узел (host vars), переменные группы - в секции [имя:vars] (group vars). Пример на INI:
Код: Выделить всё
[webservers]
web1.example.com http_port=8080 max_clients=200
web2.example.com http_port=8081
[webservers:vars]
ansible_user=deploy
proxy_env=production
В YAML то же самое выглядит структурно - переменные хоста идут как вложенные ключи под именем узла, переменные группы - в блоке vars:
Код: Выделить всё
all:
children:
webservers:
hosts:
web1.example.com:
http_port: 8080
max_clients: 200
web2.example.com:
http_port: 8081
vars:
ansible_user: deploy
proxy_env: production
Указание инвентаря и проверка через ansible-inventory
Какой файл считается инвентарём? Есть три варианта, по приоритету. Первый - флаг -i прямо в команде: ansible -i inventory all -m ping. Второй - параметр inventory в ansible.cfg, чтобы не писать -i каждый раз:
Код: Выделить всё
[defaults]
inventory = ./inventory
remote_user = deploy
Самое полезное - научиться проверять инвентарь, а не верить ему на слово. Команда ansible-inventory показывает, как Ansible на самом деле распарсил твой файл. Два режима:
Код: Выделить всё
# плоский JSON со всеми группами, хостами и переменными
ansible-inventory -i inventory --list
# наглядное дерево групп и вложенности
ansible-inventory -i inventory --graph
Код: Выделить всё
@all:
|--@webservers:
| |--web1.example.com
| |--web2.example.com
|--@production:
| |--@msk_web:
| | |--web01.msk.example.com
|--@ungrouped:
Маленькая заметка про другие дистрибутивы. Сам инвентарь от ОС не зависит вообще - INI и YAML одинаковы на RHEL, Ubuntu/Debian, RED OS и Astra Linux. Разница только в установке самого Ansible (dnf против apt) и в том, какие модули ты потом вызовешь (firewalld и SELinux - это про RHEL-семейство).
Типичные грабли
- Отступы в YAML. Один лишний пробел - и хост уехал не в ту группу или файл вообще не парсится. INI в этом плане прощает больше.
- Хост в ungrouped, хотя ты его группировал. Почти всегда это опечатка в имени группы или забытая секция :children.
- Двоеточие после хоста в YAML. web1.example.com без двоеточия - синтаксическая ошибка. Двоеточие обязательно, даже если переменных нет.
- Имя группы all или ungrouped своими руками. Эти имена зарезервированы, не переопределяй их.
- Переменные свалены в инвентарь "чтобы быстрее". Работает сегодня, болит через месяц. Выноси в group_vars/host_vars.
- Дефис в имени группы. В INI имена групп с дефисом работают, но лучше использовать подчёркивание (web_servers), чтобы имя совпадало с допустимым именем переменной.
Сделай руками, не подсматривая:
- Создай файл inventory в формате INI: группы webservers (хосты web[01:03].lab) и dbservers (db01.lab). Добавь группу production через :children, включающую обе.
- Задай в инвентаре group var ansible_user=ansible для production и host var http_port=8080 для web01.lab.
- Пропиши inventory в ansible.cfg, чтобы не указывать -i вручную.
- Прогони ansible-inventory --graph и ansible-inventory --list. Убедись, что web01 в двух группах, http_port виден только у него, а ungrouped пуст.
- Перепиши тот же инвентарь в YAML (inventory.yml) и сравни вывод --graph - он должен совпасть один в один.
- Чем отличаются спецгруппы all и ungrouped и почему hosts: all - опасный шаблон?
- Как в INI создать вложенную группу (группу групп) и как то же самое выглядит в YAML?
- Во что развернётся запись web[01:04].example.com и сохранится ли ведущий ноль?
- Какие три способа указать Ansible, какой инвентарь использовать, и какой из них приоритетнее?
Инвентарь - это карта твоего парка машин: кто есть, как сгруппирован, под кем подключаться. Освой оба формата (INI и YAML), пойми вложенные группы и диапазоны, держи переменные минимально и проверяй результат через ansible-inventory --graph перед каждым запуском. Сделаешь это привычкой - и плейбуки перестанут уходить "не туда", а на RHCE первый шаг любой задачи будешь делать на автомате.
Источники по теме: https://docs.ansible.com/ansible/latest ... ntory.html и https://docs.ansible.com/ansible/latest ... ntory.html