Найти в Дзене
Infra as Code по-русски

Ansible inventory: что это и как настроить (Часть 2)

Аннотация. В этой части продолжаем разбирать инвентарь Ansible простыми словами: порядок загрузки, переменные (групповые и хостовые), псевдонимы, поведенческие параметры подключения и подводные камни. С готовыми INI/YAML примерами и чек‑листом. Что это. Ansible может собирать инвентарь из нескольких источников: файла INI/YAML, целой директории, нескольких -i подряд, динамического инвентаря. Все эти источники объединяются в один «каталог» хостов и групп. Как управлять. [defaults] inventory = inventories/dev Подводные камни. Зачем. Переменные позволяют описать окружение: версии, порты, пути, учетные записи, параметры подключения. Благодаря этому роли становятся переиспользуемыми. Где хранить. Правило простоты. Общие значения — в группах, исключения — в host_vars. Чем ниже по иерархии, тем «ближе к железу». Пример INI: Здесь app-1 и app-2 задают хостовые переменные прямо в строке. app-3 унаследует http_port=8080 из группы. То же самое на YAML: Важно. Хостовые переменные всегда «сильнее»
Оглавление

Аннотация. В этой части продолжаем разбирать инвентарь Ansible простыми словами: порядок загрузки, переменные (групповые и хостовые), псевдонимы, поведенческие параметры подключения и подводные камни. С готовыми INI/YAML примерами и чек‑листом.

Управление порядком загрузки инвентаря

Что это. Ansible может собирать инвентарь из нескольких источников: файла INI/YAML, целой директории, нескольких -i подряд, динамического инвентаря. Все эти источники объединяются в один «каталог» хостов и групп.

Как управлять.

  • Указывайте один базовый путь в ansible.cfg — так меньше сюрпризов:
[defaults]
inventory = inventories/dev

  • Если всё же нужно несколько источников: ansible -i inventories/dev -i inventories/common .... Ansible объединит группы и хосты.
  • Детерминированность важна. Чтобы гарантировать предсказуемый порядок применения групповых переменных, стройте иерархию через :children (дочерние группы), а не надейтесь на «магический» порядок объединения несвязанных групп.

Подводные камни.

  • Один и тот же хост в разных несвязанных группах с одинаковыми ключами → «кто победит» неочевидно. Решение: вынесите конфликтующие ключи в host_vars/<hostname>.yml.
  • Смешивание форматов в одной директории (INI+YAML) допустимо, но проще придерживаться одного стиля на проект.

Переменные в инвентаре: зачем и как

Зачем. Переменные позволяют описать окружение: версии, порты, пути, учетные записи, параметры подключения. Благодаря этому роли становятся переиспользуемыми.

Где хранить.

  • В инвентаре (в файле INI/YAML): быстро и локально для примеров/демо.
  • В group_vars/ и host_vars/: масштабируется, удобно для большого проекта.
  • В vars_files роли/плейбука: когда переменные — часть роли.

Правило простоты. Общие значения — в группах, исключения — в host_vars. Чем ниже по иерархии, тем «ближе к железу».

Переменные хоста (host vars): INI и YAML на примере

Пример INI:

-2

Здесь app-1 и app-2 задают хостовые переменные прямо в строке. app-3 унаследует http_port=8080 из группы.

То же самое на YAML:

-3

Важно. Хостовые переменные всегда «сильнее» групповых.

Псевдонимы инвентаря (inventory aliases)

Зачем. Удобно называть хост по‑человечески (alias), а реальный адрес хранить отдельно — меняется IP, а имя в инвентаре остаётся.

INI:

[web]
web1 ansible_host=10.10.0.5 ansible_user=ubuntu \
ansible_ssh_private_key_file=~/.ssh/web1.pem

inventory_hostname = web1, подключение идёт к ansible_host.

YAML:

-4

Подсказка. Старайтесь использовать alias без домена (web1), а FQDN хранить в ansible_host — так легче мигрировать DNS/IP.

Определение переменных в INI

Варианты:

-5

Подводные камни.

  • Пробелы вокруг = не критичны, но лучше писать key=value.
  • Булевы значения пишите как строки ("true"/"false") или явно проверяйте в шаблонах.
  • Не используйте зарезервированные имена для собственных значений (например, inventory_hostname).

Наследование значений (группы групп)

Ключевая идея. Группа может быть «родителем» другой группы через :children (INI) или вложенность (YAML). Значения переменных из дочерней группы переопределяют такие же ключи из родительской. Если хост входит в несвязанные (не родственные) группы с одинаковым ключом — порядок не гарантирован, рассчитывать на «кто победит» нельзя.

Как задать родителя и ребёнка

INI:

-6

YAML:

-7

Правила приоритета (только в инвентаре)

  1. host_vars ▶ переменные дочерней группы ▶ переменные родительской группы ▶ all:vars.
  2. Несвязанные группы (нет родства через :children) — приоритет не определён. Не кладите один и тот же ключ в такие группы.
  3. Inline‑переменные в строке хоста в INI трактуются как хостовые (т.е. выше групповых).
  4. group_vars/<group>.yml и блок [group:vars] — это один уровень приоритета (выбирайте один стиль для проекта).

Живой пример и «кто победил»

Задача: задать log_level на разных слоях и понять итог для каждого хоста.

INI:

-8

Разбор:

  • app-1.dev.example входит в цепочку env_dev → role_app → app_dev_example. Итог log_level=debug (дочерняя role_app перебила env_dev).
  • app-2.dev.example имеет хостовое trace — оно сильнее любых групп.
  • Хосты группы role_kafka получат info (их дочерняя role_kafka перебивает env_dev).

Проверка себя:

ansible-inventory -i inventories/dev --graph
ansible -i inventories/dev app_dev_example -m debug -a 'var=log_level'

Организация host_vars и group_vars host_vars и group_vars

Когда использовать.

  • Если переменных уже десятки/сотни, уходите из inline‑строк в файлы.
  • Секреты — только через Ansible Vault в group_vars/ или host_vars/.

Пример:

-9

Как объединяются переменные и где острые углы

Коротко о приоритетах (только инвентарь):
host_vars ▶ переменные дочерней группы ▶ переменные родительской группы ▶ all:vars.

Списки и словари. По умолчанию Ansible не делает «умные» слияния — последний встретившийся ключ побеждает целиком. Если нужно «склеивать» словари/списки, делайте это явным set_fact с фильтром combine/unique или в шаблоне Jinja2.

Параметры подключения (поведенческий инвентарь)

Это «как именно стучаться к хосту». Эти ключи не про бизнес‑логику ролей, а про транспорт: через что подключаться, под каким пользователем, куда класть временные файлы, как поднимать привилегии.

Мини‑словарик ключей

  • ansible_connection — способ подключения: ssh (по умолчанию), local, docker, kubectl, winrm (Windows), chroot и др.
  • ansible_host — реальный адрес/имя узла (IP/FQDN). В инвентаре можно оставить короткий alias, а сюда положить адрес.
  • ansible_port — порт транспорта (обычно 22 для SSH, 5985/5986 для WinRM).
  • ansible_user / ansible_password — учётка удалённой машины. Пароли храните в Vault.
  • ansible_ssh_private_key_file — путь к приватному ключу для SSH.
  • Повышение привилегий: become: true, ansible_become_user (обычно root), ansible_become_method (sudo), ansible_become_password (Vault).
  • Исполнители: ansible_python_interpreter (например, /usr/bin/python3), ansible_shell_type (sh, bash), ansible_shell_executable (путь к шеллу).
  • Доп. SSH‑аргументы: ansible_ssh_common_args (общие) и ansible_ssh_extra_args (для командной сессии). Полезно для ProxyJump/проксей.
Важно. Переменные окружения удалённого хоста задавайте не в инвентаре, а в плейбуке/роли через environment: — так чище и контролируемее.

Базовые примеры

Linux по SSH с ключом (INI):

-10

То же на YAML:

-11

Частые ошибки новичков и как их избежать

Ниже — «грабли», на которые чаще всего наступают. И быстрые обходные дорожки.

Ошибка 1. Смешали alias и реальный адрес.

  • Симптом: меняете IP, а плейбук всё ещё лезет по старому.
  • Причина: в инвентаре как inventory_hostname стоит FQDN, а ansible_host не используется.
  • Как правильно: alias краткий (web1), реальный адрес в ansible_host.

Ошибка 2. Конфликтующие значения в несвязанных группах.

  • Симптом: log_level то info, то debug без логики.
  • Причина: один хост состоит в двух группах, не связанных через :children.
  • Решение: стройте иерархию (:children), конфликтующие ключи — в host_vars.

Ошибка 3. Пароли в INI.

  • Симптом: «секреты» попадают в git.
  • Решение: храните в Vault (ansible-vault encrypt), подключайте как обычные vars.

Ошибка 4. Неэкранированные пробелы/спецсимволы.

  • Симптом: Ansible «кусает» половину строки.
  • Решение: кавычки вокруг значений с пробелами/двоеточиями, особенно в SSH‑аргументах.

Ошибка 5. Нет Python на удалёнке / не тот интерпретатор.

  • Симптом: модули падают, ping не работает.
  • Решение: поставьте python3, укажите ansible_python_interpreter=/usr/bin/python3.

Ошибка 6. become не работает.

  • Симптом: задачи «Permission denied».
  • Решение: become: true, правильный ansible_become_user, проверка sudoers. Для некоторых окружений добавьте become_flags=-H -S.

Ошибка 7. Дубли имен хостов.

  • Симптом: в --graph один и тот же хост всплывает в разных местах с разными переменными.
  • Решение: уникальные inventory_hostname, адрес — через ansible_host.

Ошибка 8. Попытка «склеить» словари/списки «по магии».

  • Симптом: часть ключей «пропала» после переопределения.
  • Решение: используйте combine/unique явно, не рассчитывайте на hash_behaviour=merge.

Мини‑чеклист самопроверки

ansible-inventory -i inventories/dev --graph # иерархия групп
ansible-inventory -i inventories/dev --list | jq . # что Ansible реально видит
ansible all -m ping -i inventories/dev # подключение
ansible web1 -m debug -a 'var=hostvars[inventory_hostname]' -i inventories/dev | head -n 50

Итог. Держите поведенческие ключи подключения простыми и явными, секреты — в Vault, и всегда проверяйте структуру инвентаря прежде чем грешить на роли/плейбуки.

Почему это работает

Ansible перед выполнением задач собирает переменные со всех источников (инвентарь, group_vars/host_vars, факты, плей), выстраивает их по приоритетам и применяет «самое близкое» значение к хосту. Поэтому: чем ниже по иерархии и ближе к хосту вы задаёте значение, тем выше шанс, что оно переопределит общее.

Что сделали

  • Разобрали, как Ansible объединяет инвентарь и почему лучше строить иерархию через :children.
  • Показали, где хранить переменные и как аккуратно переопределять их на уровне хоста.
  • Разобрали псевдонимы, поведенческие ключи подключения и частые грабли.

Сделать прямо сейчас

  • В ansible.cfg укажите единый путь к инвентарю.
  • Перенесите общие параметры в group_vars/, а исключения — в host_vars/.
  • Наведите порядок: alias в inventory_hostname, адрес в ansible_host.
  • Добавьте минимум один плей, который использует эти переменные в действии (шаблон, роль).

CTA

Если было полезно — подпишитесь на серию про Ansible. В комментариях напишите свою схему групп: помогу разложить по group_vars/host_vars и подсвечу риски. В следующей части — динамический инвентарь и constructed‑группы.