Кастомный бандл ADCM: управление Bacula через веб‑интерфейс

Всем привет! Я Владимир Елагин, технический руководитель проекта Arenadata Cluster Manager (ADCM). В этой статье я хочу рассказать, как с помощью open-source продукта ADCM можно автоматизировать развертывание и управление практически любым программным обеспечением, даже если вы не используете другие продукты компании Arenadata. Для этого рассмотрим, как написать бандл для установки Bacula — open-source системы резервного копирования.
Данная статья обзорная, она предназначена для того, чтобы познакомить с базовыми понятиями ADCM. Подробная инструкция по написанию своего бандла приведена в документации ADCM. Если у Вас возникнут вопросы, Вы можете обратиться в сообщество ADCM.

Что такое ADCM?
ADCM представляет собой веб-приложение на Django в Docker-контейнере с графическим интерфейсом для управления объектами инфраструктуры. Действия над объектами представляют собой Ansible-playbook: вы можете запускать их с нужными параметрами на выбранных хостах в любой момент без обращения к командной строке. Для установки и развертывания программного обеспечения ADCM использует бандл — специальный архив, который содержит описание объектов ADCM.
К объектам ADCM относится кластер, который включает в себя набор сервисов, при этом сервис может представлять собой либо единичную сущность, либо логическую сущность, объединяющую в себе несколько компонентов.
Каждый объект ADCM может иметь собственную конфигурацию и набор действий.
Бандл: что это и из чего состоит
Бандл (bundle) — это инструкция для ADCM о том, как развернуть и управлять каким-либо сервисом или кластером. Это архивный файл в формате .tgz, который вы загружаете в ADCM. После загрузки бандла в интерфейсе ADCM на его основе можно создать один или несколько кластеров.
Внутри бандла обязательно есть два основных компонента:
Конфигурационный файл
config.yaml— это описание структуры вашего кластера. Фактически он работает как шаблон для объектов: вы описываете структуру объектов, действия над ними, а ADCM генерирует соответствующие элементы управления в веб-интерфейсе.Ansible-playbook — набор действий, приводящих хост к некому конечному состоянию: установка пакетов, копирование файлов, запуск сервисов.
Важно: В рамках этой статьи мы не будем рассматривать написание Ansible playbook — это отдельная большая тема. Мы сосредоточимся на том, как устроен
config.yaml, как его параметры влияют на отображение в интерфейсе и как с его помощью решать задачи управления инфраструктурой.
Что такое прототип и зачем он нужен?
Все объекты, которыми можно управлять из ADCM, описываются в файле config.yaml в виде прототипов.
В продуктовом бандле такими объектами могут быть:
Прототип кластера — описывает кластер в целом.
Прототип сервиса — описывает отдельный сервис внутри кластера.
Прототип компонента — описывает компонент сервиса, который может быть размещен на хосте.
Самый простой прототип кластера выглядит следующим образом:
- name: Test_cluster
type: cluster
version: 1
adcm_min_version: 2.12.0
contract_version: "2.1"
venv: "2.16"Подробное описание всех свойств в файле config.yaml можно найти в документации ADCM, я остановлюсь только на обязательных:
name— уникальное наименование прототипа.type— тип прототипа (cluster,service,component).version— версия прототипа.adcm_min_version— минимальная версия ADCM, которая необходима для работы бандла. Указывается только для прототипаcluster.contract_version— версия контракта в бандле, в соответствии с которой составлен конфигурационный файлconfig.yaml. Указывается только для прототипаcluster.venv— версия Ansible для выполнения Ansible playbook. Указывается только для прототипаcluster.
Запускаем действия
Прототип описывает объект, но сам по себе не выполняет никаких действий. Чтобы пользователь мог взаимодействовать с объектом, в прототипе описываются actions - действия, которые ADCM может выполнить над ним.
actions:
Install:
display_name: "Install"
scripts:
- name: "Install"
script_type: ansible
script: ansible/install.yaml
states:
available: anyInstall- уникальное наименование действия.display_name- наименование действия, отображаемое в интерфейсе.scripts- список скриптов, которые будут выполнены.name- наименование выполняемого скрипта, отображаемое в интерфейсе.script_type- тип скрипта (ansible/internal).script- путь до файла Ansible playbook внутри бандла.
states- состояния кластера, в которых доступно данное действие.Полный список свойств для описания действий можно найти в документации ADCM.
После запуска действия ADCM сформирует inventory-файл на основе текущей топологии кластера. В этом файле будут указаны все объекты с параметрами, к которым можно обращаться из Ansible playbook.
Более подробно о том, как происходит запуск действия, можно почитать здесь.
После загрузки такого бандла в интерфейсе ADCM появится соответствующее действие:

Добавляем кастомные параметры
Очень часто при запуске действия возникает потребность использовать параметры, которые ввел пользователь. Для этого используется специальный блок config:
config:
- name: postgresql_user
display_name: Username
description: "Database username for Bacula catalog connection"
type: string
default: "bacula"
- name: postgresql_password
display_name: Password
description: "Password for the Bacula database user"
type: password
- name: postgresql_dbname
display_name: Database name
description: "Name of the PostgreSQL database for Bacula catalog"
type: string
default: "bacula"где:
name- уникальное наименование параметра.display_name- наименование параметра, которое отображается в интерфейсе.description- описание параметра.type- тип параметра. От выбора типа зависит способ отображения в интерфейсе.default- значение по умолчанию.
Указанные параметры конфигурации будут доступны в inventory-файле и к ним можно обращаться из Ansible playbook указав {{ vars.service.postgresql.config.postgresql_user }}, где:
vars- наименование блока переменных в inventory-файле.service- тип прототипа, в котором располагается конфигурация.postgresql- наименование прототипа.config- наименование блока конфигурационных параметров.postgresql_user- наименование параметра конфигурации.
Полный список свойств параметров можно найти в документации ADCM.
В интерфейсе ADCM это будет выглядеть следующим образом:

Практика: создаём бандл для Bacula
Bacula — это система резервного копирования, которая состоит из четырёх компонентов: база данных (postgresql), управляющий сервис (director), хранилище (storage) и агенты (client) на клиентских машинах. Поэтому для развертывания кластера Bacula потребуется:
Описать прототип кластера.
Описать прототип каждого сервиса (postgresql, director, storage, client).
Описать конфигурацию сервисов.
Описать действия над кластером.
Описываем прототипа кластера
Для того чтобы в ADCM появился новый кластер, необходимо в файле config.yaml указать его прототип. Для прототипа кластера Bacula составим следующее описание:
- name: Bacula
display_name: Bacula
type: cluster
version: 15.0.3_63
contract_version: "2.1"
edition: community
adcm_min_version: 2.12.0
venv: "2.16"
После загрузки бандла у нас появится возможность создать кластер.
Описываем прототипа сервиса
Сервис представляет собой набор компонентов, которые определены в бандле продукта и не способны функционировать изолированно.
Сервисный прототип может содержать компоненты. Так как компонент сам считается прототипом, его описание тоже может содержать такие секции, как config и actions.
Чтобы не перегружать статью однотипными YAML - файлами, подробно разберем только сервис client. Остальные сервисы Bacula описываются по тому же принципу.
# Описание прототипа сервиса
- name: client
display_name: Client
type: service
required: true
description: "Bacula File Daemon service - agent installed on client hosts to provide file access for backup operations"
version: 1
# Описание компонентов сервиса
components:
client:
constraint: [1,+]
display_name: Client
# Описание конфигурационных параметров сервиса
config:
- name: Paths
type: list
description: "List of file system paths to include in backup for this client (e.g., /etc, /var/www, /home)"
group_customization: true
default:
- "/home/adcm"
# Описание действия над сервисом
actions:
Reconfig:
display_name: "Reconfig"
scripts:
- name: "Reconfig client"
script_type: ansible
script: ansible/reconfig_client.yaml
states:
available: any
on_success: installed
Все описанные в config.yaml сервисы можно добавить в кластер.
Здесь стоит обратить внимание на две важные особенности:
Блок
config— в нём определена переменная для хранения путей к директориям, которые необходимо включать в резервную копию.Блок
actions— в нём добавлено действие, которое синхронизирует значение этой переменной с сервисомdirector.

В результате сервис Client успешно добавлен в кластер: в его конфигурации присутствует параметр Paths, а также доступно действие Reconfig.
Описываем действие Install
Для того чтобы запустить установку, необходимо в прототип кластера добавить описание соответствующего действия. Для нашего примера это будет выглядеть следующим образом:
# Описание прототипа кластера
- name: Bacula
display_name: Bacula
type: cluster
version: 15.0.3_1
contract_version: "2.1"
edition: community
adcm_min_version: 2.12.0
venv: "2.16"
# Описание действия, которое можно выполнить над кластером
actions:
Install:
display_name: "Install"
scripts:
- name: Install Postgresql
script_type: ansible
script: ansible/install_postgresql.yaml
- name: Install Client
script_type: ansible
script: ansible/install_client.yaml
- name: Install Storage
script_type: ansible
script: ansible/install_storage.yaml
- name: Install Director
script_type: ansible
script: ansible/install_director.yaml
# Указание, в каких состояниях действие доступно пользователю
states:
available:
- created
on_success: installedВ интерфейсе данное действие будет выглядеть следующим образом:

После запуска установки можно перейти на страницу Jobs и увидеть, что были выполнены именно те скрипты, которые мы указали в config.yaml:

Управляем кластером Bacula
После установки Bacula необходимо предоставить пользователю инструменты для управления компонентами системы. Для этого следует описать соответствующие действия (actions).
Например, для получения списка активных заданий резервного копирования создадим action в файле config.yaml
List_jobs:
display_name: "List Jobs"
description: "Display all job categories: running, scheduled, terminated, disabled, and full history."
states:
available:
- installed
scripts:
- name: List Jobs
script_type: ansible
script: ansible/list_jobs.yaml
config:
- name: job_name
display_name: "Job Name"
description: "Filter results by job name. Leave empty to show all jobs."
type: string
required: false
pattern: "^[a-zA-Z0-9_-]+$"После добавления action в config.yaml он отобразится в интерфейсе ADCM и станет доступен для выполнения.

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

Из логов видно, что на расписании стоит одно задание backup_client_1_bacula-client-1. Реализуем Action, для его отключения:
Disable_Job:
display_name: "Disable Job"
states:
available:
- installed
on_success: installed
scripts:
- name: Disable Job
script_type: ansible
script: ansible/disable_job.yaml
config:
- name: job_name
display_name: "Job Name"
description: "Name of the backup job to disable"
type: string
required: true
pattern: "^[a-zA-Z0-9_-]+$"В интерфейсе ADCM появится форма с полем для ввода имени задания:

Успешное выполнение задания отобразится в логах:

Заключение
Мы создали собственный бандл, описали кластер Bacula, добавили сервисы с конфигурационными параметрами и связали действия ADCM с Ansible playbook. Это крошечная часть возможностей по кастомизации бандла. Полную информацию вы можете найти в документации ADCM.
Также у нас есть сообщество разработчиков бандлов! Полный бандл Bacula можно найти в репозитории нашего сообщества на GitHub.
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.