Spec-Zone.ru › Ansible 2.6

Введение в Playbooks

О Playbooks

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

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

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

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

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

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

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

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

Каждый playbook состоит из одного или нескольких «игр» в списке.

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

Комбинируя playbook из нескольких «игр», можно оркестрировать развертывания на нескольких машинах, выполняя определенные шаги на всех машинах в группе веб-серверов, затем определенные шаги на группе серверов базы данных, а затем дополнительные команды на группе веб-серверов и т. д.

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

Для начала вот playbook, содержащий только одну игру:

---
- 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 могут содержать несколько игр. У вас может быть 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 и так далее. Игры, как и задачи, выполняются в указанном порядке в playbook: сверху вниз.

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

Основы

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

Для каждой игры в 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 для конкретной задачи вместо всей игры:

---
- 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 или при использовании старого синтаксиса sudo --ask-sudo-pass (-K). Если вы запустили playbook с become и playbook задерживается, вероятно, он застрял на запросе повышения привилегий. Просто Control-C, чтобы убить его, и запустите его снова, добавив соответствующий пароль.

Важно

При использовании 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

Возможные значения для порядка:

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

Список задач

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

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

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

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

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

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

Задачи могут быть объявлены с помощью устаревшего формата 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 все задачи будут перечислены непосредственно в этой игре, хотя обычно будет более логично разбить задачи, как описано в Создание многократно используемых Playbooks.

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

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

Ansible предпочитает перечислять модули так:

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

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

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

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

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

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

Например, несколько ресурсов могут указывать на необходимость перезапуска 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 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"

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

Примечание

  • Обработчики, уведомлённые с помощью notify, всегда выполняются в том же порядке, в котором они определены, not в порядке, указанном в инструкции notify. Это также относится к обработчикам, использующим 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. Это немного специфичный случай, но может пригодиться время от времени.

Выполнение Playbook

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

ansible-playbook playbook.yml -f 10

Ansible-Pull

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

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

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

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

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

Советы и хитрости

Чтобы проверить синтаксис playbook'а, используйте ansible-playbook с флагом --syntax-check. Это позволит выполнить проверку playbook'а через парсер, чтобы убедиться, что включенные файлы, роли и т. д. не имеют проблем с синтаксисом.

Внизу выполнения playbook'а вы увидите сводку узлов, на которые был нацелен playbook, и как они выполнялись. Общие ошибки и фатальные попытки связи «недоступны» хранятся отдельно в подсчётах.

Если вы хотите увидеть подробный вывод успешных модулей, а также неуспешных, используйте флаг --verbose. Он доступен в Ansible 0.5 и более поздних версиях.

Чтобы увидеть, какие хосты будут затронуты playbook'ом до его запуска, вы можете сделать это:

ansible-playbook playbook.yml --list-hosts

См. также

YAML-синтаксис
Изучите YAML-синтаксис
Рекомендации по практике
Различные советы по управлению playbook'ами в реальном мире
Все модули
Изучите доступные модули
Разработка модулей
Узнайте, как расширить Ansible, написав собственные модули
Работа с шаблонами
Узнайте, как выбирать хосты
Директория примеров Github
Примеры playbook'ов "от начала до конца"
Список рассылки
Вопросы? Помощь? Идеи? Заходите на список в 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.6/user_guide/playbooks_intro.html

Spec-Zone.ru

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