Использование переменных
Ansible использует переменные для управления различиями между системами. С помощью Ansible вы можете выполнять задачи и плейбуки на нескольких различных системах одной командой. Для представления вариаций между этими различными системами вы можете создавать переменные с помощью стандартного синтаксиса YAML, включая списки и словари. Вы можете определить эти переменные в своих плейбуках, в вашем инвентаре, в переиспользуемых файлах или ролях, или в командной строке. Вы также можете создавать переменные во время выполнения плейбука, регистрируя возвращаемое значение или значения задачи как новую переменную.
После создания переменных, либо путем определения их в файле, передачи их в командной строке, или регистрации возвращаемого значения или значений задачи как новой переменной, вы можете использовать эти переменные в аргументах модуля, в условных операторах «when», в шаблонах и в циклах. Репозиторий ansible-examples github содержит множество примеров использования переменных в Ansible.
После того, как вы освоите концепции и примеры на этой странице, ознакомьтесь с фактами Ansible, которые являются переменными, извлекаемыми с удаленных систем.
- Создание допустимых имён переменных
- Когда нужно указывать переменные в кавычках (особенность YAML)
- Регистрация переменных
- Обращение к вложенным переменным
- Преобразование переменных с помощью фильтров Jinja2
- Использование расширенного синтаксиса переменных
Создание допустимых имён переменных
Не все строки являются допустимыми именами переменных Ansible. Имя переменной может содержать только буквы, цифры и символы подчеркивания. Ключевые слова Python или ключевые слова плейбука не являются допустимыми именами переменных. Имя переменной не может начинаться с цифры.
Имена переменных могут начинаться с символа подчеркивания. Во многих языках программирования переменные, начинающиеся с подчеркивания, являются приватными. Это не относится к Ansible. Переменные, начинающиеся с подчеркивания, обрабатываются точно так же, как и любые другие переменные. Не полагайтесь на эту конвенцию для конфиденциальности или безопасности.
В этой таблице приведены примеры допустимых и недопустимых имён переменных:
Допустимые имена переменных | Недопустимые |
|---|---|
|
|
| ключевые слова плейбука, такие как |
|
|
|
|
Простые переменные
Простые переменные объединяют имя переменной с единственным значением. Вы можете использовать этот синтаксис (и синтаксис для списков и словарей, показанных ниже) в различных местах. Подробности о настройке переменных в инвентаре, в плейбуках, в переиспользуемых файлах, в ролях или в командной строке см. в разделе Где задавать переменные.
Определение простых переменных
Вы можете определить простую переменную, используя стандартный синтаксис 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] }}"
Значение этого выражения будет «северо-восток».
Переменные-словари
Словарь хранит данные в парах ключ-значение. Обычно словари используются для хранения связанных данных, таких как информация, содержащаяся в идентификаторе или пользовательском профиле.
Определение переменных как словарей (ключ:значение)
Вы можете определять более сложные переменные, используя 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
Регистрация переменных
Вы можете создать переменные из результата задания Ansible с помощью ключевого слова задания register. Вы можете использовать зарегистрированные переменные в последующих заданиях вашего плана. Например:
- 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.
Зарегистрированные переменные хранятся в памяти. Вы не можете кэшировать зарегистрированные переменные для использования в будущих планах. Зарегистрированные переменные действуют только на хосте для остальной части текущего выполнения плана.
Зарегистрированные переменные являются переменными уровня хоста. Когда вы регистрируете переменную в задании с циклом, зарегистрированная переменная содержит значение для каждого элемента в цикле. Структура данных, помещённая в переменную во время цикла, будет содержать атрибут results — список всех ответов модуля. Более подробный пример работы см. в разделе Циклы по использованию регистров с циклом.
Примечание
Если задание завершается ошибкой или пропускается, 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, вы можете задать переменную группы. На странице Как создать инвентаризацию содержатся подробности по настройке переменных хоста и переменных группы в инвентаризации.
Определение переменных в плане
Вы можете определить переменные непосредственно в плане:
- hosts: webservers
vars:
http_port: 80
Когда вы определяете переменные в плане, они видны любому, кто выполняет этот план. Это особенно полезно, если вы широко делитесь планами.
Определение переменных в включённых файлах и ролях
Вы можете определить переменные в переиспользуемых файлах переменных и/или в переиспользуемых ролях. Когда вы определяете переменные в переиспользуемых файлах переменных, конфиденциальные переменные отделяются от планов. Это разделение позволяет хранить ваши планы в системе управления версиями и даже делиться планами без риска раскрытия паролей или другой конфиденциальной и личной информации. Сведения о создании переиспользуемых файлов и ролей см. в разделе Переиспользование артефактов 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
ansible-playbook release.yml --extra-vars "@some_file.json"
Приоритет переменных: где разместить переменную?
Вы можете задать несколько переменных с одинаковым именем во многих разных местах. В этом случае Ansible загружает все возможные переменные, а затем выбирает переменную для применения на основе приоритета переменных. Другими словами, различные переменные будут переопределять друг друга в определённом порядке.
Команды и проекты, которые согласовывают правила для определения переменных (где определять определённые типы переменных), обычно избегают проблем с приоритетом переменных. Мы рекомендуем определить каждую переменную в одном месте: решите, где определить переменную, и сохраните простоту. Примеры см. в разделе Советы по тому, где задавать переменные.
Некоторые параметры поведения, которые можно задать в переменных, можно также задать в конфигурации Ansible, в качестве опций командной строки и с помощью ключевых слов плана. Например, вы можете определить пользователя, которого Ansible использует для подключения к удалённым устройствам, как переменную с ansible_user, в файле конфигурации с DEFAULT_REMOTE_USER, как опцию командной строки с -u, и с помощью ключевого слова плана remote_user. Если вы определяете один и тот же параметр в переменной и другим способом, переменная переопределяет другое значение. Этот подход позволяет настройкам, специфичным для хоста, переопределять более общие настройки. Примеры и более подробная информация о приоритете этих различных настроек см. в разделе Управление поведением Ansible: правила приоритета.
Понимание приоритета переменных
Ansible применяет приоритет переменных, и вы можете им воспользоваться. Вот порядок приоритета от наименьшего к наибольшему (переменные, указанные последними, переопределяют все другие переменные):
- Значения командной строки (например,
-u my_user, это не переменные) - Значения по умолчанию роли (определены в role/defaults/main.yml) 1
- Переменные из файла инвентаризации или группы скриптов 2
- Переменные группы all из файла инвентаризации 3
- Переменные группы all из плейбука 3
- Переменные группы * из файла инвентаризации 3
- Переменные группы * из плейбука 3
- Переменные хоста из файла инвентаризации или скрипта 2
- Переменные хоста * из файла инвентаризации 3
- Переменные хоста * из плейбука 3
- Факты хоста / кэшированные значения set_facts 4
- Переменные плейбука
- Переменные плейбука vars_prompt
- Переменные плейбука vars_files
- Переменные роли (определены в role/vars/main.yml)
- Переменные блока (только для задач в блоке)
- Переменные задачи (только для задачи)
- 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. Подробную информацию о приоритете переменных, заданных в инвентаризации, см. в Как объединяются переменные.
Примечания
-
1 -
Задачи в каждой роли видят значения по умолчанию своей роли. Задачи, определённые вне роли, видят значения по умолчанию последней роли.
-
2(1,2) -
Переменные, определённые в файле инвентаризации или предоставленные динамической инвентаризацией.
-
3(1,2,3,4,5,6) -
Включает переменные, добавленные плагинами vars, а также host_vars и group_vars, которые добавляются стандартным плагином vars, поставляемым с Ansible.
-
4 -
Если созданы с кэшируемым параметром set_facts, переменные имеют высокий приоритет в плейбуке, но имеют тот же приоритет, что и факты хоста, когда они взяты из кэша.
Примечание
В любом разделе переопределение переменной перебивает предыдущее значение. Если несколько групп имеют одинаковую переменную, загружается последняя. Если вы определены переменную дважды в разделе vars: плейбука, то второе значение побеждает.
Примечание
Предыдущее описание относится к настройкам по умолчанию hash_behaviour=replace, переключитесь на merge для частичного переопределения.
Определение областей переменных
Вы можете определить, где установить переменную, в зависимости от того, какой охват должен иметь это значение. Ansible имеет три основные области:
- Глобальная: устанавливается конфигурацией, переменными среды и командной строкой
- Плейбук: каждый плейбук и содержащие его структуры, записи vars (vars; vars_files; vars_prompt), значения по умолчанию роли и переменные роли.
- Хост: переменные, напрямую связанные с хостом, например, инвентаризация, include_vars, факты или результаты зарегистрированных задач
Внутри шаблона вы автоматически получаете доступ ко всем переменным, которые находятся в области действия для хоста, а также к любым зарегистрированным переменным, фактам и магическим переменным.
Рекомендации по определению переменных
Вы должны выбирать, где определять переменную, исходя из того, какой контроль вы хотите над значениями.
Устанавливайте переменные в инвентаризации, которые относятся к географии или поведению. Поскольку группы часто являются сущностями, которые сопоставляют роли с хостами, вы часто можете установить переменные в группе вместо их определения в роли. Помните: дочерние группы переопределяют родительские группы, а переменные хоста переопределяют переменные группы. Подробную информацию об установке переменных хоста и группы см. в Определение переменных в инвентаризации.
Устанавливайте общие значения по умолчанию в файле group_vars/all. Подробную информацию о том, как организовать переменные хоста и группы в инвентаризации, см. в Организация переменных хоста и группы. Переменные группы обычно размещаются рядом с файлом инвентаризации, но также могут возвращаться динамической инвентаризацией (см. Работа с динамической инвентаризацией) или определяться в Red Hat Ansible Tower из интерфейса или 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
Устанавливайте значения по умолчанию в ролях, чтобы избежать ошибок undefined-variable. Если вы делитесь своими ролями, другие пользователи могут полагаться на разумные значения по умолчанию, которые вы добавили в файл 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
Переменные, установленные в одной роли, доступны последующим ролям. Вы можете установить переменные в файле roles/common_settings/vars/main.yml и использовать их в других ролях и в других местах плейбука:
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, см. в Расширенный синтаксис.
См. также
- Введение в плейбуки
-
Введение в плейбуки
- Условные выражения
-
Условные операторы в плейбуках
- Использование фильтров для обработки данных
-
Фильтры Jinja2 и их использование
- Циклы
-
Циклы в плейбуках
- Роли
-
Организация плейбуков по ролям
- Советы и рекомендации
-
Советы и рекомендации по плейбукам
- Специальные переменные
-
Список специальных переменных
- Список рассылки пользователей
-
Есть вопросы? Загляните в google группу!
- irc.freenode.net
-
IRC чат канал #ansible
© 2012–2018 Michael DeHaan
© 2018–2021 Red Hat, Inc.
Licensed under the GNU General Public License version 3.
https://docs.ansible.com/ansible/2.11/user_guide/playbooks_variables.html