Хитрости и особенности Ansible

В этой статье собраны небольшие трюки и особенности ansible, связанные с использованием и написанием плейбуков и скриптов. 

Получить файлы с сервера

В своих скриптах, мне понадобилось получать файл с сервера. Для этого служит команда fetch. Эта команда скачивает файл по пути заддному параметром src и сохраняет на хосте ansible по пути заданном атрибутом dest. Есть еще дополнительные атрибуты: fail_on_missing который принимает значение yes\no и отвечает за то, что будет ли считаться ошибкой отсутствие файла. 

Пример:

Есть еще одна полезная функция include_vars которая позволяет загрузить из yaml файла значения переменных. Например, загрузка переменных специфичных для ОС:

Есть еще интересный атрибут, который применяется к задачам, назыается delegate_to, который указывает, что данный таск будет выполнен только на указанном сервере.

Пример:

В этом примере задача “Create file1” будет выполнена только на сервере linux3, а задача “Create file2” – на всех серверах. Хотя физически команда на “Create file1” поступит на все сервера, но ее выполнит только linux3. Задача “Unregister server”, будет выполнена на сервере 127.0.0.1 (то есть ansible master) и запишет в файл инорацию обо всех серверах в данном случае (в файл log.txt).

Еще две задачи описывают как прегрузить сервера и подождать их запуска.

Дериктива run_once указывает, что задача выполняется только на одном любой сервере (обычно это первый по порядку)

Перехват и контроль ошибок

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

Например такой плейбук:

Дериктива ignore_errors: yes указывает на то, что если при выполнении задания возникнет ошибка, то она не будет останавливать дальнейшее выполнение задания на этом сервере (они не будут игнорироваться). В нашем случае несмотря на то, что команда не существует и всегда будет выдавать ошибку, то все равно весь скрипт продолжит работу. 

Задача “Task 2” – это вариант определения ошибки по результатам работы команды, результат выполнения команды сохраняется в переменную, а затем в дериктиве faild_when выполняется проверка и если ее результат положителен, то команда считает что возникла ошибка. Пример анализа ошибки по коду возврата в задаче “Task 2.2”

Директива any_errors_fatal: true в начале файла указывает на то, что ошибка на любом сервере приведет к полной остановке выполнения всего скрипта на всех серверах.

Хранение секретов Ansible-Vault

Так как хранить пароли в открытом виде, это не безопасно, то есть метод применения для таких критических данных – хранилища паролей, где данные хранятся в закодированном виде. В пакете ansible есть встроенное хранилище.

Для создания пустого хранилища используется команда: ansible-vault create <имя файла хранилища>. После чего запрашивается пароль для шифрования и открывается редактор в котором можно написать любые текстовые данные, которые по завершению будут зашифрованы.

Для просмотра данных используется команда: ansible-vault view <имя файла хранилища>.

Для редактирования данных используется команда: ansible-vault edit <имя файла хранилища>.

Для смены пароля данных используется команда: ansible-vault rekey <имя файла хранилища>.

Для примера рассмотрим блейбук:

Можно зашифровать весь плейбук: ansible-vault encrypt playbook.yml

Расшифровать можно командой: ansible-vault decrypt playbook.yml

А можно и запустить: ansible-playbook playbook.yml –ask-vault-pass (если упустить –ask-vault-pass, то возникнет ошибка что пароль не найден)

Пароль можно указать в файле, тогда запуск будет таким: ansible-playbook playbook.yml –vault-password-file <путь к файлу с паролем> (указывается просто файл с текстовым содержимым в виде пароля)

Однако можно шифровать не весь файл, а только значения переменных. Такое шифрованное значение можно получить через команду: ansible-vault encrypt-string, после чего у вас спросят пароль а затем текст который будет зашифрован. После завершения требуеся нажать Ctrl+D два раза получим строку, которая начинается с !vault и эти данные можно просто ставить в плейбук вместо пароля.

Однако такие файлы требуется всегда запускать с аргументами –ask-vault-pass или–vault-password-file.

Другой способ получить зашифрованное значение это команда:

echo -n “данные для шифрования” | ansible-vault encrypt_string

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

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

Сравнение строк

Для сравнение строк с подстроками или шаблонами применяются атрибуты match, search, regex.

Атрибут match возврашает инстину если он нашел шаблон в начале строки, в то время как search ищет совпадения по всей строке. По умолчанию regex, работает как search, однако его можно пренестроить через атрибут match_type, который определяет как идет обработка регулярного вырожения. Полный список значений можно посмотреть тут. Кроме того доступны также атрибуты  ignorecase и multiline.

Функции для IP адресов

Часто при анализе возникает потребность проверить является ли строка IP адрессом и к какой сети он относится:

Это можно сделать через фильтры ipv4, ipv6, apaddr – которые проверяют, что строка является адресом версии 4, 6 и вообще является корректным адресом.

Например: ansible_ip_addresses | ipv4 – вернет только IPv4, которые заданы для сервера.

 Фильтр ipaddr, имеет много функций, если задать адрес сети вместе с маской, то им можно проверть, что адресс соотествует указанной сети:

Кроме того тот же фильтр может проверять, что адрес публичный – ‘public’, приватный – ‘private’  и задан с маской сети – ‘net’, кроме того для адресов заданных в форме сети, можно получить количество хостов – ‘size’. Подробности тут.

Еще одна особенность например в данных про сервер с которым мы работам есть две переменные: ansible_ip_addresses – это список ip адресов, назначенных серверу и переменная ansible_interfaces – описывающая, какие интерфейсы есть на хосте, но тут есть особенность, что этим интерфейсам не сопоставлены ip адреса. 

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

– set_fact:
  net_intf: “{{ ansible_ip_addresses | ipv4 | zip( ansible_interfaces | json_query(‘[*].connection_name’)) | list }}”

Выполнение блока задач в цикле

Мне потребовалось пройти по адресам сервера и в зависимости от того к какой сети принадлежит адрес выполнить несколько действий. Однако как оказалось block не совместим с циклами. Выход оказался не обычным и потребовал применения дерективы include_tasks и создания отдельного файла с задачами.

Основной список задач содержит следующий код:

– name: Setup Network
      include_tasks: net_config.yml
   loop: “{{ net_intf }}”

А в отдельном файле net_config.yml прописываем необходимый блок или блоки, как например так:

В этом примере есть два блока которые перебираются по циклу и выполняется тот для которого ip адресс подходит под указанную сеть.

Просмотр фактов о сервере

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

Это можно сделать, через команду:

Либо как отладочная инфомация в задачах:

Коллекция плагинов для Windows серверов

Существует набор плагинов для работы с windows  серверами, эти плагины достыны по адресу https://galaxy.ansible.com/community/windows. Установить данную коллекцию можно командой:

Кроме того, данный плагин, может быть указан как завизимость в файле requirements.yml:

Установка зависимостей возможна и командой:

ansible-galaxy collection install -r requirements.yml

Кроме того есть еще стандартный набор встроенный в ansible, про него можно посмотреть тут.

Установка временной зоны для windows сервера

При настройки серверов на начальном этапе часто надо установить правильную временную зону, для этого служит команда community.windows.win_timezone, у которой есть один обязательный атрибут timezone, который задает символьную строку содержащую название временной зоны. Название зон можно посмотреть в документации windows.

Пример задачи:

Киев, Рига, София (+2 часа) – название зоны ” FLE Standard Time”.

В результате выполненя возвращается json объект с двумя полями “previous_timezone” и “timezone”, предыдущая зона и текущая соотвественно.

Создание локальных учетных записей

Для управления локальными учетными данными служит плагин ansible.windows.win_user. При помощи этого плагина можно изменить, удалить или создать пользователя:

Первая задача создает пользователя, с указанным именем, паролем и добавляет его в группу. Вторая задача удаляет пользователя. Операция добавления\удаления определяется атрибутом state (present – создать, absent – удалить).

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

  • account_disabled: yes/no – будет создан отключенный акаунт, по умолчанию no.
  • account_locked: yes/no – будет создан заблокированный акаунт, по умолчанию no.
  • description – описание акаунта
  • fullname – полное имя для акаунта
  • groups – список груп в которые должен быть добавлен акаунт
  • groups_action: add/replace/remove – операция над группами (добавить/заменить/удалить), по умолчанию заменить.
  • home_directory – домашняя категория пользователя
  • login_script – скрипт, который выполняется при логине
  • name – обязательный параметр, имя учетки
  • password – пароль
  • password_expired: yes/no – указывает, что у акаунта пароль устарел
  • password_never_expires: yes/no – указание, что пароль не будет устаревать
  • profile – профиль пользователя
  • state: present|absent|query – создать учетную запись/удалить запись/или опросить запись без изменений, по умолчанию создать (present).
  • update_password: always|on_create – всегда обнавлять / не трогать пароль если пользователь уже существует 
  • user_cannot_change_password: yes/no – указывает может ли пользователь менять пароль

Возвращает поля учетной записи, которая создана или измнена, а также общие поля о состоянии операции.

Создание локальных групп

Для управления локальными группами служит плагин ansible.windows.win_group. При помощи этого плагина можно удалить или создать локальную группу:

Есть три атрибута:

  • description – описание акаунта
  • name – обязательный параметр, имя группы
  • state: present|absent – создать группу/удалить группу, по умолчанию создать (present).

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

Для управления пользователями в группах служит плагин ansible.windows.win_group_membership. При помощи этого плагина можно добавить или убрать пользователй из гурппы:

Есть три атрибута:

  • members – список акаунтов которые должны попасть в группу
  • name – обязательный параметр, имя группы
  • state: present|absent|pute- добавить пользователей в группу/удалить их из группы/оставить только указанных пользователей, а остальных удалить, по умолчанию создать (present).

Задания статических маршрутов в Windows

Когда на сервере необходимо прописать маршрутизацию на помощь приходит модуль community.windows.win_route. Пример:

Есть четыре атрибута:

  • gateway – адрес шлюза
  • metric – метрика, занчение по умолчанию 1
  • destination – обязательный параметр, адрес сети назначения в формате ip/префикс

  • state: present|absent- добавить маршрут /удалить, по умолчанию создать (present).

 

Обсуждение закрыто.