Три дашборда на границе Grafana
Часть 2 из 3.
Смотрю логи Grafana:
kubectl logs -n grafana deployment/prod-region1-grafana -c grafana --since=1h | grep -iE "provision|dashboard"
И вот оно:
{"error":"A dashboard with the same uid already exists","file":"/tmp/dashboards/MyApp/service-metrics-overview.json"}Grafana provisioning видит файл, пытается его применить, но не может - в базе уже есть дашборд с таким UID.
Кстати в некоторых версиях Grafana логи могут не содержать сам UID.
В таком случае придётся идти в API или базу данных напрямую.
У нас графана с авторизацией по SSO, у меня права, как у девелопера.
Мне лень писать заявки на админский доступ и ковырять UI интерфейс, думаю мне хватит и curl + localhost для анализа.
Ведь я знаю, что рут пароль лежит в секретах кубера.😁
Я сам себе админ 😀
Проверяю через Grafana API:
GRAFANA_PASS=$(kubectl get secret -n grafana creds-grafana-admin -o jsonpath='{.data.admin-password}' | base64 -d)
kubectl exec -n grafana deployment/prod-region1-grafana -c grafana -- curl -s -u "admin:${GRAFANA_PASS}" "http://localhost:3000/api/search?query=service%20metrics"И вижу:
-
service-metrics-overview -
service-metrics-overview-vl-
service-metrics-overview-vl-draftСука, да откуда вы берётесь.
Три версии одного дашборда.
А файл у меня один (гит, конфигмап, файл внутри пода).
Тут до меня дошло: каждый раз, когда я менял UID, provisioning создавал новую запись в базе.
А старые записи никуда не девались - они просто висели мёртвым грузом.
Теперь, когда я хочу вернуть оригинальный UID
service-metrics-overview, он уже занят старой записью.Grafana хранит дашборды в PostgreSQL. Provisioning работает так:
- видит файл с UID
- проверяет - есть ли в БД запись с таким UID?
- если есть и привязана к этому файлу - обновляет
- если есть, но привязана к другому источнику - ошибка
Это не баг, а задуманное поведение: provisioning не перезаписывает дашборды, созданные из других источников.
Лезу в базу:
# ищу primary ноду (рид реплика не даст писать)
kubectl exec -n grafana pg-monitoring-1 -c postgres -- psql -U postgres -d grafana -c "SELECT pg_is_in_recovery();"
# true = replica
kubectl exec -n grafana pg-monitoring-2 -c postgres -- psql -U postgres -d grafana -c "SELECT pg_is_in_recovery();"
# false = primary
Смотрю что там:
kubectl exec -n grafana pg-monitoring-2 -c postgres -- psql -U postgres -d grafana -c "SELECT id, uid, title, version FROM dashboard WHERE uid LIKE '%service-metrics%' ORDER BY uid;"
id | uid | title | version
------+-------------------------------------+--------------------------------------------------+---------
3781 | service-metrics-overview | Service Metrics Overview | 1
3830 | service-metrics-overview-vl | Service Metrics Overview [VictoriaLogs] | 1
3825 | service-metrics-overview-vl-draft | Service Metrics Overview [VictoriaLogs Draft] | 1
Три записи от разных этапов миграции.
Файл один.
Вот и причина.
Варианты:
1. Удалить через UI - не выйдет (я ж попробовал), "provisioned dashboard cannot be deleted"
2. Ждать - не рассосётся само
3. Рестарт пода/подов - не вариант, мне по шапке за это дадут, графана как бы на всех.
4. Принудительный reload provisioning через API:
kubectl exec -n grafana deployment/prod-region1-grafana -c grafana -- curl -s -X POST -u "admin:${GRAFANA_PASS}" "http://localhost:3000/api/admin/provisioning/dashboards/reload"Не помогло - ошибка та же, записи в БД мешают.
5. Удалить записи из базы напрямую 🤡
Выбираю последний вариант. Сначала бэкап:
kubectl exec -n grafana pg-monitoring-2 -c postgres -- pg_dump -U postgres grafana > grafana_backup_$(date +%Y%m%d_%H%M%S).sql
Затем удаление:
kubectl exec -n grafana pg-monitoring-2 -c postgres -- psql -U postgres -d grafana -c "DELETE FROM dashboard WHERE uid IN ('service-metrics-overview', 'service-metrics-overview-vl', 'service-metrics-overview-vl-draft');"DELETE 3