Spec-Zone.ru › Ansible 2.8

Введение в Playbooks

  • О Playbooks
  • Пример языка Playbook
  • Основы
    • Хосты и Пользователи
    • Список задач
  • Сокращения действий
  • Обработчики: Выполнение операций при изменении
  • Выполнение Playbook
  • Ansible-Pull
  • Проверка playbooks
  • Другие варианты проверки playbook

О Playbooks

Playbooks — это принципиально другой способ использования Ansible по сравнению с выполнением задач в режиме ad-hoc, и они особенно мощные.

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

Playbooks могут объявлять конфигурации, но они также могут оркестрировать шаги любого ручного упорядоченного процесса, даже если различные шаги должны передаваться туда-сюда между наборами машин в определённом порядке. Они могут запускать задачи синхронно или асинхронно.

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

В репозитории ansible-examples также есть несколько полных наборов playbooks, иллюстрирующих многие из этих техник. Рекомендуется ознакомиться с ними в отдельной вкладке по ходу дела.

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

Пример языка Playbook

Playbooks записываются в формате YAML (см. Синтаксис YAML) и имеют минимальный синтаксис, который намеренно пытается не быть языком программирования или скриптом, а скорее моделью конфигурации или процесса.

Примечание

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

Каждый playbook состоит из одного или нескольких ‘plays’ в списке.

Цель play — сопоставить группу хостов с определёнными ролями, представленными тем, что Ansible называет задачами. На базовом уровне задача — это просто вызов модуля Ansible (см. Работа с модулями).

Комбинируя playbook из нескольких ‘plays’, можно оркестрировать развертывания на нескольких машинах, выполняя определённые шаги на всех машинах в группе webservers, затем определённые шаги на сервере базы данных, затем дополнительные команды обратно на серверах webservers и т. д.

“Plays” — это, так сказать, аналогия из спорта. У вас может быть довольно много plays, которые влияют на ваши системы, чтобы выполнять разные задачи. Это не так, как если бы вы просто определяли одно определённое состояние или модель, и вы можете запускать разные plays в разное время.

Для начала вот playbook, verify-apache.yml содержащий только один play:

---
- hosts: webservers
  vars:
    http_port: 80
    max_clients: 200
  remote_user: root
  tasks:
  - name: ensure apache is at the latest version
    yum:
      name: httpd
      state: latest
  - name: write the apache config file
    template:
      src: /srv/httpd.j2
      dest: /etc/httpd.conf
    notify:
    - restart apache
  - name: ensure apache is running
    service:
      name: httpd
      state: started
  handlers:
    - name: restart apache
      service:
        name: httpd
        state: restarted

Playbooks могут содержать несколько plays. У вас может быть playbook, который сначала нацелен на веб-серверы, а затем на серверы базы данных. Например:

---
- hosts: webservers
  remote_user: root

  tasks:
  - name: ensure apache is at the latest version
    yum:
      name: httpd
      state: latest
  - name: write the apache config file
    template:
      src: /srv/httpd.j2
      dest: /etc/httpd.conf

- hosts: databases
  remote_user: root

  tasks:
  - name: ensure postgresql is at the latest version
    yum:
      name: postgresql
      state: latest
  - name: ensure that postgresql is started
    service:
      name: postgresql
      state: started

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

Ниже мы разберём различные функции языка playbook.

Основы

Хосты и Пользователи

Для каждого play в playbook вы можете выбрать машины в вашей инфраструктуре, на которые нацелены, и удалённого пользователя, от имени которого будут выполняться шаги (называемые задачами).

Строка hosts — это список одной или нескольких групп или шаблонов хостов, разделенных двоеточиями, как описано в документации Работа с шаблонами. Строка remote_user просто имя учётной записи пользователя:

---
- hosts: webservers
  remote_user: root

Примечание

Параметр remote_user раньше назывался просто user. Он был переименован в Ansible 1.4, чтобы его легче было отличить от модуля user (используемого для создания пользователей на удалённых системах).

Удалённые пользователи также могут быть определены в рамках задачи:

---
- hosts: webservers
  remote_user: root
  tasks:
    - name: test connection
      ping:
      remote_user: yourname

Поддержка выполнения действий от имени другого пользователя также доступна (см. Понимание повышения привилегий):

---
- hosts: webservers
  remote_user: yourname
  become: yes

Также можно использовать ключевое слово become в конкретной задаче вместо всего play:

---
- hosts: webservers
  remote_user: yourname
  tasks:
    - service:
        name: nginx
        state: started
      become: yes
      become_method: sudo

Также можно войти как вы, а затем стать пользователем, отличным от root:

---
- hosts: webservers
  remote_user: yourname
  become: yes
  become_user: postgres

Также можно использовать другие методы повышения привилегий, такие как su:

---
- hosts: webservers
  remote_user: yourname
  become: yes
  become_method: su

Если вам нужно указать пароль для sudo, запустите ansible-playbook с --ask-become-pass или -K. Если вы запустите playbook, использующий become и playbook, похоже, зависает, это, вероятно, связано с зависанием на запросе повышения привилегий, и его можно остановить, используя Control-C, позволяя вам повторно выполнить playbook, добавив соответствующий пароль.

Важно

При использовании become_user для пользователя, отличного от root, аргументы модуля кратковременно записываются в случайный временный файл в /tmp. Эти файлы удаляются сразу после выполнения команды. Это происходит только при изменении привилегий от пользователя, такого как «bob», к «timmy», а не при переходе от «bob» к «root» или при непосредственном входе в систему как «bob» или «root». Если вас беспокоит, что эти данные кратковременно читаемы (но не записываемые), избегайте передачи нешифрованных паролей с become_user установленными. В других случаях /tmp не используется, и это не имеет значения. Ansible также заботится о том, чтобы не записывать параметры паролей.

Новое в версии 2.4.

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

- hosts: all
  order: sorted
  gather_facts: False
  tasks:
    - debug:
        var: inventory_hostname

Возможные значения для order:

inventory:
Значение по умолчанию. Порядок — «как предоставлено» инвентарём
reverse_inventory:
Как следует из названия, этот порядок меняет «как предоставлено» инвентарём
sorted:
Хосты сортируются по имени в алфавитном порядке
reverse_sorted:
Хосты сортируются по имени в обратном алфавитном порядке
shuffle:
Хосты случайным образом упорядочиваются при каждом запуске

Список задач

Каждый play содержит список задач. Задачи выполняются в порядке следования, по одной за раз, на всех машинах, соответствующих шаблону хоста, прежде чем переходить к следующей задаче. Важно понимать, что в рамках одного play все хосты получат одни и те же инструкции задачи. Цель play — сопоставить выбранные хосты с задачами.

При запуске playbook, который выполняется сверху вниз, хосты с неудачными задачами исключаются из цикла для всего playbook. Если что-то не удалось, просто исправьте файл playbook и запустите его снова.

Цель каждой задачи — выполнить модуль со специфическими аргументами. В аргументах модулей можно использовать переменные.

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

Модули command и shell обычно повторно выполняют одну и ту же команду, что вполне допустимо, если команда такая, как chmod или setsebool, и т. д. Хотя существует флаг creates который можно использовать для того, чтобы сделать эти модули также идемпотентными.

Каждая задача должна иметь name, который включается в выходные данные при запуске playbook. Это удобочитаемые выходные данные, и поэтому полезно предоставлять хорошие описания каждого шага задачи. Если имя не указано, для вывода используется строка, переданная в ‘action’.

Задачи могут быть объявлены с использованием устаревшего action: module options формата, но рекомендуется использовать более стандартный формат module: options Этот рекомендуемый формат используется во всей документации, но вы можете встретить более старый формат в некоторых playbooks.

Вот как выглядит базовая задача. Как и большинство модулей, модуль service принимает key=value аргументы:

tasks:
  - name: make sure apache is running
    service:
      name: httpd
      state: started

Модули command и shell — единственные модули, которые просто принимают список аргументов и не используют формат key=value. Это делает их работоспособными так, как вы ожидаете:

tasks:
  - name: enable selinux
    command: /sbin/setenforce 1

Модули command и shell учитывают коды возврата, поэтому если у вас есть команда, успешный код выхода которой не равен нулю, вы можете сделать так:

tasks:
  - name: run this command and ignore the result
    shell: /usr/bin/somecommand || /bin/true

Или так:

tasks:
  - name: run this command and ignore the result
    shell: /usr/bin/somecommand
    ignore_errors: True

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

tasks:
  - name: Copy ansible inventory file to client
    copy: src=/etc/ansible/hosts dest=/etc/ansible/hosts
            owner=root group=root mode=0644

В строках действия можно использовать переменные. Предположим, вы определили переменную с именем vhost в разделе vars, вы можете сделать так:

tasks:
  - name: create a virtual host file for {{ vhost }}
    template:
      src: somefile.j2
      dest: /etc/httpd/conf.d/{{ vhost }}

Эти же переменные можно использовать в шаблонах, о которых мы поговорим позже.

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

Сокращения действий

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

Ansible предпочитает перечисление модулей следующим образом:

template:
    src: templates/foo.j2
    dest: /etc/foo.conf

Ранние версии Ansible использовали следующий формат, который всё ещё работает:

action: template src=templates/foo.j2 dest=/etc/foo.conf

Обработчики: Выполнение операций при изменении

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

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

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

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

- name: template configuration file
  template:
    src: template.j2
    dest: /etc/foo.conf
  notify:
     - restart memcached
     - restart apache

Элементы, перечисленные в разделе notify задачи, называются обработчиками.

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

Вот пример раздела обработчиков:

handlers:
    - name: restart memcached
      service:
        name: memcached
        state: restarted
    - name: restart apache
      service:
        name: apache
        state: restarted

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

handlers:
# this handler name may cause your play to fail!
- name: restart "{{ web_service_name }}"

Если переменная, используемая в имени обработчика, недоступна, весь плейбук завершается неудачно. Изменение этой переменной во время плейбука не приведёт к созданию нового обработчика.

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

tasks:
  - name: Set host variables based on distribution
    include_vars: "{{ ansible_facts.distribution }}.yml"

handlers:
  - name: restart web service
    service:
      name: "{{ web_service_name | default('httpd') }}"
      state: restarted

Начиная с Ansible 2.2, обработчики также могут «прослушивать» общие темы, и задачи могут уведомлять эти темы следующим образом:

handlers:
    - name: restart memcached
      service:
        name: memcached
        state: restarted
      listen: "restart web services"
    - name: restart apache
      service:
        name: apache
        state: restarted
      listen: "restart web services"

tasks:
    - name: restart everything
      command: echo "this task will restart the web services"
      notify: "restart web services"

Это использование значительно упрощает запуск нескольких обработчиков. Также оно отвязывает обработчики от их имён, что упрощает обмен обработчиками между плейбуками и ролями (особенно при использовании ролей сторонних разработчиков из общего источника, такого как Galaxy).

Примечание

  • Обработчики уведомлений всегда выполняются в том же порядке, в котором они определены, not в порядке, указанном в операторе уведомления. Это также относится к обработчикам, использующим listen.
  • Имена обработчиков и listen темы существуют в глобальном пространстве имён.
  • Имена обработчиков могут быть шаблонизированы, а listen темы — нет.
  • Используйте уникальные имена обработчиков. Если вы запускаете более одного обработчика с одинаковым именем, первые будут перезаписаны. Запустится только последний.
  • Вы не можете уведомить обработчик, определённый внутри include. Начиная с Ansible 2.1, это работает, однако include должен быть static.

Роли описываются позже, но стоит отметить, что:

  • обработчики, уведомлённые внутри pre_tasks, tasks, и post_tasks секций, автоматически очищаются в конце секции, где они были уведомлены,
  • обработчики, уведомлённые внутри roles секции, автоматически очищаются в конце tasks секции, но до любых tasks обработчиков,
  • обработчики относятся к плейбуку и могут быть использованы за пределами роли, в которой они определены.

Если вам нужно немедленно очистить все команды обработчика, вы можете сделать это:

tasks:
   - shell: some tasks go here
   - meta: flush_handlers
   - shell: some other tasks

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

Выполнение плейбука

Теперь, когда вы изучили синтаксис плейбука, как запустить плейбук? Это просто. Давайте запустим плейбук с уровнем параллелизма 10:

ansible-playbook playbook.yml -f 10

Ansible-Pull

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

ansible-pull — это небольшой скрипт, который выгрузит репозиторий с инструкциями конфигурации из git и затем выполнит ansible-playbook против этого содержимого.

Предполагая, что вы распределяете нагрузку на своё место выгрузки, ansible-pull масштабируется практически до бесконечности.

Запустите ansible-pull --help для получения подробностей.

Также доступен умный плейбук для настройки ansible-pull через crontab из режима отправки.

Проверка плейбуков

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

Например, если вы запустите ansible-lint на плейбуке verify-apache.yml, представленном ранее в этом разделе, вы получите следующие результаты:

$ ansible-lint veryify-apache.yml
[403] Package installs should not use latest
verify-apache.yml:8
Task/Handler: ensure apache is at the latest version

На странице стандартных правил ansible-lint описаны все ошибки. Для [403], рекомендуемое исправление — изменить state: latest на state: present в плейбуке.

Другие варианты проверки плейбуков

См. Инструменты для проверки плейбуков для подробного списка инструментов, которые вы можете использовать для проверки плейбуков. Вот ещё несколько, которые следует учитывать:

  • Для проверки синтаксиса плейбука используйте ansible-playbook с флагом --syntax-check. Это запустит плейбук через парсер, чтобы убедиться, что включённые файлы, роли и т. д. не содержат проблем с синтаксисом.
  • Просмотрите вывод выполнения плейбука внизу для сводки узлов, на которые было нацелено выполнение, и результатов их выполнения. Общие ошибки и фатальные попытки недоступной связи сохраняются отдельно в отчёте.
  • Если вы хотите увидеть подробный вывод успешных и неуспешных модулей, используйте флаг --verbose. Он доступен в Ansible 0.5 и более поздних версиях.
  • Чтобы посмотреть, на какие хосты повлияет плейбук перед его запуском, выполните это:

    ansible-playbook playbook.yml --list-hosts
    

См. также

ansible-lint
Узнайте, как проверить синтаксис Ansible Playbook
YAML Синтаксис
Узнайте о синтаксисе YAML
Рекомендации
Различные советы по управлению плейбуками в реальном мире
Все модули
Узнайте о доступных модулях
Нужно ли разрабатывать модуль?
Узнайте, как расширить Ansible, написав собственные модули
Работа с шаблонами
Узнайте о способах выбора узлов
GitHub каталог примеров
Полные примеры плейбуков «от начала до конца»
Список рассылки
Вопросы? Помощь? Идеи? Загляните на список рассылки Google Groups

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

Spec-Zone.ru

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