Эксплуатация¶
Повседневная эксплуатация Alatyr: backup/restore PostgreSQL, мониторинг
webhook-очереди доставки, мониторинг очереди async-SCEP issuance
(ca_pending) и планирование волны одобрений при продлении
сертификатов. Про отказоустойчивость при нескольких репликах сервера —
отдельная страница, Отказоустойчивость (HA), читайте её тоже,
если планируете горизонтальное масштабирование.
Backup/restore PostgreSQL¶
Alatyr не поставляет backup-инфраструктуру сам
Ни один из поставляемых демо-манифестов (Docker Compose, Helm-чарт) не разворачивает job/cron для бэкапа PostgreSQL — база всегда один под без реплики и без scheduled-снапшотов (см. Отказоустойчивость и Расчёт ресурсов). Backup/restore — целиком забота оператора, разворачивающего PostgreSQL для Alatyr. Ниже — не описание встроенного механизма, а минимальный практический рецепт поверх стандартных инструментов PostgreSQL.
Всё persistent-состояние приложения — одна база, адрес которой задаёт
ALATYR_DB_URL (см. Конфигурация). Схема
версионируется миграциями,
которые применяются через goose при старте сервера — восстановленная
база должна быть на той версии схемы, которую ожидает разворачиваемый
исполняемый файл сервера.
Логический бэкап (pg_dump/pg_restore, подходит для большинства
инсталляций текущего масштаба — см. Расчёт ресурсов про
ожидаемый объём данных):
# Бэкап (custom-формат — сжатый, restore умеет частичный/параллельный)
pg_dump --format=custom --file=alatyr-$(date -u +%Y%m%dT%H%M%SZ).dump \
"$ALATYR_DB_URL"
# Restore в пустую базу той же major-версии PostgreSQL
pg_restore --clean --if-exists --no-owner \
--dbname="$ALATYR_DB_URL" alatyr-<timestamp>.dump
- Снимайте бэкап регулярно по расписанию (cron/CronJob вне приложения) и
проверяйте
pg_restore --listна свежем дампе — непроверяемый бэкап эквивалентен отсутствию бэкапа. - Для непрерывной защиты (RPO меньше, чем интервал между
pg_dump) — включайте WAL-архивирование или используйте managed-Postgres с point-in-time recovery; ни то, ни другое не настроено ни в одном манифесте репозитория по умолчанию. - Секреты, которые приложение хранит зашифрованными в самой базе
(значения секретов вебхуков и состояние SCEP-поллинга), расшифровываются
тем же ключом, что задан в окружении сервера — сохраняйте резервную
копию
ALATYR_WEBHOOK_ENC_KEY/ALATYR_SCEP_ENC_KEYотдельно от самой базы (например, в секрет-хранилище), иначе восстановленная база окажется с нечитаемыми полями. - После restore на новый инстанс сервера убедитесь, что схема совпадает с ожидаемой версией миграций до того, как пускать туда трафик — goose применит недостающие миграции при следующем старте автоматически, но сверка «какая версия схемы была в дампе» — на операторе.
Мониторинг webhook-очереди (outbox)¶
Исходящие вебхуки (ALATYR_WEBHOOKS_ENABLED=true) идут через
outbox-таблицу webhook_deliveries, которую вычитывает фоновый воркер каждые
ALATYR_WEBHOOK_POLL_SECONDS секунд (по умолчанию 10). Статус доставки —
pending → delivered, либо pending → failed после
ALATYR_WEBHOOK_MAX_ATTEMPTS попыток (по умолчанию 6). Устаревшие записи
(created_at старше ALATYR_WEBHOOK_RETENTION_DAYS, по умолчанию 30 дней)
воркер автоматически удаляет каждые 6 часов — отдельного cron для этого не
нужно.
Через API (не требует прямого доступа к БД):
GET /api/v1/admin/webhooks/{id}/deliveries— постраничный журнал доставок конкретного эндпоинта (limit/page), включаяstatus/attempts/last_response_code/last_errorкаждой попытки. См. REST API.POST /api/v1/admin/webhooks/{id}/test— вручную поставить в очередь тестовую доставку, чтобы проверить эндпоинт end-to-end.
Через БД (для алертинга/дашборда, не открывая Admin UI на каждый эндпоинт):
-- Сколько доставок застряло в pending дольше ожидаемого интервала опроса
SELECT endpoint_id, count(*), min(next_attempt_at)
FROM webhook_deliveries
WHERE status = 'pending' AND next_attempt_at < now() - interval '5 minutes'
GROUP BY endpoint_id;
-- Недавние окончательные отказы (превышен max_attempts)
SELECT id, endpoint_id, event_type, attempts, last_response_code, last_error, created_at
FROM webhook_deliveries
WHERE status = 'failed' AND created_at > now() - interval '24 hours'
ORDER BY created_at DESC;
Растущее число pending-строк с next_attempt_at в прошлом обычно
значит, что воркер не запущен (ALATYR_WEBHOOKS_ENABLED было включено
после старта процесса без рестарта) либо эндпоинт систематически
недоступен — проверьте last_error/last_response_code последних
попыток через GET .../deliveries.
Мониторинг очереди async-SCEP issuance (ca_pending)¶
Когда issuer — SCEP (ALATYR_ISSUER=scep), выпуск не синхронный: заявка
переходит в статус ca_pending (cert_requests.status), а таблица
scep_pending держит одну строку на каждую заявку, ожидающую ответа
внешнего CA. Фоновый поллер вычитывает её каждые
ALATYR_SCEP_POLL_SECONDS секунд (по умолчанию 30) и повторяет запрос к
CA, пока сертификат не будет выпущен или заявка не исчерпает
retry-бюджет.
Только одна реплика — см. Отказоустойчивость
Поллинг ca_pending корректен только на одной реплике сервера. При
нескольких репликах два поллера могут забрать одну и ту же строку и
отправить дублирующий PKCSReq во внешний CA. Подробный разбор
механизма — Отказоустойчивость (HA), раздел «Что НЕ
безопасно на N репликах сегодня» → «SCEP-поллинг».
Прямого REST-эндпоинта для очереди ca_pending нет — мониторинг идёт
через SQL или через сами заявки:
-- Заявки, зависшие в ca_pending дольше нескольких интервалов поллинга
SELECT sp.cert_request_id, sp.attempts, sp.next_poll_at, sp.last_error,
cr.status, cr.created_at
FROM scep_pending sp
JOIN cert_requests cr ON cr.id = sp.cert_request_id
WHERE sp.next_poll_at < now() - interval '10 minutes'
ORDER BY sp.next_poll_at;
Растущее attempts с непустым last_error на одной и той же строке —
сигнал, что внешний SCEP CA систематически не выпускает сертификат по
этому запросу (истёкший challenge, недоступность CA, и т.п.) — смотрите
last_error за деталями конкретного отказа CA. Единичные «потерянные»
сертификаты у осиротевшего SCEP-poll (см. предупреждение выше про
несколько реплик) обычно не видны через эту таблицу — они уже покинули
scep_pending на стороне Alatyr, но не были никогда получены обратно;
искать их нужно в логах CA, не здесь.
Продление сертификатов и волна одобрений¶
Агент продлевает сертификат самостоятельно, проходя тот же цикл enroll, что и при первичной выдаче, — подробный разбор механизма: Агенты → Продление сертификата. Для планирования эксплуатации важно одно следствие этого механизма: продление создаёт новую заявку, и она проходит ту же проверку одобрения, что и первичная.
- При ручном одобрении заявок ожидайте периодическую волну заявок на
одобрение по мере того, как у устройств флота подходит к концу срок
действия сертификата, а не равномерный редкий поток. По умолчанию
срок действия машинного сертификата (
wifi) — 3 года; это единственная цель, у которой значение настраивается на сервере. У остальных целей срок фиксированный:user_mtlsиad_logon— 1 год,ssh— 24 часа. - Если для соответствующего purpose настроено автоодобрение (сервисный
аккаунт с ролью
cert-auto-approver, см. Администрирование → Approve / reject / revoke заявок), волна проходит без ручных действий со стороны оператора.
Хранение снапшотов логов устройств¶
Загруженные через POST /api/v1/devices/{serial}/request-logs снапшоты
логов устройств хранятся не дольше 7 дней — фоновая задача сама очищает
устаревшие снапшоты, отдельного обслуживания не требует.
См. также¶
- Отказоустойчивость (HA) — что безопасно/небезопасно при нескольких репликах сервера.
- Расчёт ресурсов — ожидаемые ресурсы и объём данных.
- Логирование — структурные логи для разбора инцидентов.
- Диагностика и ограничения — известные ограничения и типовые симптомы.