From 6477681e417722462944d50ee2ad4a0c3a7d396c Mon Sep 17 00:00:00 2001 From: IK Date: Mon, 7 Sep 2026 18:46:34 +0700 Subject: [PATCH] ops: monitor database and object storage growth --- .env.production.example | 2 ++ README.md | 2 +- deploy/README.md | 2 +- deploy/monitor.sh | 20 ++++++++++++++++++-- docs/ROADMAP.md | 2 +- docs/production-monitoring.md | 9 ++++++--- 6 files changed, 29 insertions(+), 8 deletions(-) diff --git a/.env.production.example b/.env.production.example index ab88026..8709b2c 100644 --- a/.env.production.example +++ b/.env.production.example @@ -42,4 +42,6 @@ BACKUP_ROOT=/srv/rf4-backups MONITOR_DISK_MAX_PERCENT=85 MONITOR_TLS_MIN_DAYS=14 MONITOR_BACKUP_MAX_HOURS=26 +MONITOR_DB_MAX_MB=2048 +MONITOR_MINIO_MAX_MB=10240 LOG_LEVEL=INFO diff --git a/README.md b/README.md index 39f0632..cd582f6 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Production-контур для домена `rf4spotter.ru`, TLS, секреты Политика минимизации данных и ежедневная dry-run-first очистка описаны в [`docs/data-retention.md`](docs/data-retention.md). -Host-side мониторинг контейнеров, readiness, диска, резервных копий и TLS описан в [`docs/production-monitoring.md`](docs/production-monitoring.md). +Host-side мониторинг контейнеров, readiness, диска, объёма PostgreSQL/MinIO, резервных копий и TLS описан в [`docs/production-monitoring.md`](docs/production-monitoring.md). Ежедневный systemd timer создаёт проверяемую копию до retention-очистки, а production Compose ограничивает рост JSON-логов контейнеров. Фактическое состояние DNS/TLS домена и серверный чек-лист ведутся в [`docs/deployment-status.md`](docs/deployment-status.md). diff --git a/deploy/README.md b/deploy/README.md index 7099c15..46f5eae 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -145,7 +145,7 @@ systemctl list-timers rf4spotter-maintenance.timer ./deploy/monitor.sh ``` -Проверка контролирует контейнеры, `/ready`, диск, свежесть backup и срок TLS. Установка systemd timer, пороги и порядок реакции описаны в [`docs/production-monitoring.md`](../docs/production-monitoring.md). До подключения реального канала уведомлений одного журнала systemd недостаточно. +Проверка контролирует контейнеры, `/ready`, диск, объём PostgreSQL/MinIO, свежесть backup и срок TLS. Установка systemd timer, пороги и порядок реакции описаны в [`docs/production-monitoring.md`](../docs/production-monitoring.md). До подключения реального канала уведомлений одного журнала systemd недостаточно. ## 9. Что ещё блокирует публичное открытие альфы diff --git a/deploy/monitor.sh b/deploy/monitor.sh index cb97c27..2098309 100755 --- a/deploy/monitor.sh +++ b/deploy/monitor.sh @@ -20,10 +20,14 @@ backup_root=${BACKUP_ROOT:-$(read_env BACKUP_ROOT)} disk_max=${MONITOR_DISK_MAX_PERCENT:-$(read_env MONITOR_DISK_MAX_PERCENT)} tls_days=${MONITOR_TLS_MIN_DAYS:-$(read_env MONITOR_TLS_MIN_DAYS)} backup_hours=${MONITOR_BACKUP_MAX_HOURS:-$(read_env MONITOR_BACKUP_MAX_HOURS)} +db_max_mb=${MONITOR_DB_MAX_MB:-$(read_env MONITOR_DB_MAX_MB)} +minio_max_mb=${MONITOR_MINIO_MAX_MB:-$(read_env MONITOR_MINIO_MAX_MB)} disk_max=${disk_max:-85} tls_days=${tls_days:-14} backup_hours=${backup_hours:-26} -for value in "$disk_max" "$tls_days" "$backup_hours"; do +db_max_mb=${db_max_mb:-2048} +minio_max_mb=${minio_max_mb:-10240} +for value in "$disk_max" "$tls_days" "$backup_hours" "$db_max_mb" "$minio_max_mb"; do case "$value" in ''|*[!0-9]*) printf 'CRITICAL rf4spotter failures="monitor-threshold-invalid"\n'; exit 2 ;; esac done base_url=${MONITOR_BASE_URL:-https://$site_domain} @@ -48,6 +52,18 @@ case "$disk_used" in *) [ "$disk_used" -lt "$disk_max" ] || fail "disk:${disk_used}%" ;; esac +db_bytes=$($compose exec -T db sh -c 'psql -At -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "select pg_database_size(current_database())"' 2>/dev/null) || db_bytes="" +case "$db_bytes" in + ''|*[!0-9]*) db_mb="unknown"; fail "postgresql-size:unknown" ;; + *) db_mb=$(((db_bytes + 1048575) / 1048576)); [ "$db_mb" -lt "$db_max_mb" ] || fail "postgresql-size:${db_mb}MB" ;; +esac + +minio_kb=$($compose exec -T minio du -sk /data 2>/dev/null | awk 'NR==1 {print $1}') +case "$minio_kb" in + ''|*[!0-9]*) minio_mb="unknown"; fail "minio-size:unknown" ;; + *) minio_mb=$(((minio_kb + 1023) / 1024)); [ "$minio_mb" -lt "$minio_max_mb" ] || fail "minio-size:${minio_mb}MB" ;; +esac + if [ -z "$backup_root" ] || [ ! -d "$backup_root" ]; then fail "backup:directory" else @@ -77,4 +93,4 @@ if [ -n "$failures" ]; then exit 1 fi -printf 'OK rf4spotter timestamp=%s disk_used=%s%% backup_max_age=%sh tls_min=%sd\n' "$timestamp" "$disk_used" "$backup_hours" "$tls_days" +printf 'OK rf4spotter timestamp=%s disk_used=%s%% postgresql=%sMB minio=%sMB backup_max_age=%sh tls_min=%sd\n' "$timestamp" "$disk_used" "$db_mb" "$minio_mb" "$backup_hours" "$tls_days" diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 1df0bd8..55e0d2a 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -144,7 +144,7 @@ - [x] Добавить серверное «Показать ещё» для публичной ленты полевых сигналов с сохранением фильтров и пределом 48 записей (7 сентября 2026). - [x] Объединять одинаковые полевые сигналы в сюжеты без потери уникальных ссылок provenance и показывать число совпадений (7 сентября 2026). - [ ] Добавить безопасный административный экспорт диагностики без персональных данных. -- [ ] Контролировать рост PostgreSQL и MinIO с порогами предупреждений. +- [x] Контролировать рост PostgreSQL и MinIO host-monitor'ом с настраиваемыми порогами и runbook реакции (7 сентября 2026). - [ ] Добавить фоновую проверку битых исходных ссылок с соблюдением лимитов источников. - [x] Показывать версию и commit SHA в readiness и защищённой административной диагностике (7 сентября 2026). - [x] Добавить публичную `/status` без внутренних адресов, секретов и текстов ошибок (7 сентября 2026). diff --git a/docs/production-monitoring.md b/docs/production-monitoring.md index 68b2a73..d6a368d 100644 --- a/docs/production-monitoring.md +++ b/docs/production-monitoring.md @@ -7,10 +7,11 @@ - контейнеры `proxy`, `db`, `minio`, `api`, `web` находятся в running; - публичный `https://rf4spotter.ru/ready` сообщает `ready`; - файловая система проекта заполнена менее чем на 85%; +- база PostgreSQL занимает менее 2 ГБ, а данные MinIO — менее 10 ГБ; - последняя полная резервная копия не старше 26 часов и проходит проверку `SHA256SUMS`; - TLS-сертификат домена действует ещё минимум 14 дней. -Пороги задаются в `.env.production`: `BACKUP_ROOT`, `MONITOR_DISK_MAX_PERCENT`, `MONITOR_BACKUP_MAX_HOURS`, `MONITOR_TLS_MIN_DAYS`. Проверка TLS использует SNI и поэтому обнаруживает как истечение, так и выдачу сертификата для неверного домена. +Пороги задаются в `.env.production`: `BACKUP_ROOT`, `MONITOR_DISK_MAX_PERCENT`, `MONITOR_DB_MAX_MB`, `MONITOR_MINIO_MAX_MB`, `MONITOR_BACKUP_MAX_HOURS`, `MONITOR_TLS_MIN_DAYS`. Значения объёма задаются в МБ и для открытой альфы по умолчанию равны 2048/10240. Проверка TLS использует SNI и поэтому обнаруживает как истечение, так и выдачу сертификата для неверного домена. ## Ручная проверка @@ -43,5 +44,7 @@ Monitor timer записывает результат в journal. Maintenance ti 1. `service:*` — посмотреть `docker compose ... ps` и логи конкретного контейнера; не выполнять `down -v`. 2. `readiness` — проверить `/ready`, PostgreSQL и MinIO; на время сбоя остановить приём пользовательских заявок. 3. `disk:*` — сначала перенести старые backup во внешнее хранилище; не удалять Docker volumes вслепую. -4. `backup:*` — запустить `deploy/backup.sh`, проверить `SHA256SUMS` и устранить причину пропуска расписания. -5. `tls:*` — проверить DNS, доступность портов 80/443 и логи Caddy; не отключать проверку сертификата. +4. `postgresql-size:*` — проверить рост таблиц и выполнение retention; перед очисткой сделать backup и не выполнять ручное удаление строк без плана. +5. `minio-size:*` — сверить объекты с заявками и политикой retention; не удалять volume или бакет целиком. +6. `backup:*` — запустить `deploy/backup.sh`, проверить `SHA256SUMS` и устранить причину пропуска расписания. +7. `tls:*` — проверить DNS, доступность портов 80/443 и логи Caddy; не отключать проверку сертификата.