Spec-Zone.ru › Ansible 2.7

Вступление к Playbooks

О Playbooks

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

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

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

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

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

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

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

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

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

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

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

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

Для начала вот playbook, содержащий только один 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 порядке: сверху вниз.

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

Основы

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

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

Список задач

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

При выполнении 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 все задачи будут перечислены непосредственно в этом 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

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

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

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

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

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

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

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

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

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

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

Если вам нужно увидеть подробный вывод как от успешных, так и от неудачных модулей, используйте флаг --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.7/user_guide/playbooks_intro.html

Spec-Zone.ru

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