Периодическое резервное копирование по расписанию
Пакет komrad-server устанавливает всё необходимое для несопровождаемого
ночного резервного копирования: скрипт-обёртку, отключённый по умолчанию
cron-фрагмент, файл конфигурации с паролем и логротацию. Секрет шифрования
хранится только в файле с правами 0600 и никогда не появляется ни в
crontab, ни в аргументах процесса, ни в выводе ps — это прямо устраняет
практику из более ранних версий, где пароль передавался переменной окружения
в самой строке crontab.
Что устанавливает пакет
| Файл | Права, владелец | Назначение |
|---|---|---|
/usr/libexec/komrad/komrad-backup.sh | 0755, root:root | Скрипт-обёртка: запускает create → verify → prune, пишет статус в syslog и полный вывод в лог. |
/etc/cron.d/komrad-backup | 0644, root:root | Строка расписания. Ставится закомментированной — до задания пароля включать её нельзя. |
/etc/echelon/komrad/backup.env | 0600, root:root | Конфигурация: пароль шифрования, хранилище, срок хранения, доп. флаги. |
/etc/logrotate.d/komrad-backup | 0644, root:root | Еженедельная ротация backup.log с сжатием. |
Пакет komrad-server объявляет зависимость от komrad-cli: без него ставить
обёртку было бы бессмысленно, так как именно komrad-cli выполняет
create/verify/prune.
Настройка
Отредактируйте /etc/echelon/komrad/backup.env (правами 0600 root:root файл
ставится уже с нужными правами, менять их не нужно):
| Ключ | Умолчание | Назначение |
|---|---|---|
KOMRAD_BACKUP_PASSPHRASE | (пусто) | Фраза-пароль шифрования. Обязательна: пока она пуста, обёртка отказывается запускать резервное копирование — это единственное, что удерживает свежеустановленный узел от ежедневной записи провалов в лог. |
KOMRAD_BACKUP_TARGET | /var/backups/komrad | Локальный каталог, куда пишутся наборы (передаётся как --to). |
KOMRAD_BACKUP_KEEP_DAYS | 14 | Передаётся в komrad-cli backup prune --keep-days после каждого успешного запуска. |
KOMRAD_BACKUP_EXTRA_ARGS | (пусто) | Дополнительные аргументы backup create; значение разбивается по пробелам, поэтому можно передать сразу несколько флагов, например --events-window 30d --cipher openssl. Хранилище сюда не переносится — см. ниже. |
KOMRAD_BACKUP_LOG | /var/log/echelon/komrad/backup.log | Полный вывод всех трёх команд (в syslog попадают только строки start/OK/FAILED). |
KOMRAD_BACKUP_PATH | /opt/echelon/komrad/bin:/usr/bin:/bin | PATH запуска: окружение cron по умолчанию не видит встроенный pg_dump (echelonpg). |
PGPASSFILE | /root/.pgpass | Файл паролей libpq — так пароль PostgreSQL не попадает в переменные окружения. |
KOMRAD_BACKUP_NOTIFY_CMD | (пусто) | Путь к одному исполняемому файлу, запускаемому при сбое; код возврата приходит первым аргументом (значение не разбивается по пробелам). См. «Уведомления о сбоях». |
Задайте как минимум KOMRAD_BACKUP_PASSPHRASE. Ни этот, ни какой-либо другой
секрет нигде, кроме backup.env, не хранится и никогда не передаётся ни в
crontab, ни в аргументах процесса.
Хранилище запланированного копирования всегда локальное. Обёртка вызывает
backup create и backup prune с --to/<target>, равным
KOMRAD_BACKUP_TARGET, — то есть путём, а не @N или sftp/s3;
добавление --config ... в KOMRAD_BACKUP_EXTRA_ARGS этого не меняет, так
как именованные хранилища из конфига подставляются, только когда сам --to
равен @N либо буквально sftp/s3 — сам по себе такой токен не адрес, а
выбор одноимённого (первого по типу) или пронумерованного хранилища из
списка targets в --config. Более того, если KOMRAD_BACKUP_TARGET всё же
перенаправить на такое значение, ночной komrad-cli backup prune начнёт
падать каждый раз: prune явно отказывается работать с удалёнными
хранилищами (см. «Ротация»). Резервное копирование в SFTP/S3
запускайте вручную, указав хранилище из конфига токеном или индексом —
komrad-cli backup create --to sftp --config ... или
komrad-cli backup create --to @0 --config ..., см.
«Хранилища».
Затем включите расписание — раскомментируйте строку запуска и, при
необходимости, MAILTO в /etc/cron.d/komrad-backup:
# было (ставится пакетом):
#MAILTO=root
#0 2 * * * root /usr/libexec/komrad/komrad-backup.sh
# стало:
MAILTO=root
0 2 * * * root /usr/libexec/komrad/komrad-backup.sh
Фрагмент ставится отключённым намеренно: включение расписания до того, как задан пароль, каждую ночь писало бы в лог провал.
Ротация
Отслужившие наборы удаляет komrad-cli backup prune, который обёртка вызывает
после каждого успешного create+verify:
# план без удаления
komrad-cli backup prune /var/backups/komrad --keep-days 14 --dry-run
# применить
komrad-cli backup prune /var/backups/komrad --keep-days 14
Основные флаги (полный список — в справочнике):
--keep-days N— хранить наборы, созданные за последние N дней;--keep-last N— хранить N последних наборов;--dry-run— вывести план без удаления;--no-staging— пропустить очистку осиротевших директорий стейджинга ClickHouse.
Нужен хотя бы один из --keep-days/--keep-last — без обоих команда
завершается ошибкой. Оба параметра объединяются по ИЛИ: набор сохраняется,
если его оставляет хотя бы один критерий. Самый новый набор не удаляется
никогда. Базовый набор не удаляется, пока от него зависит другой сохраняемый
набор (актуально для инкрементальной цепочки — см.
предупреждение о состоянии инкрементального режима в 4.6).
Набор, чей манифест не удалось прочитать или разобрать, всегда сохраняется и
отмечается в отчёте отдельной строкой. Директории <набор>.partial
(незавершённая выгрузка) никогда не перечисляются и не удаляются.
Отдельно от удаления самих наборов, если не задан --no-staging, prune
очищает осиротевшие директории стейджинга ClickHouse на диске komrad_backup:
нативный BACKUP ClickHouse пишет туда при выгрузке, а backup create за
собой не убирает. Если ClickHouse на узле не обнаружен, эта часть команды
пропускается без ошибки — код возврата prune остаётся 0, ротация самих
наборов к этому моменту уже применена. Пропуск может сопровождаться строкой
discovery warning: ... в выводе (а значит и в backup.log) — это не
ошибка, а описание причины пропуска; на узле без со-размещённого
komrad-processor она ожидаема и не требует действий. Если же само
обнаружение ClickHouse завершается ошибкой (например, повреждён конфиг),
команда возвращает ненулевой код, хотя удаление наборов уже выполнено; обе
части идемпотентны, повторный запуск безопасен.
Удалённые хранилища (sftp:, s3:) и ссылки @N на komrad-backup.yaml
командой не поддерживаются — вместо тихого бездействия она завершается явной
ошибкой. Указывайте только локальный путь к каталогу.
Логирование
Обёртка пишет короткие статусные строки через logger с тегом
komrad-backup:
backup start— перед запуском;backup OK set=<имя>— после успешногоcreate→verify→prune;backup FAILED rc=N (see /var/log/echelon/komrad/backup.log)— при сбое любого из трёх шагов, уровеньdaemon.err.
Если предыдущий запуск ещё не завершился (например, обёртка зависла на
предыдущем тике), новый запуск не встаёт в очередь: он пишет строку
previous run still active; skipping и завершается с кодом 0.
Полный вывод backup create, backup verify и backup prune пишется в
/var/log/echelon/komrad/backup.log (путь задаётся KOMRAD_BACKUP_LOG).
Ротация — пакетным /etc/logrotate.d/komrad-backup: еженедельно, 12 копий,
сжатие с задержкой на один цикл, права новой копии 0640 root:root. До
первой ротации права лога при первой записи и файла блокировки
(/run/komrad-backup.lock) задаёт собственный umask 027 обёртки. Временный
файл вывода create (mktemp) в этот список не входит: его права 0600
задаёт сам mktemp, независимо от umask.
Код возврата обёртки
rc в строке backup FAILED — это один из трёх кодов, которые задаёт сама
обёртка, либо код возврата упавшего шага:
| Код | Причина |
|---|---|
127 | komrad-cli не найден по пути /opt/echelon/komrad/bin/komrad-cli |
78 | KOMRAD_BACKUP_PASSPHRASE не задан в backup.env |
73 | не удалось создать временный файл (mktemp) для вывода create |
| иначе | код возврата того шага (create, verify или prune), который завершился с ошибкой |
rc=78 — самый частый код на свежем узле: пакет ставит backup.env с
пустым паролем намеренно (см. «Настройка»), поэтому это ровно
то, что видит любой, кто включил расписание до того, как задал пароль.
Уведомления о сбоях
Два независимых канала:
MAILTOв/etc/cron.d/komrad-backup— путь без дополнительной настройки: cron сам отправляет письмо с выводом задания. Раскомментируйте вместе со строкой расписания.KOMRAD_BACKUP_NOTIFY_CMDвbackup.env— запускается при ненулевом коде возврата; код возврата передаётся первым аргументом. Значение — путь к одному исполняемому файлу, а не командная строка: в отличие отKOMRAD_BACKUP_EXTRA_ARGSоно не разбивается по пробелам, поэтому аргументы и опции сюда не передать напрямую — оберните их в сценарий, как в примере ниже.
Пример вебхука:
#!/bin/sh
# /usr/local/bin/komrad-backup-notify.sh
rc="$1"
curl -fsS -X POST https://hooks.example.com/komrad-backup \
-H 'Content-Type: application/json' \
-d "{\"host\":\"$(hostname)\",\"rc\":${rc}}"
KOMRAD_BACKUP_NOTIFY_CMD=/usr/local/bin/komrad-backup-notify.sh
Проверка
-
Создание копии PostgreSQL.
komrad-cli backup create --to /var/backups/komrad --passphrase "test" \--no-ch --no-natsjskomrad-cli backup verify /var/backups/komrad/<набор> --passphrase "test"Ожидаемый результат: обе команды завершаются с кодом
0; вmanifest.jsonнабора присутствует поверхностьpostgres. -
Создание копии ClickHouse.
komrad-cli backup create --to /var/backups/komrad --passphrase "test" \--no-pg --no-natsjskomrad-cli backup verify /var/backups/komrad/<набор> --passphrase "test"Ожидаемый результат: обе команды завершаются с кодом
0; вmanifest.jsonнабора присутствует поверхность ClickHouse. -
Срабатывание расписания. Автоматический e2e не проверяет работу самого cron — только поведение
komrad-cliи обёртки. Поэтому включение по расписанию проверяется вручную: временно замените строку в/etc/cron.d/komrad-backupна* * * * * root /usr/libexec/komrad/komrad-backup.sh, подождите до минуты и проверьте лог:journalctl -t komrad-backup --no-pager | tailtail /var/log/echelon/komrad/backup.logОжидаемый результат: в течение минуты появляются строки
backup startиbackup OK set=...(при заданном пароле). После проверки верните строку расписания к ночному значению (0 2 * * *). -
Ротация. Переименуйте существующий набор так, будто он старше
--keep-days(возраст берётся из метки времени в имени набора, а не из mtime каталога):mv /var/backups/komrad/komrad-test-20260728T020000Z \/var/backups/komrad/komrad-test-20260101T020000Zkomrad-cli backup prune /var/backups/komrad --keep-days 14 --dry-run# → строка "delete komrad-test-20260101T020000Z (...)"komrad-cli backup prune /var/backups/komrad --keep-days 14# → строка "deleted komrad-test-20260101T020000Z"Ожидаемый результат:
--dry-runпоказывает набор в плане на удаление и ничего не удаляет; повторный запуск без--dry-runудаляет каталог набора. -
Целостность данных. В тестовом окружении:
komrad-cli backup create --to /var/backups/komrad --passphrase "test"# повредить состояние: удалить строку/таблицу в одной из БД KOMRADsudo systemctl stop komrad-server komrad-processor komrad-correlator pauth-serversudo komrad-cli restore /var/backups/komrad/<набор> --passphrase "test"Ожидаемый результат:
restoreзавершается с кодом0; удалённые ранее данные снова присутствуют после восстановления. См. Восстановление из резервной копии. -
Поведение при недоступности СУБД.
sudo systemctl stop postgresqlsudo /usr/libexec/komrad/komrad-backup.sh; echo "rc=$?"Ожидаемый результат: обёртка не зависает, завершается быстро с ненулевым
rc;journalctl -t komrad-backup -p err --no-pagerсодержит строкуbackup FAILED rc=N (see /var/log/echelon/komrad/backup.log). ЗдесьN— код возвратаcreate(не один из трёх кодов самой обёртки, см. «Код возврата обёртки»). Верните PostgreSQL в рабочее состояние после проверки.
См. также
- Создание резервной копии — состав набора, хранилища, шифрование.
- Восстановление из резервной копии — процедуры восстановления.
- Справочник CLI — полный список флагов
create,verify,pruneиrestore, а также схемаbackup.env.