Коротко. Бэкап RX это база с архивом журналов, файловое хранилище и конфигурация, лежащие вне продуктивной площадки. Раз в месяц из них реально поднимают контур и записывают время. Один алерт на возраст копии и состояние архива обязателен.

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

Симптом

До аварии симптомов нет, и это главная проблема. Косвенные признаки, что бэкап только числится:

  • на вопрос «за сколько поднимемся» никто не может назвать время, потому что не пробовали;
  • бэкапится только база данных, а тела документов лежат в файловом хранилище, которое «и так на другом сервере»;
  • бэкап делается pg_dump, при этом база уже сотни гигабайт;
  • каталог с бэкапами и каталог с данными на одной файловой системе или в одной виртуальной машине;
  • никто не знает, что произойдёт с базой, если архивирование журналов транзакций перестанет работать.

Почему так

Directum RX хранит данные в нескольких местах, и восстановиться можно только при согласованном наборе:

Что Где обычно лежит Без этого
База данных PostgreSQL ничего не поднимется
Тела документов и версии файловое хранилище: каталог, NFS, S3-совместимое хранилище карточки есть, содержимого нет
Полнотекстовый индекс Elasticsearch поиск не работает, пока индекс не перестроится; его можно не бэкапить, но время перестроения надо знать
Конфигурация сервисов, сертификаты, секреты серверы приложений восстановление превращается в переустановку

Про способы копирования базы. pg_dump это логическая копия: на большой базе он долгий, восстановление ещё дольше, и он даёт только точку «на момент запуска». Снимок виртуальной машины согласован «как после выключения питания»: PostgreSQL с него поднимется, но это тоже одна точка в сутки, и снимок обычно живёт на той же площадке. Ни то, ни другое не даёт ответа «вернуться на 14:37, за минуту до того, как массовая операция испортила данные».

Это даёт только физический бэкап плюс непрерывная архивация журналов транзакций (WAL): базовая копия раз в сутки или неделю, и каждый закрытый сегмент журнала уходит в архив. Восстановиться можно на любую секунду между базовой копией и последним заархивированным сегментом. Из общедоступных инструментов это pg_basebackup с archive_command или pg_probackup, который умеет и базовые копии, и архив, и проверку целостности, и ретеншн.

Диагностика

Что проверить за полчаса на действующей инсталляции:

-- архивация журналов включена и работает?
show archive_mode;
show archive_command;
select last_archived_wal, last_archived_time, last_failed_wal, last_failed_time, failed_count
from pg_stat_archiver;

Если last_failed_time свежее last_archived_time или failed_count растёт, архив не работает. PostgreSQL при этом не удаляет незаархивированные журналы, каталог pg_wal растёт, и однажды диск заканчивается: база останавливается целиком. Это один из самых частых сценариев простоя RX на PostgreSQL, и он никак не связан с нагрузкой.

# возраст последней базовой копии и её статус (pg_probackup)
pg_probackup show -B /путь/к/каталогу/бэкапов

# сколько журналов накопилось, не уехав в архив
ls /путь/к/data/pg_wal | wc -l
du -sh /путь/к/data/pg_wal

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

Что сделать

Определить целевые показатели. RPO, сколько минут данных допустимо потерять, и RTO, за сколько часов надо подняться. Для базы с архивацией журналов RPO это интервал архивирования, обычно минуты. RTO измеряется, а не назначается: см. учебное восстановление.

Собрать схему целиком.

  1. База: базовая копия по расписанию плюс непрерывный архив журналов. Ретеншн задан явно: сколько копий и на какую глубину держать.
  2. Файловое хранилище: копирование в отдельное место с той же глубиной хранения. Если хранилище S3-совместимое, версионирование и репликация бакета решают задачу штатно.
  3. Конфигурация и секреты: в репозитории или в отдельном архиве, обновляемом при каждом изменении.
  4. Бэкапы лежат вне продуктивной площадки или хотя бы на другом хранилище. Бэкап, который умирает вместе с продом, не бэкап.

Учебное восстановление раз в месяц. На отдельной машине развернуть базу из последней копии с накатом журналов до заданного момента, подключить копию файлового хранилища, поднять сервисы RX и открыть документ с телом. Замерить время от старта до рабочего веб-клиента. Записать протокол: дата, версия, объём, время, что пошло не так. Это фактическое RTO, и это же документ для любого аудита вместо слов «резервное копирование настроено».

Один обязательный алерт. Возраст последней успешной базовой копии больше суток и архивация журналов не выполнялась дольше часа. Реализуется просто: скрипт по расписанию пишет метрики в текстовый файл для node_exporter, а Prometheus сравнивает время. Без этого алерта о сломанном бэкапе узнают в день, когда он понадобился.

Чего не делать

  • Считать реплику бэкапом. Реплика повторяет ошибочное удаление за миллисекунды. Она защищает от отказа сервера, а не от ошибок.
  • Хранить бэкап на диске с данными. Отказ диска или переполнение забирает и данные, и бэкап.
  • Бэкапить базу, забыв хранилище. После восстановления откроются карточки без содержимого, и это обнаруживается в самый неудобный момент.
  • Оставлять pg_dump как основной способ на большой базе. Восстановление из дампа в сотни гигабайт занимает часы, и вернуться на конкретную минуту нельзя.
  • Отключать архивацию «временно», когда диск заполнился. Это лишает точки восстановления; правильно освободить место и починить архив.