Использование переменных
Ansible использует переменные для управления различиями между системами. С помощью Ansible можно выполнять задачи и плейбуки на нескольких системах одной командой. Чтобы представить различия между этими системами, можно создавать переменные со стандартным синтаксисом YAML, включая списки и словари. Эти переменные можно определять в плейбуках, в инвентаре, в повторно используемых файлах или ролях либо в командной строке. Переменные также можно создавать во время выполнения плейбука, зарегистрировав возвращаемое значение задачи как новую переменную.
Создав переменную, можно использовать её в аргументах модулей, в условных операторах «when», в шаблонах и в циклах.
Разобравшись с понятиями и примерами на этой странице, прочитайте о фактах Ansible — переменных, которые извлекаются с удалённых систем.
- Создание допустимых имён переменных
- Когда заключать переменные в кавычки (подводный камень YAML)
- Регистрация переменных
- Обращение к вложенным переменным
- Преобразование переменных с помощью фильтров Jinja2
- Использование расширенного синтаксиса переменных
Создание допустимых имён переменных
Не все строки являются допустимыми именами переменных Ansible. Имя переменной может содержать только буквы, цифры и символы подчёркивания. Ключевые слова Python и ключевые слова плейбуков не могут быть именами переменных. Имя переменной не может начинаться с цифры.
Имена переменных могут начинаться с символа подчёркивания. Во многих языках программирования переменные, начинающиеся с символа подчёркивания, являются приватными. В Ansible это не так. Ansible обрабатывает переменные, начинающиеся с символа подчёркивания, так же, как любые другие переменные. Не полагайтесь на это соглашение в целях обеспечения конфиденциальности или безопасности.
В этой таблице приведены примеры допустимых и недопустимых имён переменных:
Допустимые имена переменных | Недопустимые |
|---|---|
|
|
| ключевые слова плейбуков, например |
|
|
|
|
Ansible внутренне определяет некоторые переменные. Определять эти переменные нельзя.
Избегайте имён переменных, совпадающих с глобальными функциями Jinja2, перечисленными в разделе Работа с плейбуками, например lookup, query, q, now и undef.
Простые переменные
Простые переменные связывают имя переменной с единственным значением. Этот синтаксис, а также показанный ниже синтаксис списков и словарей можно использовать в разных местах. Сведения о задании переменных в инвентаре, плейбуках, повторно используемых файлах и ролях или в командной строке см. в разделе Где задавать переменные.
Определение простых переменных
Простую переменную можно определить с помощью стандартного синтаксиса YAML. Например:
remote_install_path: /opt/my_app_config
Обращение к простым переменным
Определив переменную, используйте синтаксис Jinja2, чтобы обратиться к ней. В переменных Jinja2 используются двойные фигурные скобки. Например, выражение My amp goes to {{ max_amp_value }} демонстрирует простейшую форму подстановки переменной. Синтаксис Jinja2 можно использовать в плейбуках. В следующем примере показана переменная, задающая расположение файла, которое может различаться в разных системах:
ansible.builtin.template:
src: foo.cfg.j2
dest: '{{ remote_install_path }}/foo.cfg'
Ansible поддерживает циклы и условные операторы Jinja2 в шаблонах, но не в плейбуках. Создать цикл задач нельзя. Плейбуки Ansible — это чистый машиночитаемый YAML.
Когда заключать переменные в кавычки (подводный камень YAML)
Если значение начинается с {{ foo }}, необходимо заключить всё выражение в кавычки, чтобы получить корректный синтаксис YAML. Если не заключить в кавычки всё выражение, анализатор YAML не сможет интерпретировать синтаксис. Он не сможет определить, является ли это переменной или началом словаря YAML. Рекомендации по написанию YAML см. в документации по синтаксису YAML.
Если использовать переменную без кавычек, например так:
- hosts: app_servers
vars:
app_path: {{ base_path }}/22
Появится сообщение: ERROR! Syntax Error while loading YAML. Если добавить кавычки, Ansible будет работать корректно:
- hosts: app_servers
vars:
app_path: "{{ base_path }}/22"
Переменные-списки
Переменная-список связывает имя переменной с несколькими значениями. Несколько значений можно хранить в виде списка элементов или в квадратных скобках [], разделяя их запятыми.
Определение переменных в виде списков
Переменные с несколькими значениями можно определить с помощью списков YAML. Например:
region: - northeast - southeast - midwest
Обращение к переменным-спискам
Если переменная определена как список (также называемый массивом), можно использовать отдельные элементы этого списка. Первый элемент списка имеет индекс 0, второй — индекс 1 и так далее. Например:
region: "{{ region[0] }}"
Значением этого выражения будет «northeast».
Переменные-словари
Словарь хранит данные в виде пар «ключ-значение». Обычно словари используются для хранения связанных данных, например информации, содержащейся в удостоверении личности или профиле пользователя.
Определение переменных в виде словарей «ключ-значение»
Более сложные переменные можно определять с помощью словарей YAML. Словарь YAML сопоставляет ключи со значениями. Например:
foo: field1: one field2: two
Обращение к переменным-словарям «ключ-значение»
Если переменная определена как словарь «ключ-значение» (также называемый хешем), можно обращаться к отдельным элементам этого словаря, используя квадратные скобки или точечную нотацию:
foo['field1'] foo.field1
Оба примера обращаются к одному и тому же значению («one»). Нотация с квадратными скобками работает всегда. Точечная нотация может вызывать проблемы, поскольку некоторые ключи совпадают с атрибутами и методами словарей Python. Используйте нотацию с квадратными скобками, если ключи начинаются и заканчиваются двумя символами подчёркивания, которые зарезервированы в Python для специальных значений, или совпадают с одним из известных открытых атрибутов:
add, append, as_integer_ratio, bit_length, capitalize, center, clear, conjugate, copy, count, decode, denominator, difference, difference_update, discard, encode, endswith, expandtabs, extend, find, format, fromhex, fromkeys, get, has_key, hex, imag, index, insert, intersection, intersection_update, isalnum, isalpha, isdecimal, isdigit, isdisjoint, is_integer, islower, isnumeric, isspace, issubset, issuperset, istitle, isupper, items, iteritems, iterkeys, itervalues, join, keys, ljust, lower, lstrip, numerator, partition, pop, popitem, real, remove, replace, reverse, rfind, rindex, rjust, rpartition, rsplit, rstrip, setdefault, sort, split, splitlines, startswith, strip, swapcase, symmetric_difference, symmetric_difference_update, title, translate, union, update, upper, values, viewitems, viewkeys, viewvalues, zfill.
Объединение переменных
Для объединения переменных, содержащих списки или словари, можно воспользоваться следующими способами.
Объединение переменных-списков
Чтобы объединить списки в новую переменную merged_list, можно использовать модуль set_fact следующим образом:
vars:
list1:
- apple
- banana
- fig
list2:
- peach
- plum
- pear
tasks:
- name: Combine list1 and list2 into a merged_list var
ansible.builtin.set_fact:
merged_list: "{{ list1 + list2 }}"
Объединение переменных-словарей
Для объединения словарей используйте фильтр combine. Например:
vars:
dict1:
name: Leeroy Jenkins
age: 25
occupation: Astronaut
dict2:
location: Galway
country: Ireland
postcode: H71 1234
tasks:
- name: Combine dict1 and dict2 into a merged_dict var
ansible.builtin.set_fact:
merged_dict: "{{ dict1 | ansible.builtin.combine(dict2) }}"
Дополнительные сведения см. в разделе ansible.builtin.combine .
Использование lookup-плагина merge_variables
Чтобы объединить переменные, соответствующие заданным префиксам, суффиксам или регулярным выражениям, можно использовать lookup-плагин community.general.merge_variables. Например:
merged_variable: "{{ lookup('community.general.merge_variables', '__my_pattern', pattern_type='suffix') }}"
Дополнительные сведения и примеры использования см. в документации по lookup-плагину community.general.merge_variables.
Регистрация переменных
С помощью ключевого слова задачи register можно создать переменную из вывода задачи Ansible. Зарегистрированную переменную можно использовать в любой последующей задаче в плейбуке. Например:
- hosts: web_servers
tasks:
- name: Run a shell command and register its output as a variable
ansible.builtin.shell: /usr/bin/foo
register: foo_result
ignore_errors: true
- name: Run a shell command using output of the previous task
ansible.builtin.shell: /usr/bin/bar
when: foo_result.rc == 5
Дополнительные примеры использования зарегистрированных переменных в условиях последующих задач см. в разделе Условные операторы. Зарегистрированные переменные могут быть простыми переменными, переменными-списками, переменными-словарями или сложными вложенными структурами данных. Документация каждого модуля содержит раздел RETURN с описанием возвращаемых этим модулем значений. Чтобы увидеть значения для конкретной задачи, запустите плейбук с параметром -v.
Зарегистрированные переменные хранятся в памяти. Кэшировать их для использования при последующих запусках плейбука нельзя. Зарегистрированная переменная доступна только на узле до конца текущего запуска плейбука, в том числе в последующих plays в рамках того же запуска.
Зарегистрированные переменные относятся к уровню узла. Если зарегистрировать переменную в задаче с циклом, она будет содержать значение для каждого элемента цикла. Структура данных, помещаемая в переменную во время цикла, содержит атрибут results — список всех ответов модуля. Подробный пример работы этого механизма см. в разделе Циклы, посвящённом использованию register с циклом.
Если задача завершается с ошибкой или пропускается, Ansible всё равно регистрирует переменную со статусом ошибки или пропуска, кроме случаев, когда задача пропускается на основании тегов. Сведения о добавлении и использовании тегов см. в разделе Теги.
Обращение к вложенным переменным
Многие зарегистрированные переменные и факты представляют собой вложенные структуры данных YAML или JSON. Получить доступ к значениям в таких вложенных структурах с помощью простого синтаксиса {{ foo }} нельзя. Необходимо использовать нотацию с квадратными скобками или точечную нотацию. Например, чтобы обратиться к IP-адресу из фактов с помощью нотации с квадратными скобками:
'{{ ansible_facts["eth0"]["ipv4"]["address"] }}'
Чтобы обратиться к IP-адресу из фактов с помощью точечной нотации:
{{ ansible_facts.eth0.ipv4.address }}
Преобразование переменных с помощью фильтров Jinja2
Фильтры Jinja2 позволяют преобразовывать значение переменной внутри выражения шаблона. Например, фильтр capitalize переводит любое переданное ему значение в верхний регистр; фильтры to_yaml и to_json изменяют формат значений переменных. Jinja2 включает множество встроенных фильтров, а Ansible предоставляет ещё больше фильтров. Дополнительные примеры фильтров см. в разделе Использование фильтров для обработки данных.
Где задавать переменные
Переменные можно определять в разных местах: в инвентаре, плейбуках, повторно используемых файлах, ролях и командной строке. Ansible загружает все найденные переменные, а затем выбирает, какую из них применить, на основании правил приоритета переменных.
Определение переменных в инвентаре
Для каждого узла можно определить отдельные переменные или задать общие переменные для группы узлов в инвентаре. Например, если все компьютеры в группе [boston] используют ‘boston.ntp.example.com’ в качестве сервера NTP, можно задать переменную группы. На странице Как составить инвентарь приведены сведения о задании переменных узлов и переменных групп в инвентаре.
Определение переменных в play
Переменные можно определять непосредственно в play плейбука:
- hosts: webservers
vars:
http_port: 80
Переменные, определённые в play, видны только задачам, выполняемым в этом play.
Определение переменных во включаемых файлах и ролях
Переменные можно определять в повторно используемых файлах переменных или в повторно используемых ролях. Если определять переменные в повторно используемых файлах переменных, конфиденциальные переменные будут отделены от плейбуков. Это разделение позволяет хранить плейбуки в системе контроля версий и даже делиться ими без риска раскрыть пароли и другие конфиденциальные персональные данные. Сведения о создании повторно используемых файлов и ролей см. в разделе Повторное использование артефактов Ansible.
В этом примере показано, как включить переменные, определённые во внешнем файле:
---
- hosts: all
remote_user: root
vars:
favcolor: blue
vars_files:
- /vars/external_vars.yml
tasks:
- name: This is just a placeholder
ansible.builtin.command: /bin/echo foo
Содержимое каждого файла переменных представляет собой простой словарь YAML. Например:
--- # in the above example, this would be vars/external_vars.yml somevar: somevalue password: magic
Переменные для отдельных узлов и групп можно хранить в аналогичных файлах. Сведения об упорядочивании переменных см. в разделе Организация переменных узлов и групп.
Определение переменных во время выполнения
Переменные можно задавать при запуске плейбука, передавая их в командной строке с помощью аргумента --extra-vars (или -e). Также можно запросить ввод данных пользователем с помощью vars_prompt (см. раздел Интерактивный ввод: запросы). При передаче переменных в командной строке используйте одну строку в кавычках, содержащую одну или несколько переменных в одном из приведённых ниже форматов.
Формат «ключ-значение»
Значения, переданные с помощью синтаксиса key=value, интерпретируются как строки. Если требуется передать значения нестроковых типов, например логические значения, целые числа, числа с плавающей точкой и списки, используйте формат JSON.
ansible-playbook release.yml --extra-vars "version=1.23.45 other_variable=foo"
Формат строки JSON
ansible-playbook release.yml --extra-vars '{"version":"1.23.45","other_variable":"foo"}'
ansible-playbook arcade.yml --extra-vars '{"pacman":"mrs","ghosts":["inky","pinky","clyde","sue"]}'
При передаче переменных с помощью --extra-vars необходимо экранировать кавычки и другие специальные символы с учётом как используемой разметки (например, JSON), так и командной оболочки:
ansible-playbook arcade.yml --extra-vars "{\"name\":\"Conan O\'Brien\"}"
ansible-playbook arcade.yml --extra-vars '{"name":"Conan O'\\\''Brien"}'
ansible-playbook script.yml --extra-vars "{\"dialog\":\"He said \\\"I just can\'t get enough of those single and double-quotes"\!"\\\"\"}"
Переменные из файла JSON или YAML
Если специальных символов много, используйте файл JSON или YAML с определениями переменных. Перед именами файлов JSON и YAML добавьте @.
ansible-playbook release.yml --extra-vars "@some_file.json" ansible-playbook release.yml --extra-vars "@some_file.yaml"
Приоритет переменных: где следует размещать переменную?
Вы можете задать несколько переменных с одним и тем же именем в самых разных местах. В этом случае Ansible загружает все найденные переменные, а затем выбирает, какую из них применить, на основе приоритета переменных. Иными словами, разные переменные переопределяют друг друга в определённом порядке.
Команды и проекты, согласовавшие рекомендации по определению переменных (где задавать переменные определённых типов), обычно избегают проблем с приоритетом переменных. Определяйте каждую переменную в одном месте. Решите, где задавать переменную, и придерживайтесь простого подхода. Примеры приведены в разделе Советы по размещению переменных.
Некоторые параметры поведения, которые можно задавать в переменных, можно также задавать в конфигурации Ansible, в виде параметров командной строки и с помощью ключевых слов плейбука. Например, пользователя, которого Ansible использует для подключения к удалённым устройствам, можно задать как переменную с помощью ansible_user, в файле конфигурации с помощью DEFAULT_REMOTE_USER, как параметр командной строки с помощью -u и с помощью ключевого слова плейбука remote_user. Если задать один и тот же параметр в переменной и другим способом, переменная переопределит другое значение. Такой подход позволяет настройкам для конкретного узла переопределять более общие настройки. Примеры и дополнительные сведения о приоритете различных настроек см. в разделе Управление поведением Ansible: правила приоритета.
Разбираемся в приоритете переменных
Ansible применяет приоритет переменных, и иногда это может быть полезно. Ниже приведён порядок от наименьшего приоритета к наибольшему (последние перечисленные переменные переопределяют все остальные):
- Значения командной строки (например,
-u my_user; это не переменные) - Значения по умолчанию для ролей (как определено в разделе Структура каталогов роли) [1]
- Групповые переменные из файла инвентаря или скрипта [2]
- Inventory group_vars/all [3]
- Playbook group_vars/all [3]
- Inventory group_vars/* [3]
- Playbook group_vars/* [3]
- Переменные узлов из файла инвентаря или скрипта [2]
- Inventory host_vars/* [3]
- Playbook host_vars/* [3]
- Факты узлов и кэшированные set_facts [4]
- Переменные плейбука
- Переменные запроса play vars_prompt
- Файлы переменных play vars_files
- Переменные ролей (как определено в разделе Структура каталогов роли)
- Переменные блока (только для задач в блоке)
- Переменные задачи (только для этой задачи)
- include_vars
- Зарегистрированные переменные и set_facts
- Параметры роли (и include_role)
- Параметры include
- Дополнительные переменные (например,
-e "user=my_user") (всегда имеют наивысший приоритет)
В целом Ansible отдаёт приоритет переменным, которые были определены позднее, активнее и в более явной области видимости. Переменные в каталоге defaults внутри роли легко переопределить. Всё, что находится в каталоге vars роли, переопределяет предыдущие значения этой переменной в пространстве имён. Переменные узла или инвентаря переопределяют значения по умолчанию для ролей, но явные включения, например каталог vars или задача include_vars, переопределяют переменные инвентаря.
Ansible объединяет переменные, заданные в разных частях инвентаря, так что более конкретные настройки переопределяют общие. Например, ansible_ssh_user, заданная как group_var, переопределяется переменной ansible_user, заданной как host_var. Сведения о приоритете переменных, заданных в инвентаре, см. в разделе Как объединяются переменные.
Сноски
Примечание
В любом разделе повторное определение переменной переопределяет её предыдущее значение. Если одна и та же переменная есть в нескольких группах, побеждает последняя загруженная. Если определить переменную дважды в разделе vars: плейбука, будет использовано второе значение.
В предыдущем тексте описана конфигурация hash_behavior=replace по умолчанию. Переключитесь на merge, чтобы переопределять настройки только частично.
Области видимости переменных
Вы можете выбрать место для задания переменной в зависимости от требуемой области видимости её значения. В Ansible есть три основные области видимости:
- Глобальная: задаётся конфигурацией, переменными среды и командной строкой
- Плейбук: каждый плей и содержащиеся в нём структуры, записи vars (vars; vars_files; vars_prompt), значения по умолчанию для ролей и переменные ролей.
- Узел: переменные, непосредственно связанные с узлом, например переменные инвентаря, include_vars, факты или результаты зарегистрированных задач
В шаблоне автоматически доступны все переменные, находящиеся в области видимости узла, а также зарегистрированные переменные, факты и магические переменные.
Советы по размещению переменных
Выбирайте место для определения переменной с учётом того, насколько вам может понадобиться управлять её значениями.
Задавайте в инвентаре переменные, связанные с географией или поведением. Поскольку именно группы часто используются для сопоставления ролей узлам, переменные можно задавать для группы, а не определять их в роли. Помните, что дочерние группы переопределяют родительские, а переменные узлов переопределяют переменные групп. Подробнее о задании переменных узлов и групп см. в разделе Определение переменных в инвентаре.
Задавайте общие значения по умолчанию в файле group_vars/all. Подробнее об организации переменных узлов и групп в инвентаре см. в разделе Организация переменных узлов и групп. Как правило, групповые переменные размещают рядом с файлом инвентаря, но их также может возвращать динамический инвентарь (см. раздел Работа с динамическим инвентарём) или их можно определить в AWX либо в Red Hat Ansible Automation Platform через интерфейс или API:
--- # file: /etc/ansible/group_vars/all # this is the site wide default ntp_server: default-time.example.com
Задавайте переменные, зависящие от местоположения, в файлах group_vars/my_location. Все группы являются дочерними по отношению к группе all, поэтому переменные, заданные здесь, переопределяют переменные, заданные в group_vars/all:
--- # file: /etc/ansible/group_vars/boston ntp_server: boston-time.example.com
Если для одного узла используется другой NTP-сервер, его можно задать в файле host_vars, и тогда он переопределит групповую переменную:
--- # file: /etc/ansible/host_vars/xyz.boston.example.com ntp_server: override.example.com
Задавайте значения по умолчанию в ролях, чтобы избежать ошибок, связанных с неопределёнными переменными. Если вы предоставляете свои роли другим пользователям, они смогут использовать разумные значения по умолчанию, заданные вами в файле roles/x/defaults/main.yml, или легко переопределить эти значения в инвентаре либо командной строке. Дополнительные сведения см. в разделе Роли. Например:
--- # file: roles/x/defaults/main.yml # if no other value is supplied in inventory or as a parameter, this value will be used http_port: 80
Задавайте переменные в ролях, чтобы гарантировать использование значения в этой роли и не допустить его переопределения переменными инвентаря. Если вы не делитесь ролью с другими, таким способом можно определять специфичные для приложения параметры, например порты, в roles/x/vars/main.yml. Если вы делитесь ролями с другими, переменные, заданные здесь, будет сложнее переопределить, хотя их всё же можно переопределить, передав параметр роли или задав переменную с помощью -e:
--- # file: roles/x/vars/main.yml # this will absolutely be used in this role http_port: 80
Передавайте переменные в качестве параметров при вызове ролей — так обеспечиваются максимальная ясность, гибкость и наглядность. Такой подход переопределяет любые значения по умолчанию, существующие для роли. Например:
roles:
- role: apache
vars:
http_port: 8080
При чтении этого плейбука ясно, что вы решили задать переменную или переопределить значение по умолчанию. Можно также передать несколько значений, что позволит запускать одну и ту же роль несколько раз. Подробнее см. в разделе Многократный запуск роли в одном плейбуке. Например:
roles:
- role: app_user
vars:
myname: Ian
- role: app_user
vars:
myname: Terry
- role: app_user
vars:
myname: Graham
- role: app_user
vars:
myname: John
Переменные, заданные в одной роли, доступны последующим ролям. Вы можете задать переменные в каталоге vars роли (как определено в разделе Структура каталогов роли) и использовать их в других ролях и в других местах плейбука:
roles:
- role: common_settings
- role: something
vars:
foo: 12
- role: something_else
Предусмотрены некоторые механизмы защиты, позволяющие не задавать пространство имён для переменных. В этом примере переменные, определённые в ‘common_settings’, доступны задачам ‘something’ и ‘something_else’, но для задач в ‘something’ переменная foo имеет значение 12, даже если в ‘common_settings’ для foo задано значение 20.
Вместо того чтобы беспокоиться о приоритете переменных, при выборе места для переменной рекомендуем подумать о том, насколько легко или часто вы захотите её переопределять. Если вы не уверены, какие другие переменные определены, и вам нужно конкретное значение, используйте --extra-vars (-e), чтобы переопределить все остальные переменные.
Использование расширенного синтаксиса переменных
Сведения о расширенном синтаксисе YAML для объявления переменных и более гибкого управления данными в файлах YAML, используемых Ansible, см. в разделе Расширенный синтаксис плейбуков.
См. также
- Плейбуки Ansible
-
Введение в плейбуки
- Условные операторы
-
Условные операторы в плейбуках
- Использование фильтров для обработки данных
-
Фильтры Jinja2 и их применение
- Циклы
-
Циклы в плейбуках
- Роли
-
Организация плейбуков с помощью ролей
- Общие советы
-
Советы и рекомендации по работе с плейбуками
- Специальные переменные
-
Список специальных переменных
- Общение
-
Есть вопросы? Нужна помощь? Хотите поделиться идеями? Посетите руководство по общению сообщества Ansible
© 2012–2018 Michael DeHaan
© 2018–2025 Red Hat, Inc.
Licensed under the GNU General Public License version 3.
https://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_variables.html