Ровно эту боль решает ansible динамический инвентарь. Вместо того чтобы хранить список хостов вручную, ты говоришь Ansible: "сходи в облако (или в Docker, или в Kubernetes) и спроси у него актуальный список прямо сейчас". Источник правды - сама инфраструктура, а не текстовый файл, который кто-то забыл обновить.
Статический против динамического: в чём разница
Статический инвентарь - это просто файл (INI или YAML), где хосты и группы прописаны руками. Он отлично подходит для лабы и для парка, который меняется раз в квартал. Динамический инвентарь - это исполняемый источник, который Ansible опрашивает в момент запуска и получает свежий список.
Раньше dynamic inventory делали через скрипты: писали программу на Python (или чём угодно), которая по флагу
Код: Выделить всё
--listКод: Выделить всё
ec2.pyСовременный путь - inventory plugin. Ansible inventory plugin это модуль внутри коллекции, который умеет ходить в конкретный источник (AWS, Docker, GCP, OpenStack, VMware) и отдавать хосты единообразно. Конфигурируется он не кодом, а маленьким YAML-файлом. Плюсы очевидны: общий синтаксис, кеширование из коробки, переиспользование подключений и человеческая документация. Скрипты отдавали готовый JSON и всё; плагины же дают единый язык для вычисляемых групп и переменных.

Включаем плагины: enable_plugins в ansible.cfg
Чтобы Ansible вообще трогал твои YAML-файлы инвентаря, нужный плагин должен быть разрешён. По умолчанию включён только плагин
Код: Выделить всё
autoКод: Выделить всё
ansible.cfgКод: Выделить всё
[defaults]
inventory = ./inventory
[inventory]
enable_plugins = auto, host_list, yaml, ini, amazon.aws.aws_ec2, community.docker.docker_containers, constructed
Код: Выделить всё
docker.ymlКод: Выделить всё
docker.yamlКод: Выделить всё
aws_ec2.ymlКод: Выделить всё
aws_ec2.yamlКод: Выделить всё
hosts.ymlВнутри файла обязателен ключ
Код: Выделить всё
pluginКод: Выделить всё
ansible-galaxy collection install community.docker amazon.aws
Классический пример из книги - инвентарь по локальным контейнерам. Связка ansible docker полезна, когда ты гоняешь тестовое окружение в контейнерах и хочешь катать на них плейбуки как на обычных хостах. Создаём файл
Код: Выделить всё
inventory/docker.ymlКод: Выделить всё
---
plugin: community.docker.docker_containers
docker_host: unix://var/run/docker.sock
connection_type: docker_api
verbose_output: false
keyed_groups:
- prefix: image
key: docker_image
compose:
ansible_user: "'root'"
Код: Выделить всё
connection_type: docker_apiКод: Выделить всё
keyed_groupsКод: Выделить всё
image_nginxКод: Выделить всё
image_redisКод: Выделить всё
ansible-inventory -i inventory/docker.yml --graph
Два ключа делают плагины по-настоящему мощными, и они работают одинаково почти во всех инвентарных плагинах.
keyed_groups создаёт группы динамически из данных хоста. Например, в облаке у каждой машины есть теги. Хочешь, чтобы все ноды с тегом Role=web попали в группу
Код: Выделить всё
role_webcompose вычисляет переменные хоста через Jinja2. Типичный кейс - подменить адрес подключения: в облаке у инстанса есть и публичный, и приватный IP, и ты решаешь, по какому ходить. Обрати внимание на двойные кавычки в
Код: Выделить всё
composeПример облачного плагина amazon.aws.aws_ec2, файл
Код: Выделить всё
inventory/aws_ec2.ymlКод: Выделить всё
---
plugin: amazon.aws.aws_ec2
regions:
- eu-central-1
filters:
instance-state-name: running
keyed_groups:
- prefix: role
key: tags.Role
separator: "_"
- prefix: az
key: placement.availability_zone
compose:
ansible_host: private_ip_address
Код: Выделить всё
google.cloud.gcp_computeКод: Выделить всё
openstack.cloud.openstackКод: Выделить всё
vmware.vmware.esxi_hostsConstructed: дособираем группы из чего угодно
Отдельный герой - плагин
Код: Выделить всё
constructedФайл
Код: Выделить всё
inventory/constructed.ymlКод: Выделить всё
---
plugin: constructed
strict: false
groups:
webservers: "'web' in (group_names | join(','))"
high_mem: ansible_memtotal_mb is defined and ansible_memtotal_mb > 8000
keyed_groups:
- prefix: distro
key: ansible_distribution | lower
Код: Выделить всё
groupsКод: Выделить всё
ansible_*Код: Выделить всё
constructed.ymlКод: Выделить всё
aws_ec2.ymlКод: Выделить всё
ansible-inventory -i inventory/ --graph
ansible-inventory -i inventory/ --list
- Файл назван не так. Самая частая ошибка. Плагин молча игнорирует файл с неподходящим именем. Сверяйся с суффиксом из документации плагина.
- Плагин не в enable_plugins. Установил коллекцию, написал конфиг, а инвентарь пустой - почти всегда забыли строку в секции ansible.cfg.
Код: Выделить всё
[inventory] - Кавычки в compose. упадёт, потому что root будет трактоваться как переменная. Нужно
Код: Выделить всё
compose: ansible_user: root.Код: Выделить всё
"'root'" - Нет прав/кредов. Для AWS нужны ключи (env или профиль), для Docker - доступ к сокету. Если ansible-inventory ничего не вернул, проверь доступ к API руками.
- Забыл проверить графом. Не запускай плейбук вслепую. Сначала , убедись, что хосты и группы те самые.
Код: Выделить всё
ansible-inventory --graph
Повтори руками, чтобы отложилось:
- Подними 2-3 контейнера: , аналогично web2 и redis.
Код: Выделить всё
docker run -d --name web1 nginx - Установи коллекцию: .
Код: Выделить всё
ansible-galaxy collection install community.docker - Включи плагин в ansible.cfg и создай из примера выше.
Код: Выделить всё
inventory/docker.yml - Запусти и найди группы
Код: Выделить всё
ansible-inventory -i inventory/docker.yml --graphиКод: Выделить всё
image_nginx.Код: Выделить всё
image_redis - Добавь с группой по имени и скорми каталог целиком через
Код: Выделить всё
constructed.yml.Код: Выделить всё
-i inventory/
Код: Выделить всё
dnf install ansible-coreКод: Выделить всё
aptКонтрольные вопросы
- Чем inventory plugin лучше старого inventory-скрипта и почему скрипты считают легаси?
- Почему файл с конфигом Docker-плагина обязан называться так, чтобы оканчиваться на docker.yml, и что будет иначе?
- В чём разница между keyed_groups и compose, и зачем в compose двойные кавычки вокруг строкового значения?
- Что делает плагин constructed и почему он умеет опираться на ansible_* факты?
Когда хосты живут в облаке или в контейнерах, статический файл проигрывает: список устаревает мгновенно. Дай Ansible самому спросить инфраструктуру через inventory plugin, разрешив его в
Код: Выделить всё
enable_pluginsКод: Выделить всё
ansible-inventory --graph