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

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




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




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




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




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







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




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




# ansible-playbook --list-host




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







Задача — это список действий, которые вы хотите выполнить. Поле задачи содержит имя задачи (справочная информация о задаче для пользователя 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».
  7. Источник: https://hamsterden.ru/ansible-playbooks/






2021-09-01T12:08:50
Software