Spec-Zone.ru › Ansible 2.4

Переменные

  • Что делает имя переменной корректным
  • Переменные, определённые в инвентаре
  • Переменные, определённые в плейбуке
  • Переменные, определённые из включённых файлов и ролей
  • Использование переменных: общие сведения о Jinja2
  • Фильтры Jinja2
  • Подождите, есть нюанс с YAML
  • Информация, полученная от систем: факты
  • Отключение фактов
  • Локальные факты (Facts.d)
  • Версия Ansible
  • Кэширование фактов
  • Зарегистрированные переменные
  • Доступ к сложным данным переменных
  • Магические переменные и как получить информацию об других хостах
  • Разделение файлов переменных
  • Передача переменных через командную строку
  • Приоритет переменных: куда поместить переменную?
  • Области видимости переменных
  • Примеры переменных
  • Расширенный синтаксис

Хотя автоматизация упрощает повторение действий, все ваши системы, вероятно, не идентичны.

В некоторых системах вы можете захотеть установить поведение или конфигурацию, немного отличающиеся от других.

Также некоторые наблюдаемые поведение или состояние удалённых систем могут потребоваться для влияния на конфигурацию этих систем. (Например, вам может потребоваться узнать IP-адрес системы и использовать его в качестве значения конфигурации на другой системе).

У вас могут быть шаблоны конфигурационных файлов, которые в основном одинаковы, но немного отличаются в зависимости от этих переменных.

Переменные в Ansible используются для решения проблем различий между системами.

Чтобы понять переменные, вам также стоит изучить Условные операторы и Циклы. Такие полезные вещи, как модуль group_by и условный оператор when, также могут использоваться с переменными и помогают управлять различиями между системами.

Сильно рекомендуется обратиться к репозиторию ansible-examples в GitHub, чтобы увидеть множество примеров использования переменных.

Для получения рекомендаций по лучшим практикам обратитесь к разделу Переменные и хранилища в главе Лучшие практики.

Что делает имя переменной корректным

Прежде чем начать использовать переменные, важно знать, что являются корректными именами переменных.

Имена переменных должны состоять из букв, цифр и символов подчёркивания. Переменные всегда должны начинаться с буквы.

foo_port — отличная переменная. foo5 — тоже отлично.

foo-port, foo port, foo.port и 12 — некорректные имена переменных.

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.

Переменные, определённые в инвентаре

Мы уже рассмотрели много информации о переменных в другом разделе, так что это не должно быть сильно новым, но небольшой краткий обзор.

Часто вы захотите задать переменные, основанные на группах, в которых находится машина. Например, возможно, машины в Бостоне хотят использовать «boston.ntp.example.com» в качестве NTP-сервера.

См. документ Инвентаризация для различных способов определения переменных в инвентаре.

Переменные, определённые в плейбуке

В плейбуке можно определять переменные непосредственно, как показано ниже:

- hosts: webservers
  vars:
    http_port: 80

Это может быть удобно, так как они находятся прямо там, когда вы читаете плейбук.

Переменные, определённые из включённых файлов и ролей

Оказывается, мы уже обсуждали переменные и в другом месте.

Как описано в Ролях, переменные также могут включаться в плейбук через включаемые файлы, которые могут быть или не быть частью «роли Ansible». Использование ролей предпочтительнее, так как оно обеспечивает хорошую систему организации.

Использование переменных: общие сведения о Jinja2

Приятно знать, как определять переменные, но как их использовать?

Ansible позволяет ссылаться на переменные в плейбуках, используя систему шаблонизации Jinja2. Хотя вы можете выполнять множество сложных действий в Jinja, на начальном этапе вам нужно освоить только основы.

Например, в простом шаблоне вы можете сделать следующее:

My amp goes to {{ max_amp_value }}

Это предоставит самую базовую форму подстановки переменных.

Это также допустимо непосредственно в плейбуках, и вы иногда захотите делать такие вещи, как:

template: src=foo.cfg.j2 dest={{ remote_install_path }}/foo.cfg

В приведённом примере мы использовали переменную для определения места размещения файла.

Внутри шаблона вы автоматически имеете доступ ко всем переменным, которые находятся в области видимости для хоста. На самом деле это больше, чем просто это — вы также можете считывать переменные об других хостах. Мы покажем, как это сделать чуть позже.

Примечание

Ansible позволяет использовать циклы и условные операторы Jinja2 в шаблонах, но в плейбуках они не используются. Ansible плейбуки являются чистым YAML, который можно обрабатывать на уровне машин. Это довольно важная функция, поскольку она позволяет генерировать части файлов или использовать другие инструменты экосистемы для чтения файлов Ansible. Не всем это нужно, но это может открыть новые возможности.

См. также

Шаблонизация (Jinja2)
Дополнительная информация о шаблонизации Jinja2

Фильтры Jinja2

Примечание

Эти функции используются редко. Используйте их, если они подходят для вашей задачи, но это необязательные знания.

Фильтры Jinja2 — это способ преобразования выражений шаблона из одного типа данных в другой. В Jinja2 поставляется множество таких фильтров. См. встроенные фильтры в официальной документации шаблонов Jinja2.

В дополнение к этим фильтрам Ansible предоставляет ещё много других. См. документ Фильтры для списка доступных фильтров и руководства по использованию.

Подождите, есть нюанс с YAML

Синтаксис YAML требует, что если вы начинаете значение с {{ foo }}, вы должны заключить всю строку в кавычки, поскольку он хочет убедиться, что вы не пытаетесь начать словарь YAML. Об этом рассказывается на странице Синтаксис YAML.

Это не сработает:

- hosts: app_servers
  vars:
      app_path: {{ base_path }}/22

Сделайте так, и всё будет хорошо:

- hosts: app_servers
  vars:
       app_path: "{{ base_path }}/22"

Информация, полученная от систем: Факты

Существуют и другие источники переменных, но эти переменные обнаруживаются, а не задаются пользователем.

Факты — это информация, полученная в результате общения с удалёнными системами.

Например, это может быть IP-адрес удалённого хоста или операционная система.

Чтобы увидеть доступную информацию, попробуйте следующее:

ansible hostname -m setup

Это вернёт огромное количество данных переменных, которые могут выглядеть так, как показано на примере Ansible 1.4 на системе Ubuntu 12.04

В примере выше модель первого жёсткого диска может быть использована в шаблоне или книге задач как:

{{ ansible_devices.sda.model }}

Аналогично, имя хоста, как его сообщает система:

{{ ansible_nodename }}

и неопределённое имя хоста показывает строку до первой точки (.).

{{ ansible_hostname }}

Факты часто используются в условных операторах (см. Условные операторы) и в шаблонах.

Факты также могут использоваться для создания динамических групп хостов, соответствующих определённым критериям. Смотрите документацию О модулях по group_by для получения подробной информации, а также в обобщённых условных операторах, как описано в главе Условные операторы.

Отключение фактов

Если вам не нужны данные фактов о хостах и вы знаете всё о ваших системах централизованно, вы можете отключить сбор фактов. Это имеет преимущества при масштабировании Ansible в режиме push с очень большим количеством систем, в основном, или если вы используете Ansible на экспериментальных платформах. В любой книге задач сделайте это:

- hosts: whatever
  gather_facts: no

Локальные факты (Facts.d)

Новая функция в версии 1.3.

Как обсуждалось в главе о книгах задач, факты Ansible — это способ получения данных об удалённых системах для использования в переменных книги задач.

Обычно они автоматически обнаруживаются модулем setup в Ansible. Пользователи также могут создавать собственные модули фактов, как описано в руководстве по API. Однако что, если вы хотите предоставить простые способы предоставления данных системы или пользователя для использования в переменных Ansible без создания модуля фактов?

Например, что если вы хотите, чтобы пользователи могли контролировать некоторые аспекты управления своими системами? «Facts.d» — один из таких механизмов.

Примечание

Возможно, «локальные факты» — это немного неудачное название, оно означает «локально заданные значения пользователя», в отличие от «централизованно заданных значений пользователя», или то, что факты представляют — «локально динамически определённые значения».

Если удалённая управляемая система имеет каталог /etc/ansible/facts.d, любые файлы в этом каталоге, заканчивающиеся на .fact, могут быть файлами JSON, INI или исполняемыми файлами, возвращающими JSON, и они могут предоставлять локальные факты в Ansible. Альтернативный каталог можно указать с помощью директивы книги задач fact_path.

Например, предположим /etc/ansible/facts.d/preferences.fact.

[general]
asdf=1
bar=2

Это создаст переменную-факт в виде хеша general с asdf и bar в качестве элементов. Для проверки выполните следующее:

ansible <hostname> -m setup -a "filter=ansible_local"

И вы увидите добавленный факт:

"ansible_local": {
        "preferences": {
            "general": {
                "asdf" : "1",
                "bar"  : "2"
            }
        }
 }

И к этим данным можно получить доступ в template/playbook следующим образом:

{{ ansible_local.preferences.general.asdf }}

Локальное пространство имён предотвращает переопределение фактов системы или переменных, определённых в другом месте книги задач, предоставленными пользователем фактами.

Примечание

Ключевая часть в парах ключ=значение будет преобразована в нижний регистр внутри переменной ansible_local. Используя приведенный выше пример, если ini-файл содержал XYZ=3 в разделе [general], то вы должны получить доступ к нему как: {{ ansible_local.preferences.general.xyz }}, а не как {{ ansible_local.preferences.general.XYZ }}. Это потому, что Ansible использует ConfigParser Python, который проходит через все имена опций с помощью метода optionxform, а метод по умолчанию преобразует имена опций в нижний регистр.

Если у вас есть книга задач, которая копирует пользовательский факт и затем его выполняет, явное повторное выполнение модуля setup может позволить использовать этот факт во время данной задачи. В противном случае он будет доступен в следующей задаче, которая собирает информацию о фактах. Вот пример того, как это может выглядеть:

- hosts: webservers
  tasks:
    - name: create directory for ansible custom facts
      file: state=directory recurse=yes path=/etc/ansible/facts.d
    - name: install custom impi fact
      copy: src=ipmi.fact dest=/etc/ansible/facts.d
    - name: re-read facts after adding custom fact
      setup: filter=ansible_local

В этой схеме, однако, вы также можете написать модуль факта, и вы можете рассмотреть этот вариант.

Версия Ansible

Новая функция в версии 1.8.

Для адаптации поведения книги задач к определённой версии Ansible доступна переменная ansible_version со следующей структурой:

"ansible_version": {
    "full": "2.0.0.2",
    "major": 2,
    "minor": 0,
    "revision": 0,
    "string": "2.0.0.2"
}

Кэширование фактов

Новая функция в версии 1.8.

Как показано в других частях документации, один сервер может ссылаться на переменные другого, например:

{{ hostvars['asdf.example.com']['ansible_os_family'] }}

При отключённом «кэшировании фактов» для этого Ansible должен был взаимодействовать с «asdf.example.com» в текущей книге задач или другой книге задач выше в книге задач. Это стандартная конфигурация Ansible.

Чтобы этого избежать, Ansible 1.8 позволяет сохранять факты между запусками книги задач, но эта функция должна быть включена вручную. Зачем это может быть полезно?

Представьте, например, очень большую инфраструктуру с тысячами хостов. Кэширование фактов можно настроить на еженощное выполнение, но конфигурация небольшой группы серверов может выполняться в режиме ad-hoc или периодически в течение дня. При включённом кэшировании фактов не будет необходимости взаимодействовать со всеми серверами для ссылки на переменные и информацию о них.

При включённом кэшировании фактов машина в одной группе может ссылаться на переменные машин в другой группе, несмотря на то, что с ними не было взаимодействий во время текущего выполнения /usr/bin/ansible-playbook.

Чтобы использовать кэшированные факты, необходимо изменить значение параметра gathering на smart или explicit или установить gather_facts на значение False в большинстве книг задач.

В настоящее время Ansible поставляется с двумя плагинами постоянного кэша: redis и jsonfile.

Чтобы настроить кэширование фактов с помощью redis, включите его в ansible.cfg следующим образом:

[defaults]
gathering = smart
fact_caching = redis
fact_caching_timeout = 86400
# seconds

Чтобы запустить redis, выполните эквивалентные команды ОС:

yum install redis
service redis start
pip install redis

Обратите внимание, что библиотека Python redis должна быть установлена из pip, версия, упакованная в EPEL, слишком устарела для использования Ansible.

В текущих реализациях эта функция находится на стадии бета-тестирования, и плагин Redis не поддерживает конфигурацию порта или пароля. Это ожидается в ближайшее время.

Чтобы настроить кэширование фактов с помощью jsonfile, включите его в ansible.cfg следующим образом:

[defaults]
gathering = smart
fact_caching = jsonfile
fact_caching_connection = /path/to/cachedir
fact_caching_timeout = 86400
# seconds

fact_caching_connection — это локальный путь к файловой системе к каталогу, в который можно записывать (Ansible попытается создать каталог, если его нет).

fact_caching_timeout — это количество секунд для кэширования записанных фактов.

Зарегистрированные переменные

Ещё одно важное использование переменных — это выполнение команды и использование результата этой команды для сохранения результата в переменную. Результаты будут разными для разных модулей. При выполнении книг задач использование -v покажет возможные значения для результатов.

Значение выполняемой задачи в Ansible можно сохранить в переменной и использовать позже. Смотрите примеры этого в главе Условные операторы.

Хотя это упоминается и в другом месте документа, вот быстрый пример синтаксиса:

- hosts: web_servers

  tasks:

     - shell: /usr/bin/foo
       register: foo_result
       ignore_errors: True

     - shell: /usr/bin/bar
       when: foo_result.rc == 5

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

При использовании register с циклом структура данных, помещённая в переменную во время цикла, будет содержать атрибут results, который является списком всех ответов от модуля. Для более подробного примера работы с этим смотрите раздел Циклы по использованию register с циклом.

Примечание

Если задача завершилась неудачно или была пропущена, переменная всё равно регистрируется со статусом «неудачно» или «пропущено». Единственный способ избежать регистрации переменной — использовать теги.

Доступ к сложным данным переменных

Мы уже немного поговорили о фактах выше в документации.

Некоторые предоставляемые факты, например, сетевая информация, предоставляются как вложенные структуры данных. Для доступа к ним простого {{ foo }} недостаточно, но это всё ещё легко сделать. Вот как мы получаем IP-адрес:

{{ ansible_eth0["ipv4"]["address"] }}

Или альтернативно:

{{ ansible_eth0.ipv4.address }}

Аналогично, вот как мы получаем первый элемент массива:

{{ foo[0] }}

Магические переменные и как получить информацию о других хостах

Даже если вы их не определяли, Ansible автоматически предоставляет несколько переменных. Самые важные из них hostvars, group_names, и groups. Пользователи не должны использовать эти имена, так как они зарезервированы. environment также зарезервирован.

hostvars позволяет запрашивать переменные другого хоста, включая факты, собранные об этом хосте. Если на этом этапе вы ещё не взаимодействовали с этим хостом в какой-либо книге задач или наборе книг задач, вы всё равно можете получить переменные, но не сможете получить факты.

Если ваш сервер базы данных хочет использовать значение «факта» с другого узла или переменную инвентаризации, заданную для другого узла, это легко сделать в шаблоне или даже в строке действия:

{{ hostvars['test.example.com']['ansible_distribution'] }}

Кроме того, group_names — это список (массив) всех групп, к которым принадлежит текущий хост. Это можно использовать в шаблонах с помощью синтаксиса Jinja2 для создания файлов шаблонов, которые различаются в зависимости от членства хоста в группе (или роли).

{% if 'webserver' in group_names %}
   # some part of a configuration file that only applies to webservers
{% endif %}

groups — это список всех групп (и хостов) в инвентаре. Это можно использовать для перечисления всех хостов в группе. Например:

{% for host in groups['app_servers'] %}
   # something that applies to all app servers.
{% endfor %}

Часто используется выражение для просмотра группы, чтобы найти все IP-адреса в этой группе

{% for host in groups['app_servers'] %}
   {{ hostvars[host]['ansible_eth0']['ipv4']['address'] }}
{% endfor %}

Пример этого может включать указание переднего прокси-сервера на все приложения серверы, настройку правильных правил брандмауэра между серверами и т. д. Однако необходимо убедиться, что данные о этих хостах заполнены, например, путем выполнения игры против них, если данные не были недавно кэшированы (кэширование фактов было добавлено в Ansible 1.8).

Кроме того, inventory_hostname — это имя хоста, как оно настроено в файле инвентаризации хоста Ansible. Это может быть полезно, когда вы не хотите полагаться на обнаруженное имя хоста ansible_hostname или по другим загадочным причинам. Если у вас длинное полное доменное имя, inventory_hostname_short также содержит часть до первого периода, без остальной части домена.

play_hosts устарел в версии 2.2, он был таким же, как и новая переменная ansible_play_batch.

Новая версия 2.2.

ansible_play_hosts — это полный список всех активных хостов в текущей игре.

Новая версия 2.2.

ansible_play_batch доступен как список имен хостов, которые находятся в области действия текущей «партии» игры. Размер партии определяется serial, если он не задан, он эквивалентен всей игре (делая его таким же, как ansible_play_hosts).

Новая версия 2.3.

ansible_playbook_python — путь к исполняемому файлу python, используемому для вызова командной строки Ansible.

Эти переменные могут быть полезны для заполнения шаблонов несколькими именами хостов или для вставки списка в правила балансировщика нагрузки.

Не беспокойтесь об этом, если не считаете, что вам это нужно. Вы узнаете, когда это потребуется.

Также доступны inventory_dir — путь к каталогу, содержащему файл инвентаризации хоста Ansible, inventory_file — путь и имя файла, указывающие на файл инвентаризации хоста Ansible.

playbook_dir содержит базовый каталог книги сценариев.

Затем у нас есть role_path, которая вернет текущий путь к роли (с версии 1.8). Эта функция будет работать только внутри роли.

И наконец, ansible_check_mode (добавлен в версии 2.1), магическая булева переменная, которая будет установлена в True, если вы запустите Ansible с --check.

Разделение файлов переменных

Отличная идея — хранить свои книги сценариев под управлением системы контроля версий, но вы можете опубликовать исходный код книги сценариев, сохранив при этом конфиденциальность определенных важных переменных. Аналогично, иногда вы просто хотите хранить определённую информацию в разных файлах, отдельно от основной книги сценариев.

Вы можете сделать это, используя внешний файл (или файлы) переменных, так:

---

- hosts: all
  remote_user: root
  vars:
    favcolor: blue
  vars_files:
    - /vars/external_vars.yml

  tasks:

  - name: this is just a placeholder
    command: /bin/echo foo

Это снижает риск совместного использования конфиденциальных данных с другими при совместном использовании исходного кода вашей книги сценариев с ними.

Содержимое каждого файла переменных — это простой словарь YAML, например:

---
# in the above example, this would be vars/external_vars.yml
somevar: somevalue
password: magic

Примечание

Также возможно сохранение переменных на хост и в группы в очень похожих файлах, это рассмотрено в Разделение данных хостов и групп.

Передача переменных через командную строку

В дополнение к vars_prompt и vars_files, можно передавать переменные через командную строку Ansible. Это особенно полезно при написании универсальной книги сценариев выпуска, где вы хотите передать версию приложения, подлежащего развертыванию:

ansible-playbook release.yml --extra-vars "version=1.23.45 other_variable=foo"

Это полезно, среди прочего, для настройки группы хостов или пользователя для книги сценариев.

Пример:

---

- hosts: '{{ hosts }}'
  remote_user: '{{ user }}'

  tasks:
     - ...

ansible-playbook release.yml --extra-vars "hosts=vipers user=starbuck"

Начиная с Ansible 1.2, вы также можете передать дополнительные переменные как строку JSON, например:

--extra-vars '{"pacman":"mrs","ghosts":["inky","pinky","clyde","sue"]}'

Формат key=value очевидно проще, но он есть, если вам нужно!

Примечание

Значения, переданные с помощью синтаксиса key=value, интерпретируются как строки. Используйте формат JSON, если вам нужно передать что-либо, что не должно быть строкой (булевы значения, целые числа, числа с плавающей точкой, списки и т. д.).

Начиная с Ansible 1.3, дополнительные переменные могут загружаться из файла JSON с помощью синтаксиса @.

--extra-vars "@some_file.json"

Также начиная с Ansible 1.3, дополнительные переменные могут форматироваться как YAML, как в командной строке, так и в файле, как выше.

Приоритет переменных: куда поместить переменную?

Многие задаются вопросом о том, как переменные перезаписывают друг друга. В конечном счете, философия Ansible заключается в том, что лучше знать, куда поместить переменную, а затем вам нужно будет об этом меньше думать.

Избегайте определения переменной «x» в 47 местах и затем задавать вопрос «какая x используется». Почему? Потому что это не философия Ansible по поводу выполнения задач.

Существует только одно здание Эмпайр-стейт. Одна Мона Лиза и т. д. Определите, где определить переменную, и не усложняйте.

Однако давайте рассмотрим приоритет! Он существует. Это реальная вещь, и вам может понадобиться знать об этом.

Если несколько переменных с одинаковым именем определены в разных местах, они перезаписываются в определенном порядке.

Примечание

В Ansible 2.0 устарел «ssh» в ansible_ssh_user, ansible_ssh_host, и ansible_ssh_port и стали ansible_user, ansible_host, и ansible_port. Если вы используете версию Ansible до 2.0, вы должны продолжить использование старых стилей переменных (ansible_ssh_*). Эти сокращенные переменные игнорируются в более старых версиях Ansible без предупреждения.

В 1.x приоритет выглядит следующим образом (приоритет имеет последняя перечисленная переменная):

  • «Значения по умолчанию роли», которые уступают по приоритету всему и легко перезаписываются
  • переменные, определенные в инвентаризации
  • факты, обнаруженные о системе
  • «почти всё остальное» (переключатели командной строки, переменные в сценарии, включённые переменные, переменные роли и т. д.)
  • переменные соединения (ansible_user, и т. д.)
  • дополнительные переменные (-e в командной строке) всегда имеют приоритет

Примечание

В версиях до 1.5.4 факты, обнаруженные о системе, находились в категории «почти всё остальное» выше.

В 2.x мы сделали порядок приоритета более специфичным (приоритет имеет последняя перечисленная переменная):

  • значения по умолчанию роли [1]
  • переменные из файла или скрипта инвентаризации [2]
  • переменные для группы из файла инвентаризации/скрипта/all [3]
  • переменные для группы из книги сценариев/all [3]
  • переменные для группы из файла инвентаризации/* [3]
  • переменные для группы из книги сценариев/* [3]
  • переменные для хоста из файла инвентаризации/скрипта [2]
  • переменные для хоста из файла инвентаризации/*
  • переменные для хоста из книги сценариев/*
  • факты хоста / кэшированные set_facts [4]
  • переменные для хоста из файла инвентаризации/* [3]
  • переменные для хоста из книги сценариев/* [3]
  • факты хоста
  • переменные сценария
  • переменные сценария prompt
  • переменные сценария файлов
  • переменные роли (определенные в role/vars/main.yml)
  • переменные блока (только для задач в блоке)
  • переменные задачи (только для задачи)
  • параметры роли (и include_role)
  • параметры include
  • include_vars
  • set_facts / зарегистрированные переменные
  • дополнительные переменные (всегда имеют приоритет)

В основном, все, что попадает в «значения по умолчанию роли» (папка defaults внутри роли) — самое изменчивое и легко перезаписываемое. Все в каталоге vars роли перезаписывает предыдущие версии этой переменной в пространстве имен. Здесь важно следовать тому, что чем яснее вы указываете область, тем больше приоритет она имеет, причём переменные командной строки -e имеют наивысший приоритет. Переменные хоста и/или инвентаризации могут иметь приоритет над значениями по умолчанию роли, но не над явными включениями, такими как каталог vars или задача include_vars.

Примечания

[1] Задачи в каждой роли будут видеть собственные значения по умолчанию роли. Задачи, определённые вне роли, будут видеть значения по умолчанию последней роли.
[2] (1, 2) Переменные, определенные в файле инвентаризации или предоставленные динамическим инвентарем.
[3] (1, 2, 3, 4, 5, 6) Включает переменные, добавленные «плагинами переменных», а также host_vars и group_vars, добавленные стандартным плагином переменных Ansible.
[4] При создании с кэшируемым параметром set_facts, переменные будут иметь высокий приоритет в игре, но будут такими же, как у фактов хоста, когда они взяты из кэша.

Примечание

В любом разделе переопределение переменной перезаписывает предыдущий экземпляр. Если у нескольких групп есть одна и та же переменная, приоритет имеет последняя загруженная переменная. Если вы дважды определяете переменную в разделе vars сценария, приоритет имеет вторая.

Примечание

Предыдущее описание относится к конфигурации по умолчанию hash_behavior=replace, переключитесь на «merge», чтобы только частично перезаписывать.

Другой важный момент (для всех версий) заключается в том, что переменные соединения перезаписывают конфигурацию, опции/директивы командной строки и опции/директивы сценариев/ролей/задач. Например:

ansible -u lola myhost

Соединение всё равно будет как ramon, потому что ansible_ssh_user установлено в ramon в инвентаризации для myhost. Для игр/задач это также верно для remote_user:

- hosts: myhost
  tasks:
   - command: i'll connect as ramon still
     remote_user: lola

Это делается для того, чтобы настройки, специфичные для хоста, могли переопределять общие настройки. Эти переменные обычно определяются на хост или группу в инвентаризации, но они ведут себя как другие переменные. Если вы хотите переопределить удаленного пользователя глобально (даже над инвентаризацией), вы можете использовать дополнительные переменные:

ansible... -e "ansible_user=<user>"

Вы также можете переопределить как обычную переменную в плейбуке:

- hosts: all
  vars:
    ansible_user: lola
  tasks:
    - command: i'll connect as lola!

Области переменных

Ansible имеет 3 основные области:

  • Глобальная: устанавливается конфигурацией, переменными среды и командной строкой
  • Плейбук: каждый плейбук и вложенные структуры, записи переменных (vars; vars_files; vars_prompt), значения по умолчанию ролей и переменные.
  • Хост: переменные, непосредственно связанные с хостом, такие как инвентаризация, include_vars, факты или результаты зарегистрированных задач

Примеры переменных

Это кажется немного теоретическим. Давайте покажем некоторые примеры и где вы бы выбрали размещение переменных в зависимости от желаемого уровня контроля над значениями.

Прежде всего, переменные групп очень мощны.

Общие значения по умолчанию для всего сайта должны быть определены как group_vars/all настройка. Переменные групп обычно размещаются рядом с файлом инвентаризации. Они также могут быть возвращены динамическим скриптом инвентаризации (см. Динамическая инвентаризация) или определены в таких инструментах, как Ansible Tower через интерфейс пользователя или API:

---
# file: /etc/ansible/group_vars/all
# this is the site wide default
ntp_server: default-time.example.com

Региональная информация может быть определена в group_vars/region переменной. Если эта группа является дочерней группой all группы (а это так, поскольку все группы подчиняются иерархии), она переопределит группу, которая выше и более общая:

---
# file: /etc/ansible/group_vars/boston
ntp_server: boston-time.example.com

Если по какой-то невероятной причине мы захотим указать только определённому хосту использовать определенный NTP-сервер, это переопределит переменную группы!:

---
# file: /etc/ansible/host_vars/xyz.boston.example.com
ntp_server: override.example.com

Таким образом, это охватывает инвентаризацию и то, что вы обычно устанавливаете там. Это отличное место для вещей, связанных с географией или поведением. Поскольку группы часто являются сущностями, которые отображают роли на хосты, иногда это сокращение, чтобы установить переменные на группе вместо их определения в роли. Вы можете поступить так или иначе.

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

Далее: узнаем о приоритете переменных в роли.

Мы будем предполагать, что вы в основном используете роли на данном этапе. Вы должны использовать роли. Роли отличные. Вы используете роли, не так ли? Подсказка.

Итак, если вы пишете перераспределяемую роль с разумными значениями по умолчанию, поместите их в roles/x/defaults/main.yml файл. Это означает, что роль будет приносить значение по умолчанию, но ЛЮБОЕ значение в Ansible переопределит его. Это всего лишь значение по умолчанию. Вот почему говорится «значения по умолчанию» :) См. Роли для получения дополнительной информации об этом:

---
# file: roles/x/defaults/main.yml
# if not overridden in inventory or as a parameter, this is the value that 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, http_port: 8080 }

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

Это часто используется для вещей, которые могут применяться к некоторым хостам несколько раз, например:

roles:
   - { role: app_user, name: Ian    }
   - { role: app_user, name: Terry  }
   - { role: app_user, name: Graham }
   - { role: app_user, name: John   }

Это немного произвольно, но вы можете увидеть, как одна и та же роль вызывалась несколько раз. В этом примере, скорее всего, не было значения по умолчанию для «имени». Ansible может предупреждать вас, если переменные не определены — это, по сути, стандартное поведение.

Итак, это немного о ролях.

Существует несколько дополнительных аспектов, связанных с ролями.

В целом, переменные, установленные в одной роли, доступны другим. Это означает, что если у вас есть roles/common/vars/main.yml вы можете установить переменные в ней и использовать их в других ролях и в других местах вашего плейбука:

roles:
   - { role: common_settings }
   - { role: something, foo: 12 }
   - { role: something_else }

Примечание

Существуют некоторые меры предосторожности, чтобы избежать необходимости именовать переменные. В приведённом примере переменные, определённые в common_settings, безусловно, доступны задачам «something» и «something_else», но если гарантируется, что у «something» значение foo установлено в 12, даже если где-то глубоко в common_settings значение foo установлено в 20.

Итак, это приоритет, объясненный более прямо. Не беспокойтесь о приоритетах, просто подумайте, определяет ли ваша роль переменную по умолчанию или «актуальную» переменную, которую вы обязательно хотите использовать. Инвентаризация находится в середине приоритетов, и если вы хотите принудительно переопределить что-то, используйте -e.

Если вам показалось это сложным для понимания, ознакомьтесь с репозиторием ansible-examples на нашем сайте GitHub, чтобы узнать больше о том, как всё это может работать вместе.

Расширенный синтаксис

Дополнительную информацию о расширенном синтаксисе YAML, используемом для объявления переменных и более точного управления данными, размещёнными в файлах YAML, используемых Ansible, см. в разделе Расширенный синтаксис.

См. также

Плейбуки
Введение в плейбуки
Условные операторы
Условные операторы в плейбуках
Фильтры
Фильтры Jinja2 и их использование
Циклы
Использование циклов в плейбуках
Роли
Организация плейбуков с помощью ролей
Рекомендации по лучшим практикам
Рекомендации по лучшим практикам в плейбуках
Список рассылки пользователей
У вас есть вопросы? Задавайте их на форуме!
irc.freenode.net
Канал IRC-чата #ansible

© 2012–2018 Michael DeHaan
© 2018–2019 Red Hat, Inc.
Licensed under the GNU General Public License version 3.
https://docs.ansible.com/ansible/2.4/playbooks_variables.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API