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

Что такое роли

Роль в Ansible — набор задач или обработчик переменных, файлов и других артефактов, которые распространяются и подключаются как единое целое к плейбуку. Обычно она отвечает за высокоуровневые задачи: установку баз данных, веб-серверов и др. Но иногда может использоваться для автоматизации работы с каким-то низкоуровневым сервисом, который не встроен в Ansible.

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

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

«DevOps Tools для разработчиков»

Создание роли

Чтобы Ansible смог найти и использовать роли, нужна специально разработанная структура каталогов. Создадим каталог с именем roles:

cd ~
mkdir roles
cd roles

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

Создадим каталог Apache для нашей роли и заполним его каталогами:

mkdir apache
cd apache

Затем с помощью команды mkdir создадим необходимый набор подкаталогов:

mkdir defaults files handlers meta templates tasks vars

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

В зависимости от сложности выполняемых задач роли может использовать один или несколько каталогов. Что представляют собой каталоги:

  • defaults: позволяет устанавливать переменные по умолчанию для включенных или зависимых ролей.

  • files: содержит статические файлы и файлы сценариев, которые могут быть скопированы на удалённый сервер или выполнены на нём.

  • handlers: все обработчики, которые ранее были в вашем плейбуке, теперь могут быть добавлены в каталог.

  • meta: для метаданных роли, которые используются для управления зависимостями. Например, вы можете определить список ролей, которые должны быть применены до вызова текущей роли.

  • templates: для шаблонов, которые генерируют файлы на удалённых хостах. 

  • tasks: содержит один или несколько файлов с задачами, которые определяются в разделе tasks обычного плейбука Ansible. Эти задачи могут напрямую ссылаться на файлы и шаблоны, содержащиеся в соответствующих каталогах внутри роли, без необходимости указывать полный путь к файлу.

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

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

Превратим плейбук Apache в роль для более эффективной организации. Поскольку структура roles/apache2/{subdirectories} уже настроена, создадим несколько YAML-файлов. 

Файл задач main.yml

Начнем с подкаталога tasks. Перейдите в каталог:

cd ~/roles/apache/tasks

В нём нужно создать основной файл.yml и наполнить его содержимым плейбука Apache:

nano main.yml

Когда вы начнёте, файл будет выглядеть так:

Нам нужно сохранить только первую строку --- и выделенные строки в разделе «Задачи». Удалим посторонние пробелы слева от наших задач и добавим раздел для включения модуля Apache под названием modsecurity. После этих изменений новый файл ~/roles/apache/tasks/main.yml будет выглядеть следующим образом:

Теперь файл tasks проще понимать, потому что он содержит только фактические шаги, которые будут выполняться при использовании роли Apache.

Обратите внимание, что src=index.html и src=vhost.tpl используются для ссылок на файлы в роли без какого-либо предшествующего пути. Структура каталогов позволяет ссылаться на файлы и шаблоны непосредственно по их названию — Ansible найдёт их автоматически.

Сохраните и закройте файл, когда закончите редактирование.

Файл с обработчиками событий main.yml

Когда у нас есть основная часть плейбука в файле tasks/main.yml, нужно переместить раздел обработчиков в файл, расположенный по адресу handlers/main.yml.

Перейдите в подкаталог handlers:

cd ~/roles/apache/handlers

Откройте файл в текстовом редакторе и вставьте содержимое оригинального playbook.yml:

nano main.yml

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

Удалим лишние пробелы, чтобы файл выглядел так:

Сохраните и закройте файл, когда закончите.

Добавление файлов и шаблонов

Следующий шаг — проверка наличия файла index.html и шаблона vhost.tpl. Поскольку мы ссылаемся на них в файле tasks/main.yml, они должны существовать, иначе Ansible не сможет правильно запустить роль.

Создадим файл index.html в каталоге ~/roles/apache/files:

cd ~/roles/apache/files
nano index.html

Вставим в редактор следующие строки:

Сохраните изменения и закройте его.

Перейдём к редактированию шаблона. Для этого откройте каталог шаблонов и введите команду nano:

cd ~/roles/apache/files
nano index.html

Вставьте эти строки в редактор, затем сохраните и закройте его:

Мета каталог

В созданной роли Apache нам не нужны никакие зависимости. Однако в гипотетическом случае, если бы наша роль зависела от другой роли (apt), мы могли бы добавить в мета каталог файл main.yml. Он бы выглядел так:

Это бы гарантировало запуск роли apt перед нашей ролью Apache. Создание подобных зависимостей полезно с более сложными ролями, которые требуют наличия других частей программного обеспечения или конфигурации перед запуском фактической роли.

Каталог vars

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

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

Однако каталог vars всё же стоит упомянуть, потому что он полезен для сложных ролей. Например, если роли необходимо поддерживать различные дистрибутивы Linux, указание значений по умолчанию для переменных может быть полезно для обработки различных имен пакетов, версий и конфигураций.

Другие файлы

Когда вы создаёте роли с большим количеством задач, зависимостей или условной логики, они становятся большими и трудными для понимания. В подобных ситуациях лучше разделить задачи на их собственные файлы и включить в tasks/main.yml.

Скажем, если бы у нас был дополнительный набор задач по настройке TLS для нашего сервера Apache, мы могли бы выделить их в отдельный файл — вызвать файл tasks/tls.yml и включить его в файл tasks/main.yml:

Работа с плейбуком

Мы настроили структуру ролей и теперь можем использовать плейбуки для управления сервером без необходимости повторного создания задач. 

Создадим плейбук:

cd ~
nano playbook.yml

Теперь откройте файл и вставьте эти строки:

Сначала мы перечисляем серверы, на которых хотим запустить роль — для этого используем hosts: all. Затем мы объявляем роли. В данном случае роль одна — apache. Это весь план действий — он прост, быстро читается и понимается. Поддержание такого порядка в плейбуках позволяет сосредоточиться на общих целях настройки серверов, а не на механизме выполнения отдельных задач. 

Ansible Galaxy

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

Давайте познакомимся с инструментом ansible-galaxy. Проведём поиск по Galaxy и выберем подходящую роль из списка:

ansible-galaxy search "PHP for RedHat/CentOS/Fedora/Debian/Ubuntu"

Команда поиска выведет нечто подобное:

Предположим, мы выбрали роль geerlingguy.php. Чтобы загрузить её в наш плейбук, используем команду ansible-galaxy install:

ansible-galaxy install geerlingguy.php

После запуска вы команды вы увидите: 

Теперь можем добавить роль в файл playbook.yml:

Запуск ansible-playbook playbook.yml с добавленной ролью Galaxy приведет к следующему результату:

Коротко о главном

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

«DevOps Tools для разработчиков»

Больше об Ansible

Тех, кто хочет научиться управлять серверами и автоматизировать задачи с помощью Ansible, мы приглашаем на наш курс  «Ansible: Infrastructure as Code», который пройдет с 23 января по 19 февраля.

Комментарии (4)


  1. Yusmit
    21.12.2022 19:08
    +2

    стесняюсь спросить а почему мы сразу не использовали утилиту ansible-galaxy для инициализации роли, а городили огород?

    mkdir defaults files handlers meta templates tasks vars


  1. FlyingDutchman
    21.12.2022 20:34
    +2

    Статья про роли хорошая.

    P.S. Надо было написать во вчерашней статье, что продолжение следует, народ бы не возмущался.


  1. onegreyonewhite
    22.12.2022 06:54
    +1

    Что про vars вы какую-то сложную ерунду написали. Каталог vars в себе содержит переменные константы, в то время как defaults содержит переменные, которые можно переопределять для роли. Тогда уже понятно, что в константы можно вынести портянки с вхардкоженными списками пакетов, которые нужно поставить, а в defaults - детали конфигурации, которые можно будет изменить при запуске роли.

    Ничего не написали про то, что во всех этих директориях main.yaml является точкой входа, что часто путает новичков, создающих файлы по своему усмотрению.

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


  1. b0r0dat0r
    22.12.2022 13:26

    Почему не обновить список пакетов и не установить апач в один шаг?

    - name: Update package repositories and install apache
    ansible.builtin.apt:
    name: apache2
    state: latest
    update_cache: yes