Перейти к основному содержимому
Версия: 4.6.X

Периодическое резервное копирование по расписанию

Пакет komrad-server устанавливает всё необходимое для несопровождаемого ночного резервного копирования: скрипт-обёртку, отключённый по умолчанию cron-фрагмент, файл конфигурации с паролем и логротацию. Секрет шифрования хранится только в файле с правами 0600 и никогда не появляется ни в crontab, ни в аргументах процесса, ни в выводе ps — это прямо устраняет практику из более ранних версий, где пароль передавался переменной окружения в самой строке crontab.

Что устанавливает пакет

ФайлПрава, владелецНазначение
/usr/libexec/komrad/komrad-backup.sh0755, root:rootСкрипт-обёртка: запускает createverifyprune, пишет статус в syslog и полный вывод в лог.
/etc/cron.d/komrad-backup0644, root:rootСтрока расписания. Ставится закомментированной — до задания пароля включать её нельзя.
/etc/echelon/komrad/backup.env0600, root:rootКонфигурация: пароль шифрования, хранилище, срок хранения, доп. флаги.
/etc/logrotate.d/komrad-backup0644, 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_DAYS14Передаётся в 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:/binPATH запуска: окружение 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=<имя> — после успешного createverifyprune;
  • 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 — это один из трёх кодов, которые задаёт сама обёртка, либо код возврата упавшего шага:

КодПричина
127komrad-cli не найден по пути /opt/echelon/komrad/bin/komrad-cli
78KOMRAD_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

Проверка

  1. Создание копии PostgreSQL.

    komrad-cli backup create --to /var/backups/komrad --passphrase "test" \
    --no-ch --no-natsjs
    komrad-cli backup verify /var/backups/komrad/<набор> --passphrase "test"

    Ожидаемый результат: обе команды завершаются с кодом 0; в manifest.json набора присутствует поверхность postgres.

  2. Создание копии ClickHouse.

    komrad-cli backup create --to /var/backups/komrad --passphrase "test" \
    --no-pg --no-natsjs
    komrad-cli backup verify /var/backups/komrad/<набор> --passphrase "test"

    Ожидаемый результат: обе команды завершаются с кодом 0; в manifest.json набора присутствует поверхность ClickHouse.

  3. Срабатывание расписания. Автоматический e2e не проверяет работу самого cron — только поведение komrad-cli и обёртки. Поэтому включение по расписанию проверяется вручную: временно замените строку в /etc/cron.d/komrad-backup на * * * * * root /usr/libexec/komrad/komrad-backup.sh, подождите до минуты и проверьте лог:

    journalctl -t komrad-backup --no-pager | tail
    tail /var/log/echelon/komrad/backup.log

    Ожидаемый результат: в течение минуты появляются строки backup start и backup OK set=... (при заданном пароле). После проверки верните строку расписания к ночному значению (0 2 * * *).

  4. Ротация. Переименуйте существующий набор так, будто он старше --keep-days (возраст берётся из метки времени в имени набора, а не из mtime каталога):

    mv /var/backups/komrad/komrad-test-20260728T020000Z \
    /var/backups/komrad/komrad-test-20260101T020000Z

    komrad-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 удаляет каталог набора.

  5. Целостность данных. В тестовом окружении:

    komrad-cli backup create --to /var/backups/komrad --passphrase "test"
    # повредить состояние: удалить строку/таблицу в одной из БД KOMRAD
    sudo systemctl stop komrad-server komrad-processor komrad-correlator pauth-server
    sudo komrad-cli restore /var/backups/komrad/<набор> --passphrase "test"

    Ожидаемый результат: restore завершается с кодом 0; удалённые ранее данные снова присутствуют после восстановления. См. Восстановление из резервной копии.

  6. Поведение при недоступности СУБД.

    sudo systemctl stop postgresql
    sudo /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 в рабочее состояние после проверки.

См. также