Baserow HA - отказоустойчивая no-code база данных
Почему этот продукт
Baserow не кластеризуется сам. Одна ВМ со встроенной базой данных — единая точка отказа, а собрать отказоустойчивую установку вручную означает самостоятельно подключить внешние PostgreSQL и Redis, объектное хранилище, балансировщик, TLS и единственный планировщик, а потом поддерживать их согласованность. Продукт делает эту работу и даёт развёртывание, которое переживает отказ зоны доступности.
- На узлах нет постоянных данных. База приложения — в кластере Managed Service for PostgreSQL, кэш и брокер задач — в кластере Managed Service for Redis (Valkey), загруженные файлы и экспорты — в бакете Object Storage. Узлы приложения заменяемы по замыслу.
- Три зоны и настоящий кворум. Оба управляемых кластера создаются с тремя хостами, по одному в каждой зоне доступности, а узлы приложения и воркеров распределены по двум зонам за сетевым балансировщиком. Отказ одной зоны оставляет каждому кластеру кворум, а сервис — доступным.
- Эндпоинты следуют за мастером. Узлы обращаются к обоим кластерам по FQDN кластера для чтения и записи, поэтому смена мастера прозрачна для приложения. Это подтверждено приёмочным тестом, который повышает реплику в обоих кластерах и затем выполняет запись.
- Планировщик всегда ровно один. Celery beat должен работать один на установку, иначе периодические задачи дублируются. Демон-лидер удерживает advisory-lock в PostgreSQL и запускает beat только на том узле, который его держит; при отказе узла сосед перехватывает лидерство за секунды и второй beat не появляется.
- Секреты в Lockbox, а не в полях формы. Пароли базы данных и Redis, ключ подписи Django — это секреты Lockbox, которые вы выбираете или создаёте при развёртывании. В метаданных ВМ лежат только идентификаторы секретов; bootstrap читает значения при первом запуске по краткоживущим IAM-токенам из сервиса метаданных, без единого файла-ключа сервисного аккаунта.
- Первый запуск без интернета. Образ содержит образы контейнеров Baserow и Caddy, поэтому узел настраивается и запускает стек, ничего не скачивая при загрузке.
Полное описание
Baserow HA разворачивает Baserow на Ubuntu 24.04 в виде двух узлов приложения и двух узлов воркеров, со всем постоянным состоянием в управляемых сервисах Yandex Cloud. Каждый узел приложения запускает backend Baserow на gunicorn, веб-фронтенд Nuxt и обратный прокси Caddy, который терминирует TLS и направляет трафик API, WebSocket и ассистента на backend, а остальное — на фронтенд. Каждый узел воркеров запускает воркеры Celery, и ровно на одном из них работает планировщик Celery beat. Сетевой балансировщик публикует узлы приложения на порту 443 с проверкой состояния по TCP; узлы воркеров публично недоступны.
Слой состояния — трёххостовый кластер Managed Service for PostgreSQL и трёххостовый кластер Managed Service for Redis (Valkey), по одному хосту в каждой зоне доступности, плюс бакет Object Storage для загруженных файлов и экспортов. Узлы обращаются к кластерам по имени кластера для чтения и записи, поэтому при повышении другого хоста приложение следует за ним без перенастройки.
Celery beat, планировщик периодических задач, должен работать ровно один на установку, иначе задачи выполняются несколько раз. Демон-лидер на каждом узле воркеров удерживает сессионный advisory-lock в PostgreSQL и запускает контейнер beat только пока держит этот лок. Когда узел-держатель останавливается, лок перехватывает сосед и запускает beat; когда прежний держатель возвращается, он остаётся пассивным. Планировщик всегда один.
При первом запуске bootstrap читает параметры развёртывания из метаданных ВМ, забирает учётные данные из выбранных вами секретов Lockbox, формирует окружение Baserow и конфигурацию Caddy, дожидается доступности PostgreSQL и Redis и запускает стек из заранее загруженных образов. После этого он отключает себя, поэтому перезагрузка никогда не повторяет первичную настройку.
Форма запрашивает только то, что должен решить оператор: префикс имени, три подсети, SSH-ключ и сети, которым разрешён доступ по нему, публичный URL, класс хранилища для загружаемых файлов, размер развёртывания и секреты Lockbox с учётными данными. Размеры, версии, число воркеров, порты и размеры дисков зафиксированы на протестированных значениях.
Ключевые возможности
- Два узла приложения и два узла воркеров в двух зонах доступности за сетевым балансировщиком на порту 443.
- Трёххостовый Managed Service for PostgreSQL 16 и трёххостовый Managed Service for Redis (Valkey) 7.2, по одному хосту в зоне.
- Object Storage для загруженных файлов и экспортов, с выбором стандартного или умного класса хранилища с автоматическим перемещением объектов.
- Единственный Celery beat, выбираемый через advisory-lock в PostgreSQL, с автоматическим перехватом.
- TLS терминируется Caddy на каждом узле, с вашим сертификатом из Lockbox или самоподписанным.
- Все учётные данные — секреты Lockbox; в метаданных только идентификаторы.
- Доступ по SSH к каждому узлу для пользователя
ubuntu, ограниченный указанными вами сетями. - Сервисный аккаунт ровно с двумя ролями: редактор объектного хранилища и чтение payload Lockbox.
Архитектура
| Компонент | Размещение | Роль |
|---|---|---|
| Узел приложения A / B | зоны A и B | Caddy (TLS, 443), backend Baserow (gunicorn), веб-фронтенд Nuxt |
| Узел воркеров A / B | зоны A и B | Celery worker, Celery export worker и единственный Celery beat |
| Сетевой балансировщик | регион | Публикует 443, проверка по TCP, целями являются только узлы приложения |
| Managed PostgreSQL | зоны A, B и D | База приложения, три хоста, один мастер и две реплики |
| Managed Redis (Valkey) | зоны A, B и D | Кэш и брокер Celery, три хоста |
| Бакет Object Storage | регион | Загруженные файлы и экспорты |
| Lockbox | регион | Учётные данные базы, Redis и Django, сгенерированный ключ хранилища, необязательный TLS-сертификат |
Что создать перед развёртыванием
Создайте в каталоге развёртывания три секрета Lockbox. В каждом одна запись, из которой развёртывание читает значение:
| Секрет | Ключ записи | Значение |
|---|---|---|
| Пароль PostgreSQL | password |
Сгенерируйте в консоли |
| Пароль Redis | password |
Сгенерируйте в консоли |
| Ключ подписи Django | secret-key |
Сгенерируйте в консоли, не менее 50 символов |
По желанию создайте четвёртый секрет с вашим TLS-сертификатом в записях tls-cert (полная цепочка, PEM) и tls-key (закрытый ключ, PEM). Если оставить поле TLS пустым, каждый узел будет отдавать самоподписанный сертификат, о чём браузеры будут предупреждать.
Также понадобятся три подсети в одной сети VPC, по одной в каждой зоне доступности, и публичное DNS-имя, которое после развёртывания вы направите на адрес балансировщика.
Как создать секреты
Через CLI Yandex Cloud, в каталоге, куда разворачиваете:
yc lockbox secret create --name baserow-db-password \
--payload '[{"key":"password","text_value":"'"$(openssl rand -hex 24)"'"}]'
yc lockbox secret create --name baserow-redis-password \
--payload '[{"key":"password","text_value":"'"$(openssl rand -hex 24)"'"}]'
yc lockbox secret create --name baserow-secret-key \
--payload '[{"key":"secret-key","text_value":"'"$(openssl rand -base64 48)"'"}]'
Пароли базы и Redis генерируются в шестнадцатеричном виде намеренно: эти значения попадают в строку подключения, где символы вроде @, : и / ломают разбор. Ключ подписи Django читается только как переменная окружения, поэтому годится любое длинное случайное значение.
По желанию, для исходящей почты и своего сертификата:
yc lockbox secret create --name baserow-smtp-password \
--payload '[{"key":"password","text_value":"<пароль релея>"}]'
yc lockbox secret create --name baserow-tls \
--payload '[{"key":"tls-cert","text_value":"<полная цепочка PEM>"},{"key":"tls-key","text_value":"<закрытый ключ PEM>"}]'
При использовании Yandex Postbox паролем релея служит СЕКРЕТ API-ключа с областью действия yc.postbox.send, а пользователем SMTP — идентификатор этого ключа (aje...). Статический ключ доступа (YCAJE...) — другой тип учётных данных, релей отклоняет его с ошибкой 535 Authentication credentials invalid.
В консоли: Lockbox -> Создать секрет -> добавьте одну запись «ключ/значение», используя точно тот ключ записи, что указан в таблице выше. Другое имя ключа приведёт к тому, что развёртывание остановится на первой загрузке, а не запустится с учётными данными, которые не может прочитать. Затем выберите каждый секрет в соответствующем поле формы развёртывания.
Параметры развёртывания
| Параметр | Виджет | Примечание |
|---|---|---|
| Префикс имени ресурсов | текст | От 3 до 24 символов: строчные латинские буквы, цифры и дефисы, начиная с буквы |
| Подсеть VPC в зоне A / B / D | выбор подсети | По одной в зоне, все в одной сети. В зоне D размещаются только третьи хосты кластеров |
| Публичный SSH-ключ для доступа к ВМ | текст | Формат OpenSSH; даёт доступ пользователю ubuntu на всех четырёх узлах |
| CIDR, которым разрешён SSH | список | Для продакшена ограничьте своим адресом; по умолчанию разрешены все |
| Публичный URL Baserow | текст | https://ваш.домен; задаёт хост TLS и ссылки, которые формирует приложение |
| Класс хранилища для файлов | список | Стандартное или Умное с автоматическим перемещением, если файлы читают редко |
| SMTP: хост релея | текст | Необязательно. Без него почта не доставляется: сброс пароля и приглашения ни до кого не дойдут |
| SMTP: порт | текст | 587 для STARTTLS, 465 для неявного TLS |
| SMTP: пользователь | текст | Необязательно; оставьте пустым, если релей принимает отправку без аутентификации |
| SMTP: адрес отправителя | текст | Например baserow@example.com |
| Секрет Lockbox: пароль SMTP | выбор секрета | Запись password; обязателен, если задан пользователь SMTP |
| Размер развёртывания | список | Production или Development; меняет только классы хостов и диски, но не топологию |
| Секрет Lockbox: пароль PostgreSQL | выбор секрета | Запись password |
| Секрет Lockbox: пароль Redis | выбор секрета | Запись password |
| Секрет Lockbox: Django SECRET_KEY | выбор секрета | Запись secret-key |
| Секрет Lockbox: TLS-сертификат | выбор секрета | Необязательно; записи tls-cert и tls-key |
Спецификации ВМ
| Размер развёртывания | Узлы приложения и воркеров | Managed PostgreSQL | Managed Redis (Valkey) |
|---|---|---|---|
| Production | 4 vCPU (100 процентов), 8 ГБ ОЗУ, 30 ГБ network SSD | s3-c2-m8, 20 ГБ network SSD, три хоста |
hm3-c2-m8, 16 ГБ network SSD, три хоста |
| Development | 2 vCPU (50 процентов), 4 ГБ ОЗУ, 30 ГБ network HDD | c3-c2-m4, 20 ГБ network HDD, три хоста |
b3-c1-m4, 16 ГБ network SSD, три хоста |
Оба размера создают одни и те же четыре ВМ и одни и те же трёххостовые кластеры. Development дешевле в расчёте на хост и использует предварительный канал обновлений; он предназначен для ознакомления, а не для рабочих данных.
После развёртывания
Направьте своё DNS-имя на адрес балансировщика, показанный на странице приложения, откройте https://ваш.домен и создайте первую учётную запись. Созданная первой учётная запись становится администратором установки.
При первом запуске backend выполняет первичную миграцию базы под локом, поэтому примерно три минуты после старта узлов сайт отвечает ошибкой. Дождитесь, пока https://ваш.домен/api/_health/ вернёт OK, и только затем начинайте работу.
Для обслуживания подключайтесь к любому узлу как ubuntu с указанным вами ключом. Стек находится в /opt/baserow, управляется Docker Compose, журналы доступны через journalctl -u baserow-bootstrap и docker compose logs.
Порты
| Порт | Направление | Источник | Назначение |
|---|---|---|---|
| 443 | входящий | любой | HTTPS к приложению, терминируется Caddy на каждом узле |
| 443 | входящий | проверки состояния балансировщика | Проверка узлов приложения по TCP |
| 22 | входящий | указанные вами блоки CIDR | Доступ по SSH для обслуживания |
| все | внутренний | три подсети | Узлы приложения к управляемым кластерам |
-
Замена общих электронных таблиц
- Один источник данных вместо файлов, разосланных копиями
- Права доступа на уровне рабочего пространства и история изменений каждой строки
- Представления сетки, канбана, календаря, галереи и формы поверх одной таблицы
-
Внутренний реестр или несложная CRM
- Собирается из интерфейса, без разработки
- Связи между таблицами, формулы, фильтры и сортировка
- Вложения хранятся в Object Storage, а не на узле
-
Бэкенд для собственного приложения
- Тот же REST API, которым пользуется интерфейс, с токеном базы по таблицам
- Создание, чтение, изменение и удаление строк по заголовку
Authorization: Token <...> - Интерактивный справочник отдаёт сама установка по адресу
/api/redoc/
-
Приём заявок через форму
- Публичное представление формы пишет прямо в таблицу
- Вебхуки уведомляют ваши системы о событиях
rows.createdи других - Уведомления и приглашения по почте при заполненных полях SMTP
-
Регулярная передача данных в другие системы
- Выгрузка в CSV по требованию или из скрипта через API
- Выгрузка выполняется на выделенных рабочих узлах, а не на обслуживающих интерфейс
- Результат складывается в Object Storage и забирается по ссылке
OpenNix осуществляет техническую поддержку пользователей в Yandex Cloud. Вы можете связаться с технической поддержкой по электронной почте support@opennix.ru. Время работы технической поддержки с 9:00 до 18:00 (МСК) по рабочим дням.
| Тип ресурса | Количество |
|---|---|
| Права доступа к каталогу | 2 |
| Бакет Object Storage | 1 |
| Версия секрета Lockbox | 1 |
| Секрет Lockbox | 1 |
| Статический ключ доступа сервисного аккаунта | 1 |
| Сервисный аккаунт | 1 |
| База данных PostgreSQL | 1 |
| Пользователь PostgreSQL | 1 |
| Кластер PostgreSQL | 1 |
| Виртуальные машины | 4 |
| Сетевой балансировщик NLB | 1 |
| Целевая группа NLB | 1 |
| Кластер Redis | 1 |
| Группа безопасности VPC | 1 |