Привет, Хабр! Продолжу серию третьей статьей об эффективном использовании Ansible для развертывания больших инфраструктур в компаниях. В этом тексте я расскажу, какую архитектуру приложения на основе Ansible мы сформировали, и остановлюсь на модулях Deployer и Inventory.
Техническое задание
Задача стояла все та же — быстро развертывать любую цифровую инфраструктуру, что включает:
быстрое конфигурирование
быстрое развертывание
быструю разработку
длительную поддержку старого кода
интеграцию с внешними системами
Архитектурное решение
Поработав с монолитом, мы выявили следующие проблемы: вносить изменения и искать ошибки долго, сложно выполнять непрерывную поставку кода, контролировать качество развернутой инфраструктуры. Стандартного способа с ролями и коллекциями было недостаточно.
Было принято решение:
Вынести Inventory в отдельный модуль.
Вынести A-service в отдельные модули.
Создать модуль запуска развертывания — Deployer.
Зафиксировать точки входа и выхода для внешних служебных сервисов.
Получилась следующая схема:

Deployer — модуль запуска контейнеров для развертывания инфраструктуры.
Запускает модуль Inventory нужной версии;
Запускает модули A-service, указанные в Inventory.
Inventory — кодовая база Ansible inventory. На вход получает YAML-файл с конфигурацией инфраструктуры (который мы рассматривали ранее) и возвращает скоуп переменных, используемых модулями A-service.
Services (A-service) — модуль развертывания игровых сервисов на полигоне. Получает всю информацию из Inventory: данные о платформе, внешних сервисах, инвентаризации. Используя эти сведения, устанавливает сервис.
Как это нам помогло
При отделении Inventory от A-service мы получили:
Изменение YAML-файла конфигурации перестало влиять на A-service. Можем отдельно дорабатывать основные параметры инфраструктуры. Это позволяет быстро оптимизировать YAML-файл для ускорения конфигурирования.
A-service можно разрабатывать отдельно, получая на вход зафиксированные переменные от Inventory. Это позволяет:
искусственно ограничить сквозное использование переменных Ansible, что ускоряет поиск ошибок и разработку (внутренние переменные Inventory перестают влиять на переменные A-service);
быстро разрабатывать новые A-service, получая на вход задекларированные переменные, имея отдельный репозиторий (как следствие — быстрый merge, легкое встраивание в процесс разработки);
управлять запуском выбранных A-service в нужной последовательности через Deployer;
поставлять заказчику не код, а контейнер, что в разы повышает надежность развертывания (все для установки и настройки уже лежит в контейнере);
использовать разные версии ПО в разных A-service (Ansible, Python).
Появление отдельного модуля Deployer позволяет управлять последовательностью развертывания, а также легко развивать его и оптимизировать.
Минусы (как же без них)
Появилось очень большое количество репозиториев, которые нужно контролировать.
Давайте подробно остановимся на модулях Inventory и Deployer.
Модуль Inventory
Inventory — модуль инвентаризации инфраструктуры на основе Ansible inventory. Особенность модуля в том, что он запускается в отдельном контейнере и отдает на выход папку с Ansible inventory. Это позволяет подключать любые A-service для развертывания, в том числе параллельно.
В Inventory мы настраиваем:
Основной YAML-файл конфигурации.
Параметры платформы (VMware vSphere, OpenStack, различные облака).
Параметры внешних сервисов (зеркала, артефакторий, Git, HashiCorp Vault и т.п.).
На выходе получаем папку формата Ansible inventory c формализованным скоупом переменных для использования в A-service.
Хочется заметить, что в контейнер Inventory также можно встроить валидаторы входных данных для проверки доступности внешних сервисов, но здесь мы их рассматривать не будем.

Модуль Deployer
Deployer — модуль запуска контейнеров для развертывания инфраструктуры. Основной сценарий работы Deployer:
запустить контейнер Deployer + Inventory;
сформировать список всех A-service, которые есть в Inventory;
скачать (в примере — из GitLab) A-service нужных версий по списку;
сформировать последовательность запуска A-service (это, пожалуй, самая важная функция модуля);
запустить выбранные A-service в нужном порядке с информацией о пути к Inventory.
Далее A-service сам возьмет из Inventory то, что нужно, и установит заложенный сценарий.

Итог
Сформирована быстрая и независимая разработка компонентов.
Ansible и системные компоненты обновляются независимо и с минимальными затратами.
Значительно ускорилась реакция на потребности бизнеса в больших изменениях (вариабельность инфраструктур, сервисов большой связности в инфраструктуре, изменение состава внешних сервисов интеграции).