Ответ
В Ansible переменные переопределяются согласно строгой иерархии приоритетов — от наименьшего к наибольшему. Знание этой иерархии критически важно для написания предсказуемых и поддерживаемых ролей и плейбуков.
Иерархия переменных (по возрастанию приоритета):
- Роли: defaults (
defaults/main.yml) — Наименьший приоритет. Предназначены для задания безопасных значений по умолчанию, которые должны быть легко переопределены. - Инвентарь: переменные группы (
group_vars/) - Инвентарь: переменные хоста (
host_vars/) - Плейбук: переменные (
vars:в play) - Роли: переменные (
vars/main.yml) — Более высокий приоритет, чем defaults. Используются для значений, специфичных для данной роли. - Блок: переменные (
vars:внутриblock:) - Задача: переменные (
vars:внутри task) - Включенные переменные (
include_varsилиvars_files) — Выполняются во время работы плейбука. - Факты (facts), включая
set_fact— Динамически установленные факты. - Extra Variables (
-eв командной строке) — Наивысший приоритет. Всегда переопределяют всё.
Практический пример из моего опыта:
Я создаю роль для настройки Nginx. В defaults/main.yml задаю порт 80, но в group_vars/production.yml переопределяю его на 443 для продакшена, а для конкретного хоста в host_vars/lb01.yml могу задать особые настройки таймаутов.
# defaults/main.yml
nginx_port: 80
nginx_worker_processes: auto
# group_vars/production.yml
nginx_port: 443
nginx_worker_connections: 4096
# playbook.yml
- hosts: webservers
roles:
- role: nginx
vars: # Переменные роли (приоритет 5) переопределяют defaults и inventory vars для этого запуска
nginx_worker_processes: 8
Чтобы избежать путаницы, я всегда явно документирую ключевые переменные в README.md роли, указывая их назначение и место в иерархии, где их логичнее всего переопределять.