Для описания Ansible плэйбуков и ролей попробуем использовать UML-диаграммы. Ранее уже была предпринята попытка взглянуть на Ansible, как на некое подобие языка программирования под углом ООП, сейчас же проделаем подобное с помощью диаграмм классов UML.
Взаимосвязи ролей и плэйбуков изображаем в виде класс-диаграмм. Но для начала создаём пару новый стереотипов (stereotypes):
<<playbook>> для плэйбуков и <<role>> для ролей (при желании роли и плэйбуки можно даже в разные цвета стилями покрасить).
По именам ролей мы условились суффиксом (тот что до «/», у нас тут boo) обозначать принадлежность к определённой независимой системе.
Далее поговорим про методы наших «классов», зачем они нужны и вложенные роли.
Вероятно, в большинстве случаев вполне достаточно указать в плэйбуке роль по её имени. Это работает до тех пор, пока нам не важно из чего она состоит.
Как только появляется необходимость различать части роли, это должно найти отражение в сценариях Ansible. Можно либо «выкусывать» нужные части с помощью тэгов или переменных (variables), либо разделять роль на несколько ролей. Мы пойдём вторым путём, но чтобы подчеркнуть тесную связанность новых ролей, поместим их в папку с исходной. Получатся эдакие подроли.
Например, дерево ролей для boo/collector может выглядеть так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
> tree roles/boo/collector/ roles/boo/collector/ ├── api │ ├── install │ └── reconfigure ├── code │ ├── install │ ├── reconfigure │ └── update └── sys └── install 9 directories, 0 files > |
Тут мы выделили:
- sys — папку с ролями для установки системных пакетов, для чего требуются права суперюзера (в некоторых обстоятельствах root нам не доступен для этого и выделили эту подроль)
- code — папку с ролями для выливки кода из Git’а или ещё откуда-нибудь
- api — папку с ролями для установки и конфигурации WEB API. Завели отдельную роль, поскольку не все ноды использующие роль code должны иметь доступ через API
В нотации UML это могло бы выглядеть как:
где вложенные роли обозначаются методами.
Тот факт, что роль boo/collector да и все другие роли обладают неким поведением по-умолчанию описанным в tasks/main.yml, отображаем следующим образом:
Перейдём к переменным (variables), значения которым обычно указываются в yml-файлах директории group_vars.
Их можно было бы отображать в виде атрибутов наших «классов», типа:
Проанализируем, что-бы могло означать следующее:
Это могло бы означать, что роль boo/collector в meta/main.yml имеет упоминания других ролей: nginx (на конец-то знакомое слово!) и boo/common; и в файле с групповыми переменными необходимо указать значения переменным: boocollector_var1, boocollector_var2, boocollector_var3, nginx_config, boocommon_var1, boocommon_var2.
Возможность указывать значения по умолчанию, и как это выглядит в нотации UML, предлагается додумать самостоятельно.
Агрегацией (aggregation, да и composition) считается уместным указывать жёсткую связь ролей, каждая из которых отвечает за выполнение каких-либо задач по развёртыванию на том же сервере, что и другая.
Менее жёсткой связью можно указывать зависимости от ролей отвечающих за выкатывание софта на других серверах:
В принципе это уже чем-то дублирует Диаграмму Развёртывания (Deployment Diagram).
Ну, и на конец, рисуем картинку с плэйбуком:
К примеру, эта диаграмма могла бы выражать наше желание установить все сервисы, даже те, которые предназначены для работе на отдельных серверах в кластере, на одну ноду, в учётном файле (inventory) которая принадлежит группе test_vps.
Додумать, как мог бы быть отображён плэйбук, выкатывающий артефакты сразу на несколько групп серверов, предлагается факультативно. Я пока не придумал.
Таким образом, вполне не сложно заметить, что статическая структура системы развёртывания, построенной на Ansible, вполне сносно ложится на UML Диаграммы Классов (Class Diagram), и последние (диаграммы) могут быть использованы для документирования сложных процедур выкатки программных комплексов.
Было бы интересно узнать, как у вас происходит процесс моделирования-документирования процедур развёртывания.
До встречи.