Метрики: правки prometheus.yml, конфига Loki, датасорсов Grafana и запросов postgres-экспортёров вступают в силу после деплоя #3557
No reviewers
Labels
No labels
Fable 5 ревью
GG-форсайт
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
feedback/max
generative
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
ИРД
вторичка
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#3557
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/metrics-deploy-reload"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Что было
Деплой метрик клал конфиги на диск, но часть сервисов их не перечитывала. Деплой при этом оставался зелёным. Часть про правила Prometheus уже смержена в #3476. Остались хвосты #3467 и #3486.
#3467: prometheus.yml, loki-config.yml и датасорсы Grafana
prometheus.yml. Файл смонтирован в контейнер одиночным файлом. В main рядом с reload стоял комментарий: «/-/reload переоткрывает файлы ПО ПУТИ заново, поэтому новый инод после
git reset --hardподхватывается». Это неверно. Правила подключены каталогом, поэтому для них reload работает, а для prometheus.yml нет. Проверил на стендеprom/prometheus:v3.1.017.09:reload возвращает rc=0,
lastConfigTimeобновляется, а в работе остаётся старый job. Шаг из #3476 подтверждает reload поlastConfigTime, поэтому такую ситуацию он принимает за успех. Вторая проблема в том, что promtool запускался черезdocker execв работающем контейнере и проверял старый инод, а не файл, который собирались применить. То, чтоgit reset --hardпишет изменённый файл новым инодом, проверил отдельно: 66651554 → 66651563.loki-config.yml. Тоже одиночный файл, а перезагрузки основного конфига у Loki нет. В main не было ни пересоздания контейнера, ни сверки инода.
Датасорсы Grafana. Каталог provisioning смонтирован целиком, так что контейнер видит новый файл сразу. Но датасорсы Grafana читает только при старте: на стенде в #3475 изменённый url не применился и через 75 с. Вызова
/api/admin/provisioning/datasources/reloadв main нет (grep= 0). Об этом bot-backend написал в комментарии к #3467 12.09.#3486: queries.yml у трёх postgres-экспортёров
queries.yml смонтирован одиночным файлом и читается только при старте. Джобы
agent-appsиagent-infraпересоздают только alloy. Гейта наdocker-compose.metrics-agent.ymlне было:test_every_single_file_mount_has_a_way_to_arriveостался в закрытом #3475.Сейчас это не проявляется, проверил 17.09 только чтением. Beget: prometheus.yml 578436=578436, loki-config.yml 569350=569350, datasources.yml 569347=569347, queries.yml у pg-exporter-infra 569352=569352. Poincare: queries.yml у обоих экспортёров 5112170=5112170. Дыра заложена в самой конструкции: сработает при первой же правке любого из этих файлов.
Что сделано
ops/metrics/recreate-stale-mount.sh ПРОЕКТ COMPOSE СЕРВИС ФАЙЛ ПУТЬ— один скрипт для всех одиночных маунтов. Сравниваетstat -c %iна хосте и внутри контейнера (контейнер находит черезcompose ps -q). Если инод разошёлся, делаетup -d --no-deps --force-recreateи сверяет инод ещё раз. Если после пересоздания не сошлось, выходит с exit 1. Если контейнер не запущен, выходит с 0: старый инод держать некому. Ошибкуcompose psне глушит. Если прочитать инод в контейнере не удалось, это считается расхождением. Команды скрипта прогнал только на чтение на обоих хостах (docker compose v5.1.3 / v5.5.0,ps -q→ id,docker exec <id> stat→ инод). На текущем состоянии скрипт ничего не пересоздаст.ops/metrics/prometheusсмонтирован в/etc/prometheus(прогнал локально: верный конфиг rc=0, битый rc=1). Сверка prometheus.yml идёт между успешной проверкой и reload. Ожидание готовности перенесено после возможного пересоздания и теперь ждёт и Prometheus, и Grafana. Loki сверяется после подъёма стека. Датасорсы Grafana:POST /api/admin/provisioning/datasources/reload. Пароль раскрывается внутри контейнера. Успех засчитывается только по текстуDatasources config reloaded(строка изpkg/api/admin_provisioning.gov11.5.1), иначе exit 1. Заголовок авторизации проверил на проде GET-запросом/api/datasources: 200.postgres-exporter-gendesign,-tradeinи-infra, под тем же гейтомEXPORTER_PROFILE:upс явным именем сервиса сам включает его профиль.test_metrics_single_file_mounts.pyберёт одиночные маунты из обоих compose-файлов и для каждого требует путь доезда в той джобе, которая поднимает сервис: вызов скрипта с теми же аргументами или--force-recreate <сервис>. Отказ не должен глушиться|| true. Производные alertmanager.yml и alertmanager_targets.gen.yml перечислены явно. Вci.ymlbackend-фильтр теперь срабатывает и наdocker-compose.metrics-agent.yml.Тесты
docker: смотрим, что он сделал (пересоздал, не тронул или упал), а не текст скрипта. Семь сценариев: инод совпадает, инод старый, после пересоздания всё ещё старый, инод не читается, контейнер не запущен, ошибка compose, нет файла на хосте.backend/tests/ops/test_metrics_single_file_mounts.py+test_3467_prometheus_reload.pyна головеec85ea18: 20 passed (11 + 9), rc=0.tests/opsцеликом: 145 passed, 4 failed, rc=1. Упали толькоtest_2203_backup_trailer_grep_dashdash— известная проблема BSD mktemp на macOS, к этой ветке не относится.uv run python -m pytest tests/ -q -p no:cacheprovider: 5046 passed, 84 skipped, 4 failed (те жеtest_2203_*, macOS), rc=1.ruff check: All checks passed.ruff format --checkпо изменённым тестам: чисто.bash -nпо ssh-скриптам трёх джоб: ok.Фальсификация
Сломал фикс руками: сохранил копии в scratchpad, после каждого прогона восстановил и сверил
diff -q.docker exec … promtool, из проверки ответа Grafana убрал текст:ps -q … 2>/dev/null || trueиexit 0после неудачной перепроверки:postgres-exporter-infra, к вызову для-tradeinдописал|| true:Что пересоздаст деплой
ops/metrics/**и workflow). Beget: alert-ack и tg-relay пересоздаются, как и раньше. Prometheus и Loki пересоздаются только при расхождении инода, сейчас иноды совпадают, значит не пересоздадутся. Grafana перечитает датасорсы без рестарта. Poincare и Beget: alloy пересоздаётся, как и раньше. Экспортёры пересоздаются только при расхождении, сейчас его нет.backend/tests/**: пересоздаст backend, worker и beat на Poincare. Трейдин и скрейпер этот деплой не трогает. Если в gendesign-worker идёт долгая задача, её стоит проверить до мержа.Приёмка на проде (после мержа, 17–18.09.2026)
loki: … доехал до контейнера (инод …),prometheus: … доехал…,Prometheus: … reload подтверждёниGrafana: датасорсы перечитаны..docker logs gendesign-grafana --since <время деплоя>показывает записи provisioning датасорсов, аStartedAtу gendesign-grafana по-прежнему2026-09-12T11:09:20Z: датасорсы перечитаны без рестарта.postgres-exporter-{gendesign,tradein,infra}: ops/metrics/postgres/queries.yml доехал…,StartedAtу экспортёров не изменился./api/v1/status/configу Prometheus,GET /api/datasourcesу Grafana и метрики экспортёра должны отдавать новое значение. Если такой правки не будет до 01.10.2026, прогнатьworkflow_dispatchс безвредной правкой комментария в queries.yml и сверить инод иStartedAtэкспортёров.Closes #3467
Closes #3486
🤖 Generated with Claude Code