🐹 Ansible: Часть 3. Сценарии (плейбуки) — Playbooks.

Содержание:

1. Введение.
2. Сценарии — playbooks.
3. Обработчики событий — handlers.
4. Контроль выполнения.
5. Шаблонизация.
6. Делегирование задачи другому хосту.
7. Роли.
8. Структура проекта.
9. Пишем первые playbook’и.
10. Пример сценария.
11. Практические примеры плейбуков.
12. Запуск плейбуков.
13. Запрос информации о play.
14. Управление выполнением плейбука.
15. Настройка защищенных плейбуков.
16. Оригиналы источников информации.


На чем было опробовано:

  1. Ansible 2.9.18
  2. Hyper-V на Windows 10 Pro.
  3. Сервер Ansible: CentOS Linux release 7.9.2009 (Core).
  4. Node 1: CentOS Linux release 7.9.2009 (Core).
  5. Node 2: CentOS Linux release 7.9.2009 (Core).
  6. Node 3: CentOS Linux release 7.9.2009 (Core).

1. Введение.

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

Ссылка: docs.ansible.com.
Раздел: «ansible-playbook».

Как установить и первоначально настроить Ansible описано здесь:

Ссылка: «Ansible: Часть 1. Описание, установка и первоначальная настройка.»

Так как простые задачи для Ansible реально простые, в буквальном смысле слова, то я принял решение вынести их в отдельную инструкцию:

Ссылка: «Ansible: Часть 2. Примеры простых задач.»

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

Ссылка: «Ansible: Часть 4. Практические примеры плейбуков.»

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

Ссылка: «Ansible: Часть 5. Настройка защищенных плейбуков.»

2. Сценарии — playbooks.

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

Рассмотрим структуру и правила написания таких сценариев более подробно.

Все сценарии в Ansible пишутся на YAML — это удобный для человека формат данных, гораздо более простой, чем XML или JSON.

Чтобы выполнить сценарий используется команда ansible-playbook со следующим синтаксисом:

# ansible-playbook <имя_файла_сценария.yml> ... [другие параметры]

Для Ansible практически каждый YAML файл начинается со списка. Каждый элемент списка — список пар «ключ-значение», часто называемая словарем.

В начале сценария обязательно должна присутствовать последовательность символов ‘---‘ (так в YAML обозначается начало документа).

Перед каждым новым разделом списка ставится дефис ( - ):

---
- name: Операции с SELinux
  hosts: webservers
  become_method: sudo
  become_user: root

  tasks:
  - name: Отключаем SELinux
    selinux:
      state: disabled

Основными параметрами/группами простого сценария являются:

  • hosts — в нем указываются управляемые узлы или группы узлов, к которым нужно применить изменения;
  • tasks — здесь описывается состояние, в которое необходимо привести управляемый узел, альтернативой этому могут служить роли;

Также в сценарии перед непосредственным описанием задач могут быть указаны следующие параметры или группы параметров:

  • gather_facts — собирать или нет информацию об узлах перед выполнением задач, по умолчанию — да;
  • vars — в нем указываются различные переменные, которые будут использованы при выполнении сценария;
  • connection — можно указать метод соединения с узлами: pure ssh, paramiko, fireball, chroot, jail, local, accelerate (применимо также для выполнения отдельного модуля);
  • sudo — после установления соединения выполнять задачу с привилегиями другого пользователя, по умолчанию другой пользователь — root;
  • sudo_user — в сочетании с предыдущим параметром можно указать с привилегиями какого именно пользователя будет выполнена задача;
  • vars_prompt — перед выполнением плейбука Ansible в интерактивном режиме может уточнить указанные в этом разделе параметры;
  • remote_user (в предыдущих версиях — просто user) — имя пользователя для авторизации на удалённом узле.

Рассмотрим все эти разделы более подробно.

В разделе hosts указывается группа управляемых узлов, к которой будут применены описываемые в сценарии изменения.

Так, строка формата:

hosts: webservers

Это означает, что изменения будут применены к узлам из группы webservers.

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

В следующем примере авторизация на узле будет произведена с именем yourname, но задачи будут выполняться от имени пользователя root (если, конечно, этому пользователю это разрешено):

---
- name: Операции с SELinux
  hosts: webservers
  become_method: sudo
  become_user: yourname

Если добавить параметр ‘user: postgres‘, то все действия будут выполняться с привилегиями пользователя postgres.

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

- hosts: webservers
  vars:
     http_port: 80
     max_clients: 200

Список изменений, которые необходимо произвести на управляемом узле, приводится в разделе tasks. Каждой задаче (task) присваивается имя (name).

Далее указываются модули Ansible, которые будут задействованы при ее выполнении:

---
- hosts: webservers
  user: yourname
  tasks:
  - service:
      name: nginx
      state: started

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

---
- hosts: webservers
  user: yourname
  tasks:
  - service:
      name: nginx
      state: started
    sudo: yes

Еще некоторые примеры.

Все члены списка должны находится с одинаковым отступом от начала строки, и должны начинаться с пробела или «-». Комментарии начинаются с «#».

Например:

---
# Message
- Hosting
  Cloud

Словарь представлен в виде «ключ:» (двоеточие и пробел) «значение»:

---
# Message
site: habr
blog: infobox

При необходимости словари могут быть представлены в сокращенной форме:

--
# Comment
{site: habr, blog: infobox}

Можно указать логические значение (истина/ложь) так:

---
need_access: no
use_service: yes
file_conf: TRUE
read_value: True
kill_process: false

Целиком наш пример YAML–файла будет выглядеть так:

---
# About blog
site: hamstersen.ru
blog: infobox
must_read: true
themes:
- hosting
- cloud
- it
- geeks
  brands:
  - infobox
  - infoboxcloud

Для переменных Ansible использует «{{ var }}». Если значение после двоеточия начинается с «{», то YAML будет думать, что это словарь.

Для использования переменных нужно заключить скобки в кавычки:

word: "{{ variable }}"

Этого достаточно для начала написания playbooks.

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

Ссылка: «Ansible: Часть 4. Практические примеры плейбуков.»

3. Обработчики событий — handlers.

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

Приведём пример:

---
- hosts: webservers
  vars:
    max_clients: 200

  tasks:
  # генерируем файл конфигурации на основе шаблона
  # и укажем, что требуется выполнить задачу “restart apache”
  # если файл изменился
  - 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 для перезапуска веб-сервера
      service:
        name: httpd
        state: restarted

4. Контроль выполнения.

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

Для этого можно использовать оператор «when»:

tasks:
    # сохраняем файл шаблона и сохраняем результат задачи
    # в переменную last_result
    - template:
        src: /templates/foo.j2
        dest: /etc/foo.conf
      register: last_result
    # проверяем переменную last_result.changed и если она имеет
    # значение true - задача будет выполнена, иначе - будет пропущена
    - command:
        echo 'the file has changed'
        when: last_result.changed

5. Шаблонизация.

В Ansible используется шаблонизатор Jinja2.

Приведём пример шаблона (часть конфигурации powerdns):

# пароль для подключения к базе данных
gpgsql-password={{ lookup('password', 'credentials/' + inventory_hostname + '/postgresql/powerdns', length=15) }}

# IPv4-адрес, который будет “слушать” powerdns
local-address={{ ansible_default_ipv4.address }}

# IPv6-адрес, который будет “слушать” powerdns
local-ipv6={{ ansible_default_ipv6.address }}

# nsid dns-сервера (EDNS option 3, rfc5001)
server-id={{ ansible_hostname }}

В приведённом примере мы подставляем в шаблон следующие значения:

  • из заранее собранных фактов об узле:
    • ansible_default_ipv4.address — основной IPv4-адрес узла;
    • ansible_default_ipv6.address — основной IPv6-адрес узла;
    • ansible_hostname — имя узла (результат выполнения команды hostname).
  • inventory_hostname — имя узла в инвентарном файле;
  • пароль пользователя powerdns из внешнего источника данных (в данном случае файл) для подключения к базе Postgresql , полученный с помощью lookup-плагина password из стандартной поставке. Особенность некоторых lookup-плагинов — если данных нет, то они могут их генерировать и сохранить для последующего использования.

Обработку шаблонов и, в данном случае, генерацию конфигурационного файла выполняет модуль template; он же может задать необходимые права доступа и изменить владельца/группу:

- name: generate powerdns config
template: src=pdns.conf.j2 dest=/etc/powerdns/pdns.conf owner=powerdns group=powerdns mode=600

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

6. Делегирование задачи другому узлу.

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

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

Приведём пример:

- name: disable nagios alerts for this host webserver service
  nagios:
    action: disable_alerts
    host: {{inventory_hostname}}
    services: dnsserver
  delegate_to: mon_host.example.com

Результатом выполнения этой задачи будет отключение сообщений для сервиса dnsserver в Nagios.

7. Роли.

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

В сценариях роли назначаются следующим образом:

---
- name: check and apply basic configuration to all hosts
   hosts: all
   roles:
     - common

- name: check and apply configuration to group1
   hosts: group1
   roles:
     - pgsql

- name: check and apply configuration to group2
   hosts: group2
   roles:
     - fooapp

8. Структура проекта.

9. Пишем первые playbook’и.

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

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

В качестве другого примера давайте рассмотрим процесс установки nginx.

Создадим директорию, где будут хранится playbooks:

# mkdir ~/ansible/playbooks

Создадим файл setup_nginx.yml в директории playbooks со следующим содержанием:

---
- hosts: experiments
  tasks:
  - name: Install nginx package
    apt: 
      name: nginx
      update_cache: yes
    sudo: yes
  - name Starting nginx service
    service:
      name: nginx
      state: started
    sudo: yes

Давайте рассмотрим содержимое:

  • hosts: Список узлов или группа, на которой вы запускаете задачу.

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

Узнать, на каких узлах будет происходить работа, можно командой:

# ansible-playbook --list-host

где – путь к вашему playbook (playbooks/setup_nginx.yml).

  • tasks: Задачи. Все playbooks содержат задачи.

Задача — это список действий, которые вы хотите выполнить. Поле задачи содержит имя задачи (справочная информация о задаче для пользователя playbook), модуль, который должен быть выполнен и аргументы, требуемые для модуля. Параметр «name» может добавляться опционально, но, в целом,  рекомендуемый.

10. Пример сценария.

В этом примере первое воспроизведение предназначено для web-серверов, а второе — для серверов баз данных:

Пример сценария:

Кликните мышкой для просмотра...
---
- name: update web servers
  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

- name: update db servers
  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

11. Практические примеры плейбуков.

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

Ссылка: «Ansible: Часть 4. Практические примеры плейбуков.»

12. Запуск плейбуков.

Чтобы запустить плейбук и выполнить все определенные в нем задачи, используйте команду ansible-playbook:

# ansible-playbook myplaybook.yml

Чтобы перезаписать в плейбуке опцию hosts по умолчанию и ограничить выполнение определенной группой или узлом, включите в команду опцию -l:

# ansible-playbook -l server1 myplaybook.yml

13. Запрос информации о play.

Опция --list-tasks используется для перечисления всех задач, которые будут выполнены в play, при этом не внося никаких изменений на удаленные серверы:

# ansible-playbook myplaybook.yml --list-tasks

Точно так же можно запросить все узлы, которые будут затронуты выполнением play, без запуска каких-либо задач на удаленных серверах:

# ansible-playbook myplaybook.yml --list-hosts

Вы можете использовать теги, чтобы ограничить выполнение play.

Чтобы вывести список всех тегов, доступных в play, используйте параметр --list-tags:

# ansible-playbook myplaybook.yml --list-tags

14. Управление выполнением плейбука.

Вы можете использовать опцию --start-at-task, чтобы определить новую точку входа вашего плейбука. Затем Ansible пропустит все, что предшествует указанной задаче, выполнив оставшуюся часть play с заданного момента.

Эта опция в качестве аргумента требует правильное имя задачи:

# ansible-playbook myplaybook.yml --start-at-task="Set Up Nginx"

Чтобы выполнять только задачи, связанные с конкретными тегами, вы можете использовать опцию --tags.

Например, если вы хотите выполнить только задачи, помеченные как nginx или mysql, вы можете использовать:

# ansible-playbook myplaybook.yml --tags=mysql,nginx

Если вы хотите пропустить все задачи, которые находятся под определенными тегами, используйте --skip-tags.

Следующая команда будет выполнять myplaybook.yml, пропуская все задачи, помеченные как mysql:

# ansible-playbook myplaybook.yml --skip-tags=mysql

15. Настройка защищенных плейбуков.

Если ваши плейбуки Ansible содержат конфиденциальные данные, такие как пароли, ключи API и учетные данные, важно обеспечить их безопасность с помощью шифрования. Ansible предоставляет ansible-vault для шифрования файлов и переменных.

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

Ссылка: «Ansible: Часть 5. Настройка защищенных плейбуков.»

16. Оригиналы источников информации.

  1. selectel.ru «Система управления конфигурацией Ansible».
  2. dmosk.ru «Инструкция по установке и запуску Ansible на CentOS».
  3. dmosk.ru «Что такое ansible».
  4. 8host.com «Как работать с Ansible: простая удобная шпаргалка».
  5. habr.com «Автоматизируем и ускоряем процесс настройки облачных серверов с Ansible. Часть 1: Введение».
  6. kamaok.org.ua «Установка и использование Ansible на Centos7».

Читайте также: