Резервное копирование и восстановление
Rediacc может создавать резервные копии зашифрованных репозиториев во внешние хранилища и восстанавливать их на той же или другой машине. Резервные копии зашифрованы; для восстановления требуются учетные данные LUKS репозитория.
Настройка хранилища
Перед отправкой резервных копий зарегистрируйте провайдера хранилища. Rediacc поддерживает любое rclone-совместимое хранилище: S3, B2, Google Drive и многие другие.
Импорт из rclone
Если у вас уже настроен удаленный rclone-ресурс:
rdc config storage import --file rclone.conf
Эта команда импортирует конфигурации хранилища из файла конфигурации rclone в текущую конфигурацию. Поддерживаемые типы: S3, B2, Google Drive, OneDrive, Mega, Dropbox, Box, Azure Blob и Swift.
Просмотр хранилищ
rdc config storage list
Отправка резервной копии
Отправьте резервную копию репозитория во внешнее хранилище:
rdc repo push --name my-app -m server-1 --to my-storage
Push всегда проверяет, смонтирован ли целевой репозиторий перед записью. Если он не смонтирован, операция прерывается.
| Опция | Описание |
|---|---|
--to <storage> | Целевое хранилище |
--to-machine <machine> | Целевая машина для копирования между машинами |
--dest <filename> | Пользовательское имя файла назначения |
--checkpoint | Создать контрольную точку CRIU перед отправкой (для контейнеров с меткой rediacc.checkpoint=true). Целевая машина автоматически восстанавливает при repo up |
--force | Перезаписать существующую резервную копию |
--bwlimit <limit> | Ограничение пропускной способности для rsync-передачи (например, 10M, 500K) |
--tag <tag> | Пометить резервную копию тегом |
-w, --watch | Отслеживать прогресс операции |
--debug | Включить подробный вывод |
--skip-router-restart | Пропустить перезапуск сервера маршрутов после операции |
Получение / Восстановление резервной копии
Получите резервную копию репозитория из внешнего хранилища:
rdc repo pull --name my-app -m server-1 --from my-storage
Pull всегда проверяет, смонтирован ли целевой репозиторий перед записью. Если он не смонтирован, операция прерывается.
| Опция | Описание |
|---|---|
--from <storage> | Исходное хранилище |
--from-machine <machine> | Исходная машина для восстановления между машинами |
--force | Перезаписать существующую локальную резервную копию |
--bwlimit <limit> | Ограничение пропускной способности для rsync-передачи (например, 10M, 500K) |
-w, --watch | Отслеживать прогресс операции |
--debug | Включить подробный вывод |
--skip-router-restart | Пропустить перезапуск сервера маршрутов после операции |
Список резервных копий
Просмотрите доступные резервные копии в хранилище:
rdc repo backup list --from my-storage -m server-1
Вывод представляет собой объединённую таблицу, которая сводит обе папки запланированных резервных копий (hot/ и cold/), так что вы видите каждую резервную копию в одном представлении:
| Колонка | Значение |
|---|---|
Mode | hot или cold. В какой папке запланированных резервных копий находится эта запись |
Name | Имя репозитория, разрешённое из вашей локальной конфигурации (для репозиториев не из конфигурации используется GUID) |
GUID | GUID репозитория на диске |
Size | Удобочитаемый размер файла резервной копии |
Modified | Метка времени UTC от хранилища |
Чтобы перейти к одному режиму, передайте --path:
rdc repo backup list --from my-storage -m server-1 --path hot
rdc repo backup list --from my-storage -m server-1 --path cold
Раскладка хранилища
Запланированные резервные копии попадают в подпапки по режиму внутри настроенной папки хранилища, поэтому одно и то же хранилище аккуратно содержит как почасовой, так и еженедельный потоки, не смешивая их:
<bucket>/<folder>/
├── hot/
│ ├── <guid-1>
│ ├── <guid-2>
│ └── ...
└── cold/
├── <guid-1>
├── <guid-3>
└── ...
Репозиторий может появляться и в hot/, и в cold/ (почасовое расписание делает его снимок; еженедельное расписание делает его снимок снова). Объединённый список показывает обе строки, чтобы было ясно, какие потоки покрывают какие репозитории.
Массовая синхронизация
Отправьте или получите все репозитории одновременно:
Отправка всех в хранилище
rdc repo push --to my-storage -m server-1
Получение всех из хранилища
rdc repo pull --from my-storage -m server-1
| Опция | Описание |
|---|---|
--to <storage> | Целевое хранилище (направление отправки) |
--from <storage> | Исходное хранилище (направление получения) |
--repo <name> | Синхронизировать определенные репозитории (можно указывать несколько раз) |
--override | Перезаписать существующие резервные копии |
--debug | Включить подробный вывод |
--skip-router-restart | Пропустить перезапуск сервера маршрутов после операции |
Запланированное резервное копирование
Rediacc использует именованные стратегии резервного копирования. Каждая стратегия определяет расписание, режим резервного копирования, необязательное ограничение пропускной способности и фильтры файлов. Машины ссылаются на стратегии по имени, чтобы определить, какие резервные копии на них выполняются.
Режимы резервного копирования
| Режим | Поведение | Простой |
|---|---|---|
hot | Снимок BTRFS создается во время работы сервисов (согласованность при сбое) | Отсутствует |
cold | Сервисы остановлены, снимок сделан, сервисы перезапущены, снимок загружен (согласованность на уровне приложения) | Окно остановки+запуска для каждого репозитория, распараллеленное между репозиториями. См. «Оценка простоя при холодном резервном копировании» ниже. |
Используйте hot для сервисов, допускающих снимки с согласованностью при сбое. Используйте cold, когда нужна гарантированная согласованность и допустим кратковременный перезапуск.
Семантика холодного резервного копирования
Холодное резервное копирование выполняется в трех фазах для каждого включенного репозитория: остановка — снимок — запуск. Понимание границ гарантий помогает операторам своевременно обнаруживать частичные сбои.
Что гарантирует холодное резервное копирование:
- Перед снимком каждый работающий контейнер в каждом включенном репозитории корректно останавливается через хук
down()Rediaccfile, а Docker daemon репозитория переводится в состояние покоя. Таким образом, снимок согласован на уровне приложения, а не только при сбое. - Набор ID контейнеров, работавших до снимка, сохраняется в файл-sidecar по пути
/var/run/rediacc/cold-backup-<guid>.running.json. Это источник истины о том, “что должно быть запущено после завершения.” - После снимка вызывается хук
up()Rediaccfile репозитория для восстановления полного compose-стека. - Файл-sidecar статуса выполнения по пути
/var/run/rediacc/cold-backup-<guid>.status.jsonфиксирует фазу, результат и ошибки каждой попытки.
Что холодное резервное копирование НЕ гарантирует:
up()выполняется по принципу “наилучших усилий”. Он может завершиться неудачей по причинам, не зависящим от холодного резервного копирования (условиеdepends_on: service_healthyещё ожидает, синтаксическая ошибка в файле compose, временный сбой сети при загрузке образа). При сбое холодное резервное копирование логирует ошибку на уровне error, записывает файл-sidecar статуса и переходит к следующему репозиторию.- Если
up()завершается неудачей, активируется прямой запасной перезапуск: читается running-sidecar, и каждый записанный ID контейнера перезапускается напрямую через Docker API (без compose). Это возвращает сервисы в рабочее состояние даже при проблемах с compose-потоком, хотя без повторного выполнения хуков Rediaccfile. - Если даже запасной вариант не срабатывает для некоторых ID контейнеров (например, сам Docker daemon недоступен), sidecar остается на месте, чтобы watchdog маршрутизатора мог продолжать попытки при каждом тике.
Восстановление через watchdog: при каждом тике watchdog проверяет наличие running-sidecar. Любой ID контейнера из списка, который в данный момент остановлен, перезапускается независимо от сохраненного restart_policy контейнера. Это означает, что сервисы с restart: on-failure (которые Docker НЕ перезапустит после чистой остановки) всё равно восстанавливаются после холодного резервного копирования. Как только все перечисленные контейнеры запущены, sidecar удаляется.
Как операторы обнаруживают сбои:
rdc machine query --name <machine> --containersпоказывает состояние выполнения. Сравните с ожидаемым набором./var/run/rediacc/cold-backup-<guid>.status.jsonна машине. Проверьте черезrdc term connect -m <machine> -r <repo> -c "cat /var/run/rediacc/cold-backup-$GUID.status.json".success: falseс устаревшимstartedAtозначает, что последнее резервное копирование не завершилось корректно.- Логи запуска резервного копирования renet (
journalctl -u renet-*или прямой вызовrdc machine deploy-backup) содержат итоговую строку видаCold backup: post-snapshot restart summary total=N compose_ok=N fallback_ok=N failed=N failed_repos=[...]. Непустойfailed_reposявляется целевым шаблоном для grep.
Оценка простоя при холодном резервном копировании
Каждый репозиторий остаётся недоступен только на время собственного окна down() + up(). На прогретом хосте эти значения обычно такие:
| Тип репозитория | Типичное время остановки+запуска |
|---|---|
| Малый (1-2 контейнера, без БД) | 5-15 с |
| Средний (веб-приложение + кэш) | 20-45 с |
| Тяжёлый (БД + очереди + почта) | 60-120 с |
Шаг снимка (btrfs subvolume snapshot -r) выполняется за O(1) независимо от размера репозитория: 0,1-1 с. Репозиторий не остаётся остановленным во время снятия снимков других репозиториев. Загрузчик затем работает с доступным только для чтения снимком, пока все репозитории уже снова запущены.
Общее время выполнения всего прогона определяется тем, сколько репозиториев перезапускается параллельно. renet выводит это значение из параметров хоста:
concurrency = min(repoCount, max(2, NumCPU/2), 8)
Примеры:
| Хост | Репозитории | Параллелизм | Время перезапуска |
|---|---|---|---|
| ВМ с 4 CPU | 5 репозиториев, в среднем 30 с каждый | 2 | ~75 с |
| Сервер с 16 CPU | 10 репозиториев, в среднем 40 с каждый | 8 | ~80 с |
| Узел флота с 64 CPU | 50 репозиториев, в среднем 40 с каждый | 8 | ~4 мин |
Переопределение через переменную окружения: установите REDIACC_COLD_BACKUP_CONCURRENCY=N в окружении сервиса резервного копирования (обычно через drop-in systemd), чтобы зафиксировать конкретное значение. Значение =1 принудительно включает строго последовательные перезапуски, что полезно при отладке цикла крашей в хуке up() одного из репозиториев.
Если у вас есть репозиторий, чувствительный к задержкам (публичное веб-приложение, почта), его простой ограничен собственным окном остановки+запуска (обычно 30-90 с), а не общей длительностью прогона. Репозитории распределяются по слотам параллелизма в порядке их обнаружения; очереди приоритетов нет. Разделите тяжёлые репозитории в отдельные стратегии с ограничением через --exclude, если нужна более тонкая настройка расписания.
Длительные резервные копии и перекрывающиеся расписания
Холодное резервное копирование, длящееся дольше собственного интервала расписания (например, первичный сид репозитория на 500 ГБ через умеренный канал может легитимно потребовать более 24 ч, в течение которых ночной таймер срабатывает снова), не ставит в очередь и не запускает второй прогон. Юнит systemd Type=oneshot является единственным экземпляром: когда таймер срабатывает, а сервис уже activating, systemd объединяет запуск с существующей задачей. Новый процесс не запускается, прогон не ставится в очередь на потом.
Конкретно, прогон, начатый в понедельник в 03:00 UTC и завершившийся в четверг в полдень:
| День | Срабатывание в 03:00 UTC | Результат |
|---|---|---|
| Понедельник | Первое срабатывание | Прогон начинается |
| Вторник | Второе срабатывание | Молча отброшено (предыдущий прогон всё ещё активен) |
| Среда | Третье срабатывание | Молча отброшено (предыдущий прогон всё ещё активен) |
| Четверг | Прогон завершается в полдень | Нет догона; следующий прогон в пятницу 03:00 UTC |
Директива Persistent=true таймера не спасает эти срабатывания. Persistent=true воспроизводит срабатывания, пропущенные потому, что сам таймер был неактивен (система выключена, таймер отключен). Срабатывания, отброшенные потому, что сервис был занят, теряются.
Это поведение по умолчанию преднамеренно. Запуск двух холодных резервных копий параллельно против одного и того же datastore будет конкурировать за путь снимка BTRFS, удалённое хранилище rclone и per-repo sidecar’ы в /var/run/rediacc/cold-backup-<guid>.status.json. Сериализация за длительным прогоном является безопасным исходом.
Следствия для мониторинга. Зависший бэкап (например, rclone, заклинивший на сетевой чёрной дыре) молча отбрасывает каждое последующее срабатывание таймера. Планировщик не выдаёт тревог. Следите за systemctl show <unit> -p ActiveEnterTimestamp: если сервис находится в состоянии activating дольше ожидаемой длительности прогона (например, более 48 ч на ночном таймере), проведите расследование.
Если вам нужно, чтобы каждое запланированное срабатывание выполнилось, переключите таймер с OnCalendar=<cron> на OnUnitInactiveSec=<интервал>. Это срабатывает через N часов после завершения предыдущего прогона вместо фиксированного расписания по настенным часам, так что длительные прогоны не вызывают потерь. Они просто смещают следующий прогон. Компромисс заключается в дрейфе расписания: ваш ночной 03:00 становится «24 ч после завершения последнего».
Определение стратегии
Каноническое значение по умолчанию. Это разделение на две стратегии: быстрый почасовой hot-поток, охватывающий каждый репозиторий, и более медленный еженедельный cold-поток, делающий согласованные на уровне приложения снимки. Две стратегии пишут в разные подпапки хранилища (hot/ и cold/), так что резервные копии никогда не смешиваются.
rdc config backup-strategy set \
--name hourly-hot \
--destination my-storage \
--cron "0 * * * *" \
--mode hot \
--bwlimit 20M \
--enable
rdc config backup-strategy set \
--name weekly-cold \
--destination my-storage \
--cron "15 3 * * 0" \
--mode cold \
--exclude very-large-repo \
--enable
Фильтр --exclude в cold-стратегии. Рекомендуемый запасной вариант для очень больших репозиториев, не помещающихся в ваше еженедельное окно обслуживания. Почасовая hot-стратегия по-прежнему их охватывает; cold их просто пропускает. Имена репозиториев в --exclude совпадают с именем репозитория в локальной конфигурации (без :tag).
| Опция | Описание |
|---|---|
--name <name> | Имя стратегии (используется для привязки к машине) |
--destination <storage> | Провайдер хранилища для загрузки |
--cron <expression> | Cron-выражение (например, "0 2 * * *" для ежедневного запуска в 2 часа ночи) |
--mode <hot|cold> | Режим резервного копирования |
--bwlimit <limit> | Ограничение пропускной способности для загрузок (например, 10M) |
--include <pattern> | Фильтр включения (можно указывать несколько раз) |
--exclude <pattern> | Фильтр исключения (можно указывать несколько раз) |
--enable / --disable | Включить или отключить стратегию |
Просмотр стратегий
rdc config backup-strategy list
rdc config backup-strategy show --name weekly-cold
Удаление стратегии
rdc config backup-strategy remove --name weekly-cold
Привязка стратегий к машине
В конфигурации привяжите одно или несколько имен стратегий к машине:
{
"machines": {
"hostinger": {
"backupStrategies": ["hourly-hot", "weekly-cold"]
}
}
}
Операции резервного копирования
Развертывание расписания на машине
Отправьте привязанные стратегии на машину в виде systemd-таймеров:
rdc machine backup schedule -m server-1
rdc machine backup schedule -m server-1 --dry-run
Развёртывание является реконсилятором состояния. Оно читает текущие юнит-файлы и состояние systemd на машине, сравнивает их с тем, что произвела бы конфигурация (SHA-256 на файл), и трогает только те юниты, содержимое которых действительно изменилось. Повторный запуск без изменений конфигурации не производит действий: нет записей, нет daemon-reload, нет колебаний таймеров.
--dry-run печатает план для каждой стратегии (created, updated (service, timer, env), unchanged, removed), не трогая машину. В сочетании с --debug также печатаются сгенерированные тела юнитов; токены rclone редактируются.
Если для стратегии, которую вы собираетесь обновить или удалить, в настоящий момент выполняется резервное копирование, развёртывание завершается с ошибкой, предлагая отменить его или передать --force. С --force выполняющийся вызов сохраняет свой юнит в памяти, а новая конфигурация применяется при следующем срабатывании таймера, поэтому выполняющееся резервное копирование никогда не прерывается принудительно.
--reset-failed является опциональным флагом. Когда он передан, после успешного развёртывания сбрасывается состояние failed на затронутых сервисах. По умолчанию выключен, чтобы предыдущие сигналы об ошибках оставались видимыми для оповещений.
Запуск резервного копирования сейчас
Запустить резервное копирование немедленно, не дожидаясь таймера. Работает даже без развернутых таймеров, используя systemd-run для разовых запусков:
rdc machine backup now -m server-1
rdc machine backup now -m server-1 --strategy weekly-cold
Просмотр статуса резервного копирования
Отображает текущий статус таймеров резервного копирования и результаты последних задач:
rdc machine backup status -m server-1
rdc machine backup status -m server-1 --strategy hourly-hot
Отмена выполняющегося резервного копирования
rdc machine backup cancel -m server-1
rdc machine backup cancel -m server-1 --strategy weekly-cold
Миграция репозитория
Перенос репозитория с одной машины на другую:
rdc repo migrate --name my-app --from server-1 --to server-2
| Опция | Описание |
|---|---|
--name <repo> | Репозиторий для миграции |
--from <machine> | Исходная машина |
--to <machine> | Целевая машина |
--provision | Подготовить репозиторий на целевой машине перед переносом |
--checkpoint | Создать контрольную точку CRIU перед миграцией |
--skip-dns | Пропустить обновление DNS-записей после миграции |
--bwlimit <limit> | Ограничение пропускной способности для передачи (например, 50M) |
Миграция передает зашифрованные данные репозитория через rsync. Исходный репозиторий остается нетронутым, пока вы явно его не удалите.
Обзор хранилища
Просмотрите содержимое хранилища:
rdc storage browse --name my-storage
Лучшие практики
- Настройте ежедневное холодное резервное копирование для согласованных на уровне приложения снимков критически важных данных
- Используйте горячее резервное копирование для высокочастотных снимков с нулевым временем простоя
- Периодически проверяйте восстановление для подтверждения целостности резервных копий
- Используйте несколько провайдеров хранилищ для критически важных данных (например, S3 + B2)
- Храните учетные данные в безопасности; резервные копии зашифрованы, но для восстановления требуются учетные данные LUKS