Как стать автором
Обновить

Миграция базы данных Grafana: от внутреннего хранилища к PostgreSQL

Уровень сложностиПростой
Время на прочтение5 мин
Количество просмотров2.6K

Всем доброго дня! Пишу здесь впервые. На написание меня этой статьи побудило желание рассказать людям об эффективном способе миграции от внутренней базы данных sqlite3 к внешней БД PostgreSQL. Подобной статьи на Хабре я не нашел, поэтому надеюсь будет полезно.

Я перечитал много статей на эту тему и попробовал различные варианты, но получилось у меня только с одним. Спасибо этому человеку: Oodcode. Так же расскажу про остальные способы и что из них вышло.

Предпосылки

Изначально причиной миграции стали ошибки алертов, приходящие из Grafana (~130 штук). А именно: failed to build query 'A': [sqlstore.max-retries-reached] retry 1: database is locked. Видимо столько алертов слишком сильно грузили внутреннюю БД и она редко выходила из состояния locked. Про миграцию писали как на сторонних форумах, так и на форуме Grafana, как о решении этой проблемы.

Подготовка

Grafana хранит все данные во внутренней бд sqlite3 grafana.db.

Необходимо подготовить нашу внешнюю БД Postgres и создать схему и таблицы, чтобы было куда переносить.

Поднимаем docker контейнер с Postgres 16:

docker run --name my_postgres
-e POSTGRES_DB=grafana
-e POSTGRES_USER=grafana
-e POSTGRES_PASSWORD=mypassword
-v /path/to/your/data:/var/lib/postgresql/data
-p 5432:5432
-d postgres:16

Далее необходимо остановить Grafana, временно подключить ее к нашей бд, чтобы создать схему и таблицы.

docker run --name my_grafana
-e GF_DATABASE_TYPE=postgres
-e GF_DATABASE_HOST=HOST:5432
-e GF_DATABASE_NAME=grafana
-e GF_DATABASE_USER=grafana
-e GF_DATABASE_PASSWORD=mypassword
-p 3000:3000
-d grafana/grafana

Для удобства можно подключиться к новой БД и проверить, что все создалось:

Созданные таблицы
Созданные таблицы

Пока наша Grafana остановлена, создайте бэкап grafana.db и можно вернуть Grafana в рабочее состояние.

Теперь мы имеем на руках:

  • Копию grafana.db

  • Подготовленную БД Postgres

Миграция

Способа имеется два:

Pgloader

Устанавливаем на хост pgloader:

sudo apt update
sudo apt install pgloader

Создаем файл grafana.load с таким содержанием (не забудь изменить данные для подключения Postgres):

load database
from sqlite:///path-to-grafana.db
into postgresql://grafana:mypassword@host:5432/grafana?sslmode=prefer
with data only, reset sequences
set work_mem to '16MB', maintenance_work_mem to '512 MB';

Запускаем этот конфиг:

pgloader grafana.load

По итогу у нас вылезут ошибки и это нормально. Вывод примерно такой:

2025-04-29T16:15:13.213561-04:00 ERROR Database error 23505: duplicate key value violates unique constraint "org_pkey" DETAIL: Key (id)=(1) already exists. CONTEXT: COPY org, line 1 2025-04-29T16:15:13.233584-04:00 ERROR Database error 23505: duplicate key value violates unique constraint "user_pkey1" DETAIL: Key (id)=(1) already exists. CONTEXT: COPY user, line 1 2025-04-29T16:15:13.258421-04:00 ERROR Database error 23505: duplicate key value violates unique constraint "migration_log_pkey" DETAIL: Key (id)=(1) already exists. CONTEXT: COPY migration_log, line 1 ...

Теперь, когда мы видим с какими таблицами у нас возникли ошибки при миграции данных, мы составим список. Сейчас нам необходимо полностью очистить БД Postgres, снова подключить Grafana к БД для создания схем и таблиц и остановить Grafana.

Возьмем таблицы из нашего списка, их необходимо очистить. Мой список получился такой:

TRUNCATE TABLE alert_configuration;
TRUNCATE TABLE alert_configuration_history;
TRUNCATE TABLE signing_key;
TRUNCATE TABLE"user";
TRUNCATE TABLE org;
TRUNCATE TABLE org_user;
TRUNCATE TABLE dashboard_acl;
TRUNCATE TABLE cache_data;
TRUNCATE TABLE kv_store;
TRUNCATE TABLE migration_log;
TRUNCATE TABLE server_lock;

После этого снова запускаем миграцию:

pgloader grafana.load

Утилита выдаст WARNING'и (это нормально) и итоговый отчет:

2023-05-29T15:24:21.045861-04:00 LOG report summary reset table name errors rows bytes total time --------------------------- --------- --------- --------- -------------- fetch 0 0 0.000s fetch meta data 0 63 0.044s Drop Foreign Keys 0 0 0.000s --------------------------- --------- --------- --------- -------------- "user" 0 20 4.2 kB 0.530s migration_log 0 487 81.1 kB 0.562s org 0 1 0.1 kB 0.546s dashboard_tag 0 1 0.0 kB 1.023s dashboard_provisioning 0 0 1.093s api_key 0 0 1.517s quota 0 0 1.585s star 0 5 0.0 kB 0.814s session 0 0 2.090s org_user 0 20 1.1 kB 1.070s playlist_item 0 0 2.058s dashboard 0 36 1.0 MB 1.420s alert 0 12 21.0 kB 2.549s annotation 0 4490 902.4 kB 2.831s data_source 0 2 0.5 kB 1.555s dashboard_snapshot 0 1 6.1 kB 1.968s plugin_setting 0 0 2.042s playlist 0 0 2.493s preferences 0 3 0.3 kB 2.600s alert_notification 0 6 1.6 kB 2.944s test_data 0 0 3.071s team 0 6 0.3 kB 3.533s dashboard_acl 0 12 0.7 kB 3.642s login_attempt 0 0 4.112s alert_notification_state 0 22 0.8 kB 4.214s user_auth_token 0 12 3.8 kB 4.607s temp_user 0 9 1.2 kB 4.703s annotation_tag 0 0 5.115s alert_instance 0 16 4.6 kB 5.137s alert_rule_version 0 302 548.1 kB 5.674s library_element 0 0 5.595s ngalert_configuration 0 0 6.066s data_keys 0 110 21.5 kB 6.111s role 0 28 3.1 kB 6.533s user_role 0 19 0.6 kB 6.532s query_history 0 1 0.3 kB 7.007s query_history_star 0 0 6.989s secrets 0 2 0.4 kB 7.472s entity_event 0 0 7.464s file 0 0 8.040s seed_assignment 0 0 7.973s folder 0 0 8.446s dashboard_version 0 406 14.8 MB 4.523s team_member 0 22 1.2 kB 3.185s tag 0 0 3.709s user_auth 0 19 33.9 kB 4.238s server_lock 0 4 0.2 kB 4.762s cache_data 0 0 4.839s alert_rule_tag 0 0 5.298s short_url 0 2 0.3 kB 5.343s alert_rule 0 15 26.0 kB 5.791s alert_configuration 0 1 3.1 kB 5.826s library_element_connection 0 0 6.253s kv_store 0 5 0.5 kB 6.292s permission 0 160 13.1 kB 6.720s team_role 0 6 0.2 kB 6.786s builtin_role 0 3 0.2 kB 7.238s provenance_type 0 0 7.297s alert_image 0 0 7.713s correlation 0 0 7.783s dashboard_public 0 0 8.211s file_meta 0 0 8.265s alert_configuration_history 0 19 78.7 kB 8.362s --------------------------- --------- --------- --------- -------------- COPY Threads Completion 0 4 8.694s Reset Sequences 0 55 0.837s Create Foreign Keys 0 0 0.000s Install Comments 0 0 0.000s --------------------------- --------- --------- --------- -------------- Total import time ✓ 6285 17.5 MB 9.532s

После этого можно подключить Grafana к БД Postgres и продолжать работу :)

Grafana-migrator

Этот способ намного проще, но с Grafana 11.3.5 и PostgreSQL 16 решение не сработало. Но это не мешает попробовать вам.

Это утилита из github: https://github.com/wbh1/grafana-sqlite-to-postgres

Скачиваем бинарник, делаем его исполняемым и запускаем с grafana.db:

wget https://github.com/wbh1/grafana-sqlite-to-postgres/releases/download/v2.2.5/grafana-migrate_linux_amd64-v2.2.5

chmod +x grafana-migrate_linux_amd64-v2.2.5

./grafana-migrate_linux_amd64-v2.2.5 /var/lib/grafana/grafana.db 'postgres://grafana:mypassword@localhost:5432/grafana?sslmode=disable'

Но у меня вылезала похожая ошибка:
INFO[2024-07-25T14:48:29+03:00] 📁 SQLlite file: grafana.db
INFO[2024-07-25T14:48:29+03:00] 📁 Dump directory: /tmp
INFO[2024-07-25T14:48:29+03:00] ✅ sqlite3 command exists
INFO[2024-07-25T14:48:30+03:00] ✅ sqlite3 database dumped to /tmp/grafana.sql
INFO[2024-07-25T14:48:33+03:00] ✅ CREATE statements removed from dump file
INFO[2024-07-25T14:48:43+03:00] ✅ sqlite3 dump sanitized
INFO[2024-07-25T14:48:48+03:00] ✅ migration_log statements removed
INFO[2024-07-25T14:48:49+03:00] ✅ char keyword transformed
INFO[2024-07-25T14:48:50+03:00] ✅ hex-encoded data values wrapped for insertion
FATAL[2024-07-25T14:48:51+03:00] ❌ pq: invalid input syntax for type bigint: "AbiGL-yVz" INSERT INTO "playlist" VALUES(3,'Live Managment','5m',5,'AbiGL-yVz',0,0) - failed to import dump file to Postgres.

P. S. Я бы хотел привести больше скринов и выводов из консоли, но к моменту написания статьи этого уже нет. Пару моментов позаимствовал у Oodcode и из официального репозитория grafana‑migrator.

Теги:
Хабы:
+8
Комментарии1

Публикации

Работа

DevOps инженер
31 вакансия

Ближайшие события