Grafana: от новичка до Senior-разработчика

Продвинутый курс, который охватывает архитектуру Grafana, разработку плагинов, сложный алертинг, production-настройку и глубокую интеграцию с Prometheus, Loki, Tempo и базами данных. Баланс 50/50 между теорией и практикой с реальными кейсами из production-окружений крупных компаний.

1. Введение в Grafana и путь от новичка к senior-разработчику

Введение в Grafana и путь от новичка к senior-разработчику

Grafana — это платформа с открытым исходным кодом для визуализации данных, мониторинга и observability, которая за последние годы превратилась из простого инструмента построения графиков в полноценную экосистему для работы с метриками, логами и трейсами. Сегодня Grafana используется в Netflix, Uber, PayPal, Bloomberg и тысячах других компаний — от стартапов до корпораций с миллиардными оборотами.

Разница между junior и senior в Grafana — это не количество знакомых панелей. Это понимание того, почему система работает именно так, умение принимать архитектурные решения под нагрузкой и способность отлаживать проблемы, которые не гуглятся.

Что такое Grafana на самом деле

Большинство новичков воспринимают Grafana как «красивый фронтенд для Prometheus». Это принципиально неверное понимание. Grafana — это универсальный observability-хаб, который умеет:

  • подключаться к более чем 150 источникам данных через систему плагинов;
  • объединять данные из разных источников в одной панели (например, метрики из Prometheus и логи из Loki на одном дашборде);
  • выполнять трансформации данных на стороне фронтенда без изменения запросов к источнику;
  • управлять алертингом с маршрутизацией, шаблонами и интеграцией с PagerDuty, Slack, OpsGenie;
  • разворачиваться в режиме высокой доступности с несколькими репликами и общей базой данных.
  • > Grafana — это не просто дашборд. Это операционная система для observability.

    Именно поэтому на senior-позициях спрашивают не «как добавить панель», а «как организовать мониторинг для 50 микросервисов с разными командами, разными правами доступа и единым alerting-пайплайном».

    Экосистема Grafana Labs

    Чтобы понимать контекст, важно знать, что Grafana — это не только одно приложение. Grafana Labs развивает целый стек:

    | Компонент | Назначение | Аналог | |---|---|---| | Grafana | Визуализация и дашборды | Kibana, Datadog UI | | Prometheus | Метрики (pull-модель) | InfluxDB, VictoriaMetrics | | Loki | Логи (индексирование меток) | Elasticsearch, Splunk | | Tempo | Распределённые трейсы | Jaeger, Zipkin | | Mimir | Масштабируемое хранилище метрик | Thanos, Cortex | | Pyroscope | Профилирование (continuous profiling) | Parca, Polar Signals | | Grafana Agent | Универсальный коллектор | Prometheus, Fluentd |

    Весь этот стек называется LGTM (Loki, Grafana, Tempo, Mimir) — полноценная open-source альтернатива коммерческим решениям вроде Datadog или New Relic. Senior-разработчик должен понимать, как эти компоненты взаимодействуют и когда использовать каждый из них.

    Три уровня зрелости работы с Grafana

    Путь от новичка к senior можно разбить на три чётких уровня. Понимание, где вы находитесь сейчас, помогает выстроить правильный план обучения.

    Уровень 1 — Пользователь (Junior/Middle): Умеет создавать дашборды, добавлять панели, писать базовые PromQL-запросы, настраивать простые алерты. Работает с готовыми datasource-плагинами. Знает интерфейс Grafana.

    Уровень 2 — Инженер (Middle/Senior): Понимает архитектуру Grafana изнутри. Настраивает Grafana в production: HA, provisioning, RBAC, SSO. Пишет сложные запросы с трансформациями. Проектирует систему алертинга для команды. Знает, как оптимизировать производительность дашбордов.

    Уровень 3 — Эксперт (Senior/Staff): Разрабатывает собственные плагины. Проводит root cause analysis по метрикам, логам и трейсам одновременно. Проектирует observability-стратегию для всей организации. Знает внутренние механизмы Query Engine, Plugin System, Alerting Engine.

    Как устроен интерфейс Grafana изнутри

    Даже если вы уже работали с интерфейсом, важно понять структуру данных, которая за ним стоит.

    Дашборд в Grafana — это JSON-документ. Каждый дашборд хранится в базе данных Grafana (SQLite по умолчанию, PostgreSQL или MySQL в production) как JSON-строка. Когда вы нажимаете «Save», Grafana сериализует текущее состояние дашборда в JSON и сохраняет его с версионированием.

    Вот упрощённая структура JSON дашборда:

    Понимание этой структуры критично для работы с provisioning (управление дашбордами как кодом), разработки плагинов и автоматизации через Grafana API.

    Grafana API как инструмент автоматизации

    Grafana предоставляет полноценный REST API, через который можно делать всё то же самое, что и через интерфейс. Это ключевой инструмент для автоматизации в production.

    Примеры реальных сценариев использования API:

    В реальных проектах API используется для: синхронизации дашбордов между окружениями (dev → staging → prod), автоматического создания datasource при деплое нового сервиса, интеграции с CI/CD пайплайнами.

    Версии Grafana и что важно знать

    Grafana активно развивается. Версии выходят каждые несколько недель. Для senior-разработчика важно понимать ключевые вехи:

  • Grafana 7.x — введён новый Alerting Engine (Unified Alerting), появились трансформации данных.
  • Grafana 8.x — Unified Alerting стал основным, появился Grafana Agent, улучшена поддержка Loki и Tempo.
  • Grafana 9.x — переработан редактор панелей, улучшен Explore, появились Correlations (связи между метриками, логами и трейсами).
  • Grafana 10.x — новый дизайн навигации, улучшенный Scenes API для разработки плагинов, Grafana OnCall интегрирован в OSS-версию.
  • Grafana 11.x — Scenes-based dashboards, улучшенный Alerting с поддержкой recording rules, новый Query History.
  • На собеседованиях часто спрашивают про разницу между Legacy Alerting и Unified Alerting — это принципиально разные системы, и понимание этого перехода показывает глубину знаний кандидата.

    Почему Grafana выбирают крупные компании

    Реальный кейс: команда в Uber использует Grafana для мониторинга более 4000 микросервисов. Ключевые причины выбора — возможность разграничить доступ по командам через RBAC, единый интерфейс для метрик (Prometheus/M3), логов (ELK) и трейсов (Jaeger), а также возможность автоматизировать создание дашбордов через API при деплое нового сервиса.

    Другой пример: в Bloomberg Grafana интегрирована с внутренними системами через кастомные datasource-плагины, которые подключаются к проприетарным хранилищам финансовых данных. Это возможно именно благодаря открытой Plugin System.

    Что отличает senior-разработчика на собеседовании

    На middle-позиции спрашивают: «Как настроить алерт в Grafana?» На senior-позиции спрашивают: «Как спроектировать систему алертинга для 20 команд с разными on-call расписаниями, чтобы избежать alert fatigue и обеспечить правильную маршрутизацию?»

    Разница — в системном мышлении. Senior понимает не только как, но и почему и какой ценой. Он знает, что каждый дашборд с 50 панелями и интервалом обновления 5 секунд создаёт нагрузку на Prometheus, и умеет это оптимизировать. Он понимает, что RBAC в Grafana имеет ограничения на уровне папок, и проектирует структуру организации с учётом этих ограничений.

    !Путь от новичка к senior в Grafana: уровни компетенций и ключевые навыки

    Этот курс построен так, чтобы провести вас через все три уровня последовательно. Каждая следующая статья предполагает знание предыдущей и добавляет новый слой понимания — от архитектуры до разработки плагинов и подготовки к собеседованию.

    10. Оптимизация производительности Grafana при высокой нагрузке

    Оптимизация производительности Grafana при высокой нагрузке

    Grafana с 10 пользователями и Grafana с 10 000 пользователей — это принципиально разные задачи. При высокой нагрузке возникают проблемы, которые невозможно воспроизвести в dev-окружении: медленная загрузка дашбордов, таймауты запросов к datasource, перегрузка Prometheus, утечки памяти в браузере. Эта статья — практическое руководство по диагностике и устранению этих проблем.

    Профилирование: где теряется время

    Прежде чем оптимизировать, нужно измерить. Grafana предоставляет несколько инструментов для профилирования.

    Встроенные метрики Grafana

    Grafana экспортирует собственные Prometheus-метрики на /metrics. Ключевые метрики для мониторинга производительности:

    Создай дашборд «Grafana Self-Monitoring» с этими метриками — это стандартная практика в production. Grafana Labs публикует готовый дашборд для мониторинга самой Grafana на grafana.com/grafana/dashboards/3590.

    pprof: профилирование Go-процесса

    Grafana backend написан на Go и поддерживает стандартный pprof-профилировщик:

    Реальный кейс: в одной компании Grafana потребляла 8 ГБ памяти при 500 активных пользователях. Анализ heap-профиля показал утечку в кастомном datasource-плагине: каждый запрос создавал новый HTTP-клиент без закрытия. После фикса потребление памяти упало до 1.2 ГБ.

    Оптимизация запросов к Prometheus

    Медленные запросы к Prometheus — самая частая причина проблем с производительностью дашбордов.

    Query Inspector: диагностика в браузере

    В Grafana есть встроенный Query Inspector (кнопка «Inspect» → «Query» в любой панели). Он показывает:

  • Точный запрос, отправленный к datasource.
  • Время выполнения запроса.
  • Размер ответа.
  • Количество точек данных в ответе.
  • Если запрос возвращает 100 000 точек данных, но панель показывает 500 точек — это признак неоптимального step.

    Правильный выбор step

    Step — это интервал между точками данных в запросе к Prometheus. Grafana вычисляет step автоматически на основе ширины панели и временного диапазона. Но иногда нужно переопределить:

    ini [caching] enabled = true backend = redis connstr = addr=redis:6379

    [caching.encryption] enabled = true

    Плохо: обновление каждые 5 секунд для дашборда с 30 панелями

    refresh: 5s → 30 запросов каждые 5 секунд = 360 запросов/минуту

    Хорошо: обновление каждые 30 секунд

    refresh: 30s → 30 запросов каждые 30 секунд = 60 запросов/минуту json // В настройках дашборда { "options": { "lazyLoad": true } } sql -- Проверить размер таблиц в PostgreSQL SELECT schemaname, tablename, pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) AS size FROM pg_tables WHERE schemaname = 'public' ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC;

    -- Таблица dashboard_version хранит историю версий дашбордов -- Может вырасти до нескольких ГБ при активном использовании -- Grafana автоматически очищает старые версии (настраивается через dashboard_version_limit) ini [dashboards] versions_to_keep = 20 # хранить только 20 последних версий (по умолчанию: 20) min_refresh_interval = 30s # минимальный интервал обновления (защита от слишком частых запросов) yaml

    Отдельный деплой renderer

    apiVersion: apps/v1 kind: Deployment metadata: name: grafana-renderer spec: replicas: 2 # несколько реплик для параллельного рендеринга template: spec: containers: - name: renderer image: grafana/grafana-image-renderer:latest env: - name: ENABLE_METRICS value: "true" - name: RENDERING_CLUSTERING_MODE value: "browser" # переиспользовать браузер между запросами - name: RENDERING_CLUSTERING_MAX_CONCURRENCY value: "5" resources: requests: cpu: 500m memory: 1Gi limits: cpu: 2000m memory: 3Gi ini

    grafana.ini

    [rendering] server_url = http://grafana-renderer:8081/render callback_url = http://grafana:3000/ concurrent_render_request_limit = 10 # максимум параллельных рендеров ```

    Масштабирование при экстремальной нагрузке

    При тысячах одновременных пользователей горизонтальное масштабирование Grafana (добавление реплик) имеет ограничения: основным узким местом становится Prometheus, а не Grafana.

    Стратегия для экстремальной нагрузки:

  • Grafana: 5–10 реплик за load balancer, Redis для кэша и сессий.
  • Prometheus: Recording Rules для всех дорогих запросов, Thanos/Mimir для горизонтального масштабирования.
  • Query Cache: включить кэширование запросов в Grafana.
  • CDN для статики: статические ресурсы Grafana (JS, CSS) можно кэшировать в CDN.
  • Read replicas: PostgreSQL read replicas для снижения нагрузки на primary.
  • 11. Разработка плагинов: Plugin SDK, React, TypeScript и Grafana UI toolkit

    Разработка плагинов: Plugin SDK, React, TypeScript и Grafana UI toolkit

    Разработка плагинов — это то, что отличает senior Grafana-разработчика от просто опытного пользователя. Когда стандартных возможностей не хватает — кастомная визуализация для специфических данных, подключение к проприетарному API, создание корпоративного приложения поверх Grafana — нужно разрабатывать плагины.

    Экосистема разработки плагинов

    Grafana предоставляет полноценный инструментарий для разработки плагинов:

    @grafana/create-plugin — CLI для создания плагинов с нуля. Генерирует шаблон с правильной структурой, настроенным TypeScript, тестами и Docker-окружением для разработки.

    @grafana/plugin-sdk-go — Go SDK для backend-части datasource-плагинов.

    @grafana/ui — библиотека React-компонентов Grafana (кнопки, формы, таблицы, графики). Использование этой библиотеки гарантирует визуальную согласованность с интерфейсом Grafana.

    @grafana/data — типы данных и утилиты (DataFrame, FieldType, PanelPlugin и т.д.).

    @grafana/runtime — API для взаимодействия с Grafana runtime (datasource API, темы, конфигурация).

    Структура плагина

    plugin.json: манифест плагина

    id должен быть уникальным и следовать формату {author}-{name}-{type}. Для публикации в Grafana Plugin Catalog нужна регистрация на grafana.com.

    Разработка Panel Plugin

    Panel Plugin — это React-компонент, который получает данные в формате DataFrame и рендерит визуализацию.

    Базовая структура Panel Plugin

    Использование Grafana UI компонентов

    Scenes API значительно упрощает создание сложных app-плагинов с несколькими страницами, переменными и интерактивными элементами.

    Тестирование плагинов

    Публикация и подписание плагинов

    Для публикации в Grafana Plugin Catalog плагин должен быть подписан (signed). Это защита от вредоносных плагинов.

    В production никогда не используй allow_loading_unsigned_plugins для плагинов из ненадёжных источников — это потенциальная уязвимость.

    12. Создание кастомных datasource-плагинов и визуальных панелей

    Создание кастомных datasource-плагинов и визуальных панелей

    Datasource-плагин — самый сложный тип плагинов в Grafana. Он требует понимания как frontend (TypeScript/React), так и backend (Go), протокола взаимодействия между ними и формата данных DataFrame. Эта статья — практическое руководство по созданию полноценного datasource-плагина с нуля.

    Когда нужен кастомный datasource-плагин

    Стандартные сценарии:

  • Подключение к проприетарному API (внутренняя система компании, специализированная БД).
  • Существующий плагин не поддерживает нужные функции (кастомная аутентификация, специфический формат данных).
  • Нужна серверная обработка данных (вычисления, трансформации, которые нельзя сделать на frontend).
  • Реальный кейс: финансовая компания разработала datasource-плагин для подключения к Bloomberg Terminal API. Плагин выполняет аутентификацию через корпоративный SSO, запрашивает котировки и возвращает их в формате DataFrame для визуализации в стандартных панелях Grafana.

    Архитектура datasource-плагина

    Datasource-плагин состоит из двух частей:

    Frontend (TypeScript): конфигурационная форма (настройки datasource), Query Editor (интерфейс построения запросов), обработка ответов от backend.

    Backend (Go): выполнение запросов к внешней системе, аутентификация, преобразование данных в DataFrame, health check.

    Коммуникация: Frontend → Grafana Backend → (gRPC) → Plugin Backend → Внешняя система.

    Создание datasource-плагина: пошаговое руководство

    Frontend: DataSource класс

    DataSourceWithBackend — базовый класс для datasource с backend. Он автоматически маршрутизирует запросы через Grafana Data Proxy к Go backend-плагину.

    Frontend: Query Editor

    Frontend: Config Editor (настройки datasource)

    SecretInput — специальный компонент для ввода секретов. После сохранения он показывает [configured] вместо реального значения, так как Grafana не возвращает секреты на frontend.

    Backend: Go Plugin

    Запуск и отладка

    Продвинутые возможности datasource-плагинов

    Streaming: real-time данные

    Streaming позволяет создавать real-time панели, которые обновляются без периодических запросов — данные «проталкиваются» от backend к frontend через WebSocket.

    13. Интеграция Grafana с базами данных и внешними системами: PostgreSQL, ClickHouse, Elasticsearch

    Интеграция Grafana с базами данных и внешними системами: PostgreSQL, ClickHouse, Elasticsearch

    Grafana — это не только Prometheus и Loki. В реальных production-проектах часто нужно визуализировать данные из реляционных баз данных, аналитических хранилищ и поисковых систем. Каждый тип datasource имеет свои особенности, ограничения и лучшие практики.

    PostgreSQL: мощь SQL в Grafana

    PostgreSQL datasource в Grafana позволяет выполнять произвольные SQL-запросы и визуализировать результаты. Это открывает огромные возможности для бизнес-аналитики и мониторинга приложений.

    Настройка PostgreSQL datasource

    sql -- Топ-10 медленных запросов из pg_stat_statements SELECT LEFT(query, 100) as query_preview, calls, ROUND(mean_exec_time::numeric, 2) as avg_ms, ROUND(total_exec_time::numeric / 1000, 2) as total_sec, ROUND(stddev_exec_time::numeric, 2) as stddev_ms FROM pg_stat_statements WHERE calls > 100 ORDER BY mean_exec_time DESC LIMIT 10;

    -- Мониторинг размера таблиц (для Table панели) SELECT schemaname || '.' || tablename as table_name, pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) as total_size, pg_size_pretty(pg_relation_size(schemaname||'.'||tablename)) as table_size, pg_size_pretty(pg_indexes_size(schemaname||'.'||tablename)) as index_size FROM pg_tables WHERE schemaname NOT IN ('pg_catalog', 'information_schema') ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC LIMIT 20; sql -- TimescaleDB: автоматическое downsampling через continuous aggregates CREATE MATERIALIZED VIEW metrics_hourly WITH (timescaledb.continuous) AS SELECT time_bucket('1 hour', time) AS bucket, device_id, AVG(value) as avg_value, MAX(value) as max_value, MIN(value) as min_value FROM metrics GROUP BY 1, 2;

    -- В Grafana: запрос к continuous aggregate работает в разы быстрее SELECT bucket as time, avg_value as value FROM metrics_hourly WHERE device' ORDER BY 1; yaml

    provisioning/datasources/clickhouse.yml

    apiVersion: 1 datasources: - name: ClickHouse type: grafana-clickhouse-datasource url: http://clickhouse:8123 jsonData: defaultDatabase: default port: 9000 username: grafana tlsSkipVerify: false timeout: "60" queryTimeout: "60" httpHeaders: - name: X-ClickHouse-User value: grafana secureJsonData: password: __timeFilter(timestamp) GROUP BY time ORDER BY time sql -- Таблица для хранения Prometheus-метрик CREATE TABLE metrics ( date Date DEFAULT toDate(timestamp), timestamp DateTime, name LowCardinality(String), tags Array(String), value Float64 ) ENGINE = MergeTree() PARTITION BY toYYYYMM(date) ORDER BY (name, tags, timestamp) TTL date + INTERVAL 1 YEAR DELETE;

    -- Запрос: rate за последние 5 минут SELECT toStartOfMinute(timestamp) as time, (max(value) - min(value)) / 300 as rate FROM metrics WHERE name = 'http_requests_total' AND has(tags, 'job=api-server') AND {ES_PASSWORD} basicAuth: true basicAuthUser: grafana

    Найти ошибки в конкретном сервисе

    service.name:"payment-service" AND level:ERROR

    Найти медленные запросы (duration в миллисекундах)

    service.name:"api-gateway" AND http.response_time:[1000 TO *]

    Исключить health check запросы

    http.url:* NOT http.url:"/health"

    Комбинированный запрос

    (level:ERROR OR level:CRITICAL) AND service.name:("payment-service" OR "auth-service") json // Запрос через Query Editor: количество ошибок по сервисам { "metrics": [{ "type": "count", "id": "1" }], "bucketAggs": [ { "type": "date_histogram", "field": "@timestamp", "settings": { "interval": "auto" } }, { "type": "terms", "field": "service.name", "settings": { "size": "10", "order": "desc", "orderBy": "1" } } ], "query": "level:ERROR" } sql -- MySQL: группировка по времени SELECT __timeFilter(created_at) GROUP BY 1 ORDER BY 1

    -- Мониторинг MySQL через information_schema SELECT table_schema as database_name, ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) as size_mb FROM information_schema.tables GROUP BY table_schema ORDER BY size_mb DESC;

    Панель "Business Impact":

  • Запрос A (Prometheus): rate(http_requests_total[5m]) — технические метрики
  • Запрос B (PostgreSQL): SELECT COUNT(*) FROM orders WHERE created_at > NOW() - INTERVAL '5 minutes' — бизнес-метрики
  • Запрос C (Elasticsearch): count of ERROR logs — логи ошибок
  • Трансформация: Merge → одна таблица с техническими и бизнес-метриками рядом ```

    Это позволяет ответить на вопрос: «Как рост числа ошибок влияет на количество заказов?» — прямо в одной панели.

    !Попробуйте написать SQL-запрос к PostgreSQL и посмотрите, как Grafana-макросы адаптируют его к выбранному временному диапазону

    14. Мониторинг, troubleshooting и root cause analysis в production

    Мониторинг, troubleshooting и root cause analysis в production

    Знание инструментов — это половина дела. Умение применять их в условиях реального инцидента, когда давление высокое и времени мало — это то, что отличает senior-инженера. Эта статья — практическое руководство по работе с production-инцидентами через Grafana.

    Методология: структурированный подход к инцидентам

    Хаотичный troubleshooting — главная ошибка при инцидентах. Структурированный подход позволяет найти причину быстрее и не пропустить важные сигналы.

    USE Method (для инфраструктуры):

  • Utilization — насколько загружен ресурс (CPU, память, диск, сеть)?
  • Saturation — есть ли очередь ожидания (run queue, swap, disk queue)?
  • Errors — есть ли ошибки (hardware errors, packet drops, disk errors)?
  • RED Method (для сервисов):

  • Rate — сколько запросов в секунду обрабатывает сервис?
  • Errors — какой процент запросов завершается ошибкой?
  • Duration — какова латентность запросов (P50, P95, P99)?
  • Four Golden Signals (Google SRE):

  • Latency, Traffic, Errors, Saturation — расширенная версия RED.
  • Применяй эти методы последовательно: сначала RED для сервиса (что сломалось?), потом USE для инфраструктуры (почему сломалось?).

    Практический сценарий: расследование инцидента

    Разберём реальный сценарий: в 14:32 сработал алерт «P99 латентность payment-service превысила 3 секунды».

    Шаг 1: Подтверждение и масштаб

    Результат: все 3 инстанса показывают высокую латентность. Проблема началась в 14:28.

    Шаг 2: Анализ трафика и ошибок

    Результат: трафик не изменился, ошибок нет. Значит, сервис работает, но медленно. Это указывает на проблему с зависимостью (база данных, внешний API), а не с самим сервисом.

    Шаг 3: Анализ зависимостей через трейсы

    Открываем Explore → Tempo → TraceQL:

    Находим несколько медленных трейсов. В каждом из них span db.query занимает 2.5–2.8 секунды. Тег db.statement показывает: SELECT * FROM payment_history WHERE user_id = ? ORDER BY created_at DESC.

    Шаг 4: Анализ базы данных

    Видим: pg_locks_count{mode="ExclusiveLock"} резко вырос в 14:28. Одновременно смотрим логи PostgreSQL в Loki:

    В логах находим: в 14:27 запустилась миграция ALTER TABLE payment_history ADD COLUMN metadata JSONB. Эта операция заблокировала таблицу на несколько минут, вызвав очередь запросов.

    Root cause: плановая миграция базы данных без использования CONCURRENTLY заблокировала таблицу и вызвала деградацию производительности.

    Grafana Explore: профессиональная работа

    Explore — основной инструмент для интерактивного расследования. Несколько профессиональных техник:

    Split view: метрики и логи рядом

    В Explore можно открыть два datasource одновременно (кнопка «Split»). Слева — Prometheus с метриками, справа — Loki с логами. Временная шкала синхронизирована: при изменении диапазона слева он автоматически меняется справа.

    Correlations: автоматические переходы

    В Grafana настрой отображение аннотаций с тегом deploy на всех production-дашбордах. Теперь при взгляде на график сразу видно: «Вот здесь задеплоили v2.3.1, и сразу выросла латентность».

    SLO-дашборды: мониторинг надёжности

    SLO (Service Level Objective) — целевой показатель надёжности сервиса. Например: «99.9% запросов должны выполняться успешно» или «P99 латентность не должна превышать 500ms».

    Error Budget — допустимое количество ошибок за период. При SLO 99.9% за 30 дней error budget = 0.1% × 30 × 24 × 60 = 43.2 минуты даунтайма.

    Multi-window burn rate alerting — лучшая практика для SLO-алертов:

    Мониторинг самой Grafana

    Grafana должна мониторить саму себя. Ключевые метрики для дашборда «Grafana Health»:

    15. Best practices, GitOps, тестирование дашбордов и подготовка к собеседованию middle/senior

    Best practices, GitOps, тестирование дашбордов и подготовка к собеседованию middle/senior

    Финальная статья курса объединяет всё изученное в систему профессиональных практик. Здесь — не просто «делай так», а объяснение, почему именно так, с реальными примерами из production и конкретными вопросами с собеседований.

    Best Practices: организация дашбордов

    Иерархия дашбордов

    Профессиональная организация дашбордов в Grafana строится по принципу «от общего к частному»:

    Между уровнями должны быть ссылки: из Executive Overview → в Service Overview для конкретного сервиса, из Service Overview → в Service Detail при клике на аномалию.

    Naming conventions

    Единые соглашения об именовании критичны при работе в команде:

    Правила хорошего дашборда

    Практики из реальных production-проектов, проверенные временем:

  • Один дашборд — одна аудитория. Дашборд для on-call инженера и дашборд для CEO — разные дашборды.
  • Заголовок панели — это вопрос. «CPU Usage» — плохо. «Есть ли перегрузка CPU?» — лучше. Ещё лучше — добавить threshold, чтобы ответ был визуально очевиден.
  • Единицы измерения везде. Никогда не оставляй числа без единиц. 42 — что это? Байты? Миллисекунды? Запросы в секунду?
  • Описание панели. Каждая нетривиальная панель должна иметь описание (кнопка «i» в углу): что показывает, как интерпретировать, что делать при аномалии.
  • Ссылка на runbook. В описании панели или в алерте — всегда ссылка на документацию.
  • GitOps для Grafana: полный пайплайн

    GitOps-подход к управлению Grafana означает, что Git — единственный источник истины для всех конфигураций. Как отмечают практики, это обеспечивает полную историю изменений, возможность code review и автоматический деплой (habr.com).

    Структура репозитория

    CI/CD пайплайн для дашбордов

    Экспорт дашбордов из UI в Git

    ``bash #!/bin/bash

    scripts/export-dashboard.sh

    Использование: ./export-dashboard.sh <dashboard-uid> <output-file>

    DASHBOARD_UID=2

    curl -s \ -H "Authorization: Bearer GRAFANA_URL/api/dashboards/uid/OUTPUT_FILE"

    echo "Exported to __interval в запросах. База данных: PostgreSQL с read replicas, настроить max_open_conn.

    Вопросы по безопасности

    Вопрос: «Как настроить SSO с автоматическим назначением ролей на основе групп в Active Directory?»

    Правильный ответ: Через LDAP-интеграцию. В ldap.toml настраиваем group_mappings: каждая группа AD маппится на роль Grafana (Admin/Editor/Viewer). При входе пользователя Grafana запрашивает его группы из AD и назначает соответствующую роль. Роль синхронизируется при каждом входе — если пользователя убрали из группы в AD, при следующем входе он потеряет роль в Grafana.

    Чеклист готовности к senior-собеседованию

    | Область | Что нужно знать | |---|---| | Архитектура | Data Proxy, Query Engine, Plugin System, HA, leader election | | PromQL | rate/irate, histogram_quantile, binary ops, subqueries, recording rules | | LogQL | Парсинг (json/logfmt/regexp), metric queries, unwrap, оптимизация | | Alerting | Unified Alerting, Notification Policies, шаблоны, Silences, alert fatigue | | Production | HA-настройка, provisioning, GitOps, обновление без downtime | | Безопасность | RBAC, OAuth/LDAP/SAML, Auth Proxy, шифрование секретов | | Производительность | Query Cache, Recording Rules, оптимизация дашбордов, pprof | | Плагины | Plugin SDK, DataSourceWithBackend, DataFrame, Scenes API | | Observability | LGTM-стек, корреляция сигналов, SLO/SLA, error budget | | Troubleshooting | USE/RED Method, root cause analysis, Explore, Correlations |

    > Лучший способ подготовиться к собеседованию — это не заучивать ответы, а построить реальную систему мониторинга для своего проекта и столкнуться с реальными проблемами.

    Пройдя этот курс, вы получили не просто набор знаний, а системное понимание Grafana — от внутренней архитектуры до GitOps-практик. Это именно то, что отличает senior-инженера: умение видеть систему целиком, принимать обоснованные архитектурные решения и объяснять их на собеседовании.

    !Интерактивная карта знаний: проверьте свою готовность к собеседованию по всем темам курса

    2. Архитектура Grafana: backend, frontend, Query Engine и Plugin System

    Архитектура Grafana: backend, frontend, Query Engine и Plugin System

    Понимание внутренней архитектуры Grafana — это то, что отделяет инженера, который «настраивает дашборды», от инженера, который «проектирует observability-платформу». На senior-собеседованиях вопросы про архитектуру встречаются в каждом втором интервью: «Как Grafana обрабатывает запросы к datasource?», «Что происходит, когда пользователь открывает дашборд с 30 панелями?», «Как работает Data Proxy и зачем он нужен?»

    Общая архитектура: три слоя

    Grafana состоит из трёх логических слоёв, каждый из которых выполняет свою роль.

    Backend написан на Go. Он отвечает за: аутентификацию и авторизацию, хранение конфигурации в базе данных, проксирование запросов к datasource, выполнение алертинга, управление плагинами.

    Frontend написан на React + TypeScript. Он отвечает за: рендеринг дашбордов и панелей, выполнение трансформаций данных, интерфейс редактора панелей, визуализацию данных через библиотеки (D3.js, uPlot, ECharts).

    База данных (SQLite / PostgreSQL / MySQL) хранит: дашборды (в формате JSON), пользователей и роли, datasource-конфигурации (с зашифрованными паролями), настройки алертинга, аннотации.

    !Архитектура Grafana: взаимодействие backend, frontend, Query Engine и Plugin System

    Backend: как устроен Go-сервер

    Grafana backend — это монолитное Go-приложение, которое при запуске инициализирует несколько подсистем. Важно понимать каждую из них.

    HTTP Server обрабатывает все входящие запросы. Grafana использует собственный роутер на базе macaron (исторически) и постепенно мигрирует на стандартный net/http. Все API-эндпоинты начинаются с /api/.

    Database Layer использует xorm как ORM для работы с SQLite, PostgreSQL и MySQL. При старте Grafana автоматически выполняет миграции схемы базы данных — это важно понимать при обновлении версий в production.

    Secret Management — пароли и токены datasource хранятся в базе данных в зашифрованном виде. Ключ шифрования задаётся через secret_key в конфигурации. Если ключ потерян — все datasource-пароли становятся нечитаемыми. В enterprise-версии поддерживается интеграция с HashiCorp Vault и AWS KMS.

    Background Services — Grafana запускает несколько фоновых горутин: планировщик алертов, очиститель старых данных, синхронизатор provisioning-файлов.

    Data Proxy: почему запросы идут через backend

    Один из самых частых вопросов на собеседовании: «Почему браузер не обращается к Prometheus напрямую?»

    Data Proxy — это механизм, при котором все запросы к datasource проходят через Grafana backend, а не напрямую из браузера пользователя. Вот почему это правильное решение:

  • Безопасность: учётные данные datasource (логины, пароли, токены) хранятся на сервере и никогда не передаются в браузер. Пользователь не может получить пароль от Prometheus, даже имея доступ к дашборду.
  • CORS: Prometheus, InfluxDB и другие системы не настроены на приём запросов из браузеров. Data Proxy решает проблему Cross-Origin Resource Sharing.
  • Аудит: все запросы к datasource логируются на стороне Grafana, что важно для compliance.
  • Трансформация: backend может модифицировать запросы перед отправкой (например, добавлять заголовки аутентификации).
  • Поток запроса выглядит так:

    Исключение — Direct режим в datasource, когда запросы идут напрямую из браузера. Это используется редко и только в специфических сценариях (например, когда datasource доступен публично).

    Query Engine: как обрабатываются запросы

    Query Engine — это подсистема Grafana, которая оркестрирует выполнение запросов к datasource. Начиная с Grafana 8.x, Query Engine значительно усложнился благодаря появлению Query Caching, Query Splitting и Server-Side Expressions.

    Query Pipeline

    Когда пользователь открывает дашборд, для каждой панели запускается следующий пайплайн:

  • Парсинг запроса — Grafana читает конфигурацию панели и извлекает список targets (запросов к datasource).
  • Подстановка переменных — все {DB_PASSWORD}
  • [remote_cache] type = redis connstr = addr=redis-cluster:6379,pool_size=100

    [unified_alerting] ha_peers = grafana-1:9094,grafana-2:9094,grafana-3:9094 ha_listen_address = 0.0.0.0:9094 ``

    Понимание этих механизмов — обязательное требование для senior-позиции. На собеседовании могут спросить: «Что произойдёт, если в HA-кластере из трёх инстансов упадёт лидер алертинга?» Правильный ответ: другой инстанс выиграет новые выборы лидера через механизм в базе данных, и алертинг продолжит работу с небольшой задержкой (обычно 10–30 секунд).

    3. Глубокая работа с Prometheus datasource и PromQL

    Глубокая работа с Prometheus datasource и PromQL

    Prometheus — самый распространённый datasource в Grafana. По данным Grafana Labs, более 80% инстансов Grafana подключены к Prometheus. При этом большинство пользователей используют лишь 20% возможностей PromQL. На senior-собеседованиях PromQL проверяют глубоко: recording rules, subqueries, histogram_quantile, offset modifier, binary operations между метриками из разных job.

    Модель данных Prometheus: что хранится на самом деле

    Prometheus хранит временные ряды (time series). Каждый временной ряд идентифицируется уникальным набором меток (labels) — пар ключ-значение. Метрика без меток — это просто имя; метрика с метками — это конкретный временной ряд.

    Типы метрик в Prometheus:

  • Counter — монотонно возрастающий счётчик (запросы, ошибки, байты). Никогда не уменьшается, кроме перезапуска процесса.
  • Gauge — произвольное значение, которое может расти и падать (использование памяти, температура, количество горутин).
  • Histogram — распределение значений по бакетам (латентность запросов). Хранит _bucket, _sum, _count.
  • Summary — предвычисленные квантили на стороне клиента. В отличие от Histogram, квантили нельзя агрегировать между инстансами.
  • > Ключевое правило: никогда не используй Summary, если нужна агрегация по нескольким инстансам. Используй Histogram + histogram_quantile().

    PromQL: от базового к продвинутому

    Базовые запросы (выбор метрики, фильтрация по меткам) предполагаются известными. Сосредоточимся на том, что реально спрашивают на senior-собеседованиях.

    Rate vs irate: когда что использовать

    rate() вычисляет среднюю скорость изменения counter за указанный интервал. irate() вычисляет мгновенную скорость по двум последним точкам.

    Практическое правило: используй rate() для дашбордов (нужна стабильная линия), irate() для алертов на аномалии (нужна чувствительность к пикам). Интервал в rate() должен быть минимум в 4 раза больше интервала сбора метрик (scrape interval). Если scrape interval = 15s, минимальный интервал rate = 1m.

    histogram_quantile: правильное вычисление перцентилей

    Это одна из самых часто используемых и часто неправильно применяемых функций.

    Критический нюанс: sum by (le) обязателен. Если убрать sum, вы получите перцентиль для каждого инстанса отдельно, а не агрегированный. Если добавить лишние метки в by, перцентиль будет вычислен для каждой комбинации меток.

    Ещё один нюанс: histogram_quantile интерполирует значение внутри бакета линейно. Это значит, что точность результата зависит от правильной настройки бакетов. Если все запросы укладываются в бакет le="0.5", а следующий бакет le="1.0", то P99 будет где-то между 0.5 и 1.0 — не очень точно.

    Binary operations: мощь межметричных вычислений

    Binary operations позволяют выполнять арифметические и логические операции между двумя временными рядами. Это одна из самых мощных возможностей PromQL.

    При binary operations между метриками с разными наборами меток нужно использовать on() или ignoring():

    group_left() означает «один-ко-многим»: одна метрика из правой части соответствует многим из левой. group_right() — наоборот.

    Subqueries: запросы внутри запросов

    Subquery позволяет применить range-функцию к instant-вектору за прошедший период. Это полезно, когда нужно вычислить, например, максимальный rate за последний час.

    Синтаксис [1h:5m] означает: смотреть на 1 час назад, вычислять значение каждые 5 минут. Subqueries создают значительную нагрузку на Prometheus — используй их осторожно и только там, где это действительно нужно.

    Offset modifier: сравнение с прошлым

    Если результат больше 1 — трафик вырос по сравнению с прошлой неделей. Это полезно для детектирования аномалий с учётом сезонности (например, пиковая нагрузка в пятницу вечером — это норма, а не аномалия).

    Recording Rules: предвычисление дорогих запросов

    Recording Rules — это механизм Prometheus, который позволяет предвычислять сложные PromQL-выражения и сохранять результат как новую метрику. Это критически важно для производительности.

    Соглашение об именовании recording rules: level:metric:operations. Например, job:http_requests:rate5m означает: агрегация на уровне job, метрика http_requests, операция rate5m.

    Когда использовать recording rules:

  • Запрос занимает более 1–2 секунд в Prometheus.
  • Запрос используется в нескольких дашбордах или алертах.
  • Запрос содержит сложные агрегации по большому количеству временных рядов.
  • Запрос используется в алертах (алерты должны вычисляться быстро).
  • Реальный пример: в компании с 500 микросервисами запрос sum(rate(http_requests_total[5m])) по всем сервисам может занимать 3–5 секунд. С recording rule этот же запрос выполняется за миллисекунды, потому что результат уже предвычислен.

    Настройка Prometheus datasource в Grafana

    Важный параметр httpMethod: POST: по умолчанию Grafana отправляет PromQL-запросы через GET. Длинные запросы (особенно с recording rules и сложными выражениями) могут превышать лимит URL. POST решает эту проблему.

    timeInterval сообщает Grafana о scrape interval Prometheus. Grafana использует это значение для автоматического выбора шага (step) при запросах — чтобы не запрашивать данные с разрешением выше, чем они реально собираются.

    Exemplars: связь метрик с трейсами

    Exemplars — это механизм, который позволяет прикрепить к точке метрики ссылку на конкретный трейс. Например, к точке P99 латентности можно прикрепить ID трейса самого медленного запроса в этот момент.

    В Grafana exemplars отображаются как маленькие ромбики на графике. Клик по ромбику открывает соответствующий трейс в Tempo. Это мощный инструмент для root cause analysis: видишь пик латентности → кликаешь на exemplar → видишь конкретный медленный запрос в трейсе.

    Prometheus Federation и Thanos/Mimir

    В крупных инфраструктурах один Prometheus не справляется. Есть два подхода к масштабированию:

    Federation — иерархическая схема, где глобальный Prometheus собирает агрегированные метрики с локальных Prometheus-инстансов. Подходит для небольших инфраструктур.

    Thanos / Mimir — более современный подход. Thanos добавляет к Prometheus компоненты для долгосрочного хранения (в S3/GCS), глобальных запросов и дедупликации. Mimir — это полностью совместимое с Prometheus хранилище от Grafana Labs, оптимизированное для горизонтального масштабирования.

    !Интерактивный PromQL-конструктор: попробуйте разные функции и посмотрите, как меняется результат

    В Grafana datasource для Thanos настраивается так же, как для Prometheus — Thanos Query предоставляет совместимый API. Единственное отличие — нужно указать url на Thanos Query вместо Prometheus.

    4. Loki, LogQL и профессиональный анализ логов в Grafana

    Loki, LogQL и профессиональный анализ логов в Grafana

    Loki — это система хранения логов от Grafana Labs, спроектированная по принципу «Prometheus для логов». Главное отличие от Elasticsearch: Loki индексирует только метки (labels), а не содержимое логов. Это делает Loki значительно дешевле в эксплуатации, но требует другого подхода к запросам и организации данных.

    Архитектура Loki: почему она такая

    Традиционные системы логирования (Elasticsearch, Splunk) индексируют каждое слово в каждой строке лога. Это обеспечивает быстрый полнотекстовый поиск, но требует огромных ресурсов на индексирование и хранение индекса.

    Loki хранит логи в сжатых чанках (обычно в S3 или GCS) и индексирует только метки — небольшой набор пар ключ-значение, которые описывают источник лога. Поиск по содержимому выполняется через grep по сжатым данным — это медленнее, чем полнотекстовый индекс, но при правильной организации меток большинство запросов всё равно выполняются быстро.

    Реальный кейс: компания с 10 ТБ логов в месяц платила за Elasticsearch ~15 000 долл./месяц на инфраструктуру. После миграции на Loki + S3 стоимость упала до ~2 000 долл./месяц. Компромисс — некоторые сложные полнотекстовые запросы стали медленнее.

    Компоненты Loki в production

    Loki может работать в нескольких режимах:

    Monolithic mode — все компоненты в одном процессе. Подходит для небольших инсталляций (до ~50 ГБ логов в сутки).

    Simple Scalable mode — два типа процессов: read и write. Позволяет масштабировать чтение и запись независимо.

    Microservices mode — каждый компонент запускается отдельно. Используется в крупных инсталляциях (Grafana Cloud, крупные enterprise-клиенты).

    Ключевые компоненты:

  • Distributor — принимает логи от агентов, валидирует и распределяет по Ingester.
  • Ingester — буферизует логи в памяти, периодически сбрасывает в хранилище.
  • Querier — выполняет запросы, объединяя данные из Ingester и долгосрочного хранилища.
  • Query Frontend — кэширует запросы, разбивает большие запросы на части.
  • Compactor — сжимает и дедуплицирует данные в хранилище.
  • Правильная организация меток: самая важная тема

    Неправильная организация меток — главная причина проблем с производительностью Loki. Это нужно понять глубоко.

    Кардинальность (cardinality) — количество уникальных значений метки. Высокая кардинальность = много уникальных временных рядов = большой индекс = медленные запросы и высокое потребление памяти.

    Золотое правило: метки должны описывать источник лога, а не содержимое. Содержимое (user_id, request_id, IP) должно быть в теле лога и извлекаться через LogQL при запросе.

    LogQL: язык запросов Loki

    LogQL состоит из двух частей: log queries (фильтрация и поиск строк) и metric queries (агрегация логов в метрики).

    Log Queries: поиск и фильтрация

    Парсинг логов: извлечение структурированных данных

    Это ключевая возможность LogQL, которую часто недооценивают.

    Реальный кейс: у вас есть nginx-логи в формате combined. Нужно найти все запросы с латентностью более 1 секунды к конкретному endpoint:

    Metric Queries: логи как источник метрик

    unwrap — это ключевое слово, которое извлекает числовое значение из метки для использования в агрегациях. Без unwrap все metric queries считают количество строк; с unwrap — агрегируют числовые значения из полей логов.

    Настройка Loki datasource и Promtail

    derivedFields — мощная функция: Grafana автоматически ищет в каждой строке лога паттерн (например, traceID=abc123) и превращает найденное значение в кликабельную ссылку, которая открывает соответствующий трейс в Tempo. Это основа корреляции логов и трейсов.

    Promtail: агент сбора логов

    Promtail — агент, который читает логи из файлов и отправляет их в Loki. Конфигурация Promtail определяет, какие метки будут присвоены логам.

    Pipeline stages — это цепочка трансформаций, которые Promtail применяет к каждой строке лога перед отправкой в Loki. Это позволяет: парсить JSON и извлекать метки, фильтровать ненужные логи (экономия места), маскировать чувствительные данные (PII).

    Работа с логами в Grafana Explore

    Explore — это режим Grafana для интерактивного исследования данных без создания дашборда. Для логов это основной инструмент.

    Ключевые возможности Explore для Loki:

    Log volume histogram — автоматически показывает количество строк логов во времени. Позволяет быстро увидеть аномальные пики (например, резкий рост ошибок в 14:32).

    Live tail — режим реального времени, аналог tail -f. Полезен при отладке в production.

    Context — для каждой строки лога можно открыть контекст: несколько строк до и после. Это помогает понять, что происходило вокруг ошибки.

    Correlations — начиная с Grafana 9.x, можно настроить автоматические переходы между логами и метриками. Например, из строки лога с job="payment-service" перейти к дашборду этого сервиса.

    Оптимизация запросов в Loki

    Медленные запросы в Loki — частая проблема. Вот практические правила оптимизации:

    Всегда начинай с селектора меток: {app="service"} должен быть максимально специфичным. Чем меньше потоков логов выбирает селектор, тем быстрее запрос.

    Фильтры до парсинга: сначала отфильтруй строки по содержимому (|= "ERROR"), потом парси (| json). Парсинг — дорогая операция, не нужно парсить строки, которые всё равно будут отфильтрованы.

    Chunk cache: Loki кэширует чанки данных. Повторные запросы к одному временному диапазону выполняются значительно быстрее. Это важно при расследовании инцидентов: первый запрос медленный, последующие — быстрые.

    !Интерактивный LogQL-конструктор: составьте запрос к логам и посмотрите, как работают фильтры и парсинг

    5. Tempo, распределённая трассировка и полный observability-стек

    Tempo, распределённая трассировка и полный observability-стек

    Распределённая трассировка (distributed tracing) — это метод отслеживания пути запроса через несколько микросервисов. Если метрики отвечают на вопрос «что сломалось», а логи — «почему», то трейсы отвечают на вопрос «где именно и сколько времени это заняло».

    Представьте запрос к интернет-магазину: браузер → API Gateway → Auth Service → Product Service → Inventory Service → Database. Каждый переход добавляет латентность. Без трейсинга вы видите только итоговое время ответа (например, 3 секунды) и не знаете, где именно потеряно время. С трейсингом вы видите: Auth Service — 50ms, Product Service — 2400ms (вот где проблема!), Inventory Service — 200ms.

    Ключевые концепции трейсинга

    Trace — полный путь одного запроса через систему. Идентифицируется уникальным Trace ID (128-битный идентификатор).

    Span — единица работы внутри трейса. Каждый вызов сервиса, запрос к базе данных, вызов внешнего API — это отдельный span. Span содержит: имя операции, время начала и длительность, теги (метаданные), логи (события внутри span), ссылку на родительский span.

    Context Propagation — механизм передачи Trace ID между сервисами. Обычно через HTTP-заголовки (traceparent в стандарте W3C Trace Context, или X-B3-TraceId в формате Zipkin).

    Grafana Tempo: архитектура и отличия от Jaeger/Zipkin

    Grafana Tempo — это бэкенд для хранения трейсов, оптимизированный для интеграции с Grafana. Ключевые отличия от Jaeger:

    | Характеристика | Tempo | Jaeger | |---|---|---| | Хранилище | Object storage (S3, GCS, Azure) | Cassandra, Elasticsearch, Badger | | Индексирование | Только Trace ID (без полнотекстового) | Полный индекс по тегам | | Стоимость хранения | Очень низкая (S3) | Высокая (Cassandra/ES) | | Поиск по тегам | Через TraceQL или внешний индекс | Встроенный | | Интеграция с Grafana | Нативная | Через datasource-плагин |

    Tempo, как и Loki, жертвует возможностью поиска по содержимому ради низкой стоимости хранения. Поиск трейса по Trace ID — мгновенный. Поиск по тегам (например, «найди все трейсы с error=true за последний час») требует дополнительного компонента — Tempo Search или интеграции с Loki (хранить Trace ID в логах и искать через Loki).

    Настройка Tempo datasource в Grafana

    Этот конфиг делает Tempo «умным»: при просмотре трейса Grafana автоматически предлагает перейти к логам этого сервиса за тот же временной период, или к метрикам сервиса. Это и есть корреляция сигналов — основа современного observability.

    TraceQL: язык запросов к трейсам

    TraceQL — язык запросов, специфичный для Tempo (появился в Tempo 2.0). Позволяет искать трейсы по условиям на уровне span.

    Последний пример — структурный запрос (structural query). Оператор >> означает «предок-потомок»: найти трейсы, где span от api-gateway является предком span от payment-service с ошибкой. Это уникальная возможность TraceQL, которой нет в других системах трейсинга.

    OpenTelemetry: стандарт инструментирования

    OpenTelemetry (OTel) — это open-source стандарт и набор SDK для инструментирования приложений. Он заменяет проприетарные SDK Jaeger, Zipkin и другие. Grafana полностью поддерживает OTel.

    Архитектура OTel:

    OTel Collector — это промежуточный компонент, который принимает телеметрию от приложений и маршрутизирует её в нужные бэкенды. Это позволяет менять бэкенд (например, с Jaeger на Tempo) без изменения кода приложения.

    Tail-based sampling — критически важная концепция. Вместо того чтобы решать, сохранять ли трейс в начале (head-based sampling), tail sampling принимает решение после получения всего трейса. Это позволяет всегда сохранять трейсы с ошибками или высокой латентностью, даже если общий процент семплирования низкий.

    Service Map и Node Graph

    Service Map — автоматически генерируемая карта зависимостей между сервисами, построенная на основе трейсов. В Grafana она отображается через Node Graph панель.

    Для работы Service Map нужно настроить Span Metrics — компонент Tempo (или OTel Collector), который генерирует Prometheus-метрики из трейсов:

    После этого Tempo автоматически генерирует метрики вида traces_service_graph_request_total и traces_spanmetrics_duration_seconds, которые Grafana использует для построения Service Map с показателями RED (Rate, Errors, Duration) для каждого сервиса.

    Полный observability-стек: как всё связано

    Теперь соберём всё вместе. Полный LGTM-стек выглядит так:

    Сценарий root cause analysis с полным стеком:

  • Алерт: P99 латентности payment-service превысил 2 секунды.
  • Открываем дашборд payment-service в Grafana → видим рост латентности с 14:32.
  • Кликаем на точку графика → переходим в Explore → смотрим логи за этот период.
  • В логах видим: ERROR: database connection timeout. Рядом — Trace ID.
  • Кликаем на Trace ID → открывается трейс в Tempo.
  • В трейсе видим: span db.query занимает 2.3 секунды из 2.5 общих.
  • Смотрим теги span: db.statement = "SELECT * FROM orders WHERE user_id = ?", db.rows_affected = 150000.
  • Вывод: запрос без индекса сканирует 150 000 строк. Нужен индекс на user_id.
  • Весь этот путь — от алерта до конкретного SQL-запроса — занимает 5–10 минут с полным observability-стеком. Без него — часы или дни.

    !Полный LGTM observability-стек: как метрики, логи и трейсы связаны в единую систему через Grafana

    6. Продвинутые дашборды: переменные, трансформации, вложенные панели и сложная логика

    Продвинутые дашборды: переменные, трансформации, вложенные панели и сложная логика

    Разница между дашбордом новичка и дашбордом senior-инженера — не в красоте, а в функциональности и масштабируемости. Дашборд новичка работает для одного сервиса и одного окружения. Дашборд senior-инженера работает для любого сервиса в любом окружении, автоматически адаптируется к выбранному контексту и не требует дублирования при добавлении нового сервиса.

    Переменные: типы и продвинутые сценарии

    Переменные (template variables) — это параметры дашборда, которые пользователь может менять через выпадающие списки. Grafana поддерживает несколько типов переменных, и выбор правильного типа критичен.

    Query-переменные: динамические списки из datasource

    Каскадные переменные — это когда значения одной переменной зависят от другой. В примере выше job. Grafana автоматически обновляет зависимые переменные при изменении родительской.

    Важный нюанс производительности: каждая Query-переменная выполняет отдельный запрос к datasource при загрузке дашборда. Если у вас 5 переменных, это 5 дополнительных запросов. Используй refresh: On time range change вместо On dashboard load для переменных, которые не меняются часто.

    Custom и Constant переменные

    Constant-переменные полезны для хранения URL или других конфигурационных значений, которые различаются между окружениями, но не должны быть видны пользователю.

    Datasource-переменные: мультитенантные дашборды

    Это позволяет создать один дашборд, который работает с несколькими инстансами Prometheus (например, для разных регионов или клиентов). Пользователь выбирает datasource из списка, и все панели автоматически переключаются на него.

    Regex-фильтрация значений переменных

    Multi-value и All: работа с множественным выбором

    Когда переменная поддерживает множественный выбор, PromQL-запрос должен использовать regex-матчинг:

    При выборе нескольких значений Grafana подставляет их через |: job=~"service-a|service-b|service-c". При выборе «All» подставляется .*.

    Трансформации данных: мощь без изменения запросов

    Трансформации (transformations) — это операции над данными, которые выполняются в браузере после получения ответа от datasource. Это позволяет изменять представление данных без изменения запросов.

    Merge: объединение нескольких запросов

    Это полезно, когда нужно показать несколько метрик в одной таблице, но они приходят из разных запросов.

    Filter by value: динамическая фильтрация

    Organize fields: переименование и переупорядочивание колонок

    Calculate field: вычисление новых колонок

    Это позволяет вычислять производные метрики прямо в таблице без изменения PromQL-запросов.

    Group by: агрегация на стороне Grafana

    Полезно, когда datasource не поддерживает агрегацию (например, CSV-файл или SQL без GROUP BY).

    Реальный кейс: сложная трансформация

    Задача: показать таблицу с топ-10 самых медленных endpoint'ов, включая количество запросов, P99 латентность и процент ошибок.

    Панели: продвинутые типы и настройки

    Time Series: продвинутые настройки

    Time Series — основная панель для временных рядов. Важные настройки, которые часто игнорируют:

    Thresholds — пороговые значения с цветовой индикацией:

    Override — переопределение настроек для конкретных серий:

    Stat панель: правильное использование

    Stat панель показывает одно значение с опциональным sparkline. Типичная ошибка — показывать последнее значение метрики вместо агрегированного:

    Table панель: продвинутые настройки

    Column styles позволяют настроить отображение каждой колонки:

  • Числа: единицы измерения, количество знаков после запятой.
  • Цвет фона: по пороговым значениям.
  • Ссылки: кликабельные ячейки, ведущие на другой дашборд.
  • TOKEN" \ -H "Content-Type: application/json" \ -d '{ "dashboardUID": "prod-overview", "time": '"instance Direction: Horizontal Max per row: 4 ``

    Результат: Grafana автоматически создаёт отдельную панель CPU для каждого выбранного инстанса. Если выбрано 8 инстансов — 8 панелей в 2 ряда по 4. Если выбрано 3 — 3 панели в один ряд.

    Это позволяет создать один дашборд для мониторинга любого количества инстансов без ручного дублирования панелей.

    !Попробуйте настроить переменные и трансформации — и посмотрите, как дашборд адаптируется к выбранному контексту

    7. Современный Alerting Engine: правила, маршрутизация, шаблоны и уведомления

    Современный Alerting Engine: правила, маршрутизация, шаблоны и уведомления

    Unified Alerting (он же Grafana Alerting) — это полностью переработанная система алертинга, введённая в Grafana 8.x и ставшая единственной в Grafana 9.x. Она заменила как Legacy Alerting (встроенный в Grafana), так и необходимость использовать Alertmanager отдельно. Понимание архитектуры Unified Alerting — обязательное требование для senior-позиции.

    Архитектура Unified Alerting

    Unified Alerting состоит из нескольких взаимосвязанных компонентов:

    Alert Rules — определения условий, при которых должен срабатывать алерт. Хранятся в базе данных Grafana.

    Alerting Engine — планировщик, который периодически выполняет запросы из Alert Rules и оценивает условия. Работает на backend Grafana.

    Alert Instances — конкретные «экземпляры» алерта. Один Alert Rule может генерировать множество Alert Instances (например, правило «CPU > 80%» создаёт отдельный instance для каждого сервера).

    Contact Points — конфигурации каналов уведомлений (Slack, PagerDuty, Email, Telegram и т.д.).

    Notification Policies — дерево правил маршрутизации, которое определяет, какие алерты отправлять в какие Contact Points.

    Silences — временное подавление уведомлений по условиям на метках.

    Mute Timings — расписания, по которым уведомления не отправляются (например, ночью или в выходные).

    Alert Rules: типы и настройка

    Grafana-managed rules vs Data source-managed rules

    Grafana-managed rules — правила, которые Grafana выполняет сама. Поддерживают:

  • Запросы к любому datasource (Prometheus, Loki, InfluxDB, SQL).
  • Server-Side Expressions для вычислений между datasource.
  • Хранение состояния в базе данных Grafana.
  • Data source-managed rules (Mimir/Loki rules) — правила, которые выполняются непосредственно в Prometheus/Mimir/Loki. Grafana только отображает их состояние. Это предпочтительный подход для production при высокой нагрузке, так как снимает нагрузку с Grafana.

    Анатомия Alert Rule

    for duration — это период ожидания перед отправкой уведомления. Если алерт срабатывает на 3 минуты и for: 5m, уведомление не отправится. Это защита от кратковременных флуктуаций. Состояние алерта в этот период — Pending.

    noDataState — критически важный параметр. Если данные не приходят (datasource недоступен, метрика исчезла), что считать: NoData, Alerting или OK? Правильный выбор зависит от контекста: для алерта «сервис недоступен» отсутствие метрики = Alerting; для алерта «высокая нагрузка» отсутствие метрики = NoData.

    Notification Policies: дерево маршрутизации

    Notification Policies — это иерархическое дерево правил, которое определяет, куда отправлять каждый алерт. Это аналог Alertmanager routing tree, но встроенный в Grafana.

    Группировка (grouping) — алерты с одинаковыми значениями указанных меток группируются в одно уведомление. Это предотвращает «alert storm» — ситуацию, когда 100 серверов одновременно отправляют 100 отдельных уведомлений.

    Contact Points: настройка каналов уведомлений

    Slack

    Шаблоны уведомлений: Go templates

    Grafana использует Go templates для форматирования уведомлений. Это мощный механизм, позволяющий создавать информативные, контекстные сообщения.

    Доступные переменные в шаблонах:

    | Переменная | Описание | |---|---| | .Status | firing или resolved | | .Alerts.Firing | список активных алертов | | .Alerts.Resolved | список разрешённых алертов | | .CommonLabels | метки, общие для всех алертов в группе | | .CommonAnnotations | аннотации, общие для всех алертов | | .GroupLabels | метки, по которым сгруппированы алерты |

    Silences и Mute Timings: управление подавлением

    Silence — временное подавление уведомлений для алертов, соответствующих условию на метках. Создаётся вручную (например, во время планового обслуживания).

    Mute Timings — расписания подавления, которые применяются автоматически. В отличие от Silence, Mute Timings настраиваются заранее и применяются по расписанию.

    Inhibition: подавление зависимых алертов

    Inhibition — механизм, при котором один алерт подавляет другие. Например, если сервер недоступен (node_down), не нужно отправлять алерты о высоком CPU или памяти на этом сервере — они все следствие одной причины.

    Alert fatigue: как не превратить алертинг в шум

    Alert fatigue — состояние, когда команда получает так много уведомлений, что начинает их игнорировать. Это одна из главных проблем в production.

    Практические правила против alert fatigue:

  • Алерт должен требовать действия: если получив алерт, инженер не знает, что делать — алерт не нужен.
  • Каждый алерт должен иметь runbook: ссылка на документацию с инструкцией по реагированию.
  • Используй for duration: минимум 5 минут для большинства алертов. Кратковременные флуктуации не должны будить людей ночью.
  • Разделяй severity: critical = нужно проснуться ночью, warning = посмотреть завтра утром.
  • Группируй алерты: 50 серверов с высоким CPU = одно уведомление, не 50.
  • Регулярно ревьюй алерты: раз в квартал проверяй, какие алерты срабатывают чаще всего и действительно ли они нужны.
  • 8. Production-настройка Grafana: масштабирование, HA и provisioning как код

    Production-настройка Grafana: масштабирование, HA и provisioning как код

    Запустить Grafana локально — просто. Запустить её в production так, чтобы она выдерживала тысячи пользователей, не теряла данные при обновлениях и восстанавливалась после сбоев — это совсем другая задача. Эта статья — практическое руководство по production-настройке.

    Конфигурация Grafana: полный разбор grafana.ini

    Grafana конфигурируется через файл grafana.ini или переменные окружения (формат: GF_<SECTION>_<KEY>). В production предпочтительны переменные окружения — они легче управляются через Kubernetes Secrets и не требуют перезапуска при изменении через ConfigMap.

    !Попробуйте сконфигурировать Grafana для HA-режима и посмотрите, как распределяется нагрузка между инстансами

    9. Безопасность, RBAC, аутентификация и управление доступом в Grafana

    Безопасность, RBAC, аутентификация и управление доступом в Grafana

    Безопасность Grafana в production — это не просто «поставить пароль». Это многоуровневая система: аутентификация пользователей, авторизация на уровне ресурсов, шифрование данных, защита от атак и аудит действий. На senior-собеседованиях этот блок проверяют через сценарии: «Как дать команде A доступ к дашбордам, но не к datasource? Как настроить SSO с автоматическим назначением ролей?»

    Модель безопасности Grafana: три уровня

    Уровень 1 — Аутентификация: кто этот пользователь? Уровень 2 — Авторизация (RBAC): что этому пользователю разрешено? Уровень 3 — Изоляция данных: какие данные видит пользователь?

    Важно понимать, что Grafana контролирует доступ к своим ресурсам (дашборды, datasource, алерты), но не контролирует доступ к данным в самих datasource. Если пользователь имеет доступ к datasource Prometheus, он может написать любой PromQL-запрос и получить любые метрики из этого Prometheus. Для ограничения доступа к данным нужно использовать отдельные datasource с разными правами или Label-Based Access Control в Mimir/Loki.

    Аутентификация: все механизмы

    Basic Auth и Service Accounts

    Service Accounts (введены в Grafana 9.x) заменили API Keys. Это более безопасный механизм для автоматизации:

    Преимущества Service Accounts перед API Keys: привязаны к организации, имеют роль (не только Admin), можно назначать права на конкретные ресурсы, поддерживают ротацию токенов.

    OAuth 2.0: интеграция с GitHub, Google, GitLab

    role_attribute_path — это JMESPath-выражение, которое вычисляет роль пользователя на основе данных из OAuth-провайдера. В примере: если пользователь состоит в группе grafana-admins — получает роль Admin, иначе — Viewer.

    LDAP: интеграция с Active Directory

    Важный нюанс: при LDAP-аутентификации Grafana синхронизирует роли при каждом входе пользователя. Если пользователя удалили из группы grafana-admins в AD, при следующем входе он потеряет роль Admin в Grafana автоматически.

    SAML: enterprise SSO

    SAML доступен только в Grafana Enterprise и Grafana Cloud. Используется для интеграции с Okta, Azure AD, OneLogin.

    Auth Proxy: делегирование аутентификации

    Auth Proxy используется, когда перед Grafana стоит reverse proxy (nginx, Traefik, Envoy), который уже выполнил аутентификацию. Grafana доверяет заголовку X-WEBAUTH-USER и создаёт/обновляет пользователя автоматически.

    Критическая уязвимость: если Auth Proxy включён, но whitelist не настроен, любой может отправить запрос с заголовком X-WEBAUTH-USER: admin и получить доступ. Всегда настраивай whitelist.

    RBAC: модель прав доступа

    Встроенные роли

    | Роль | Возможности | |---|---| | Viewer | Просмотр дашбордов и панелей, использование Explore (если разрешено) | | Editor | Создание и редактирование дашбордов, управление плейлистами, создание алертов | | Admin | Полный доступ к организации: управление пользователями, datasource, плагинами | | Grafana Admin | Суперадмин: управление организациями, глобальные настройки |

    Права на уровне папок и дашбордов

    Grafana позволяет назначать права на конкретные папки и дашборды, переопределяя роль организации:

    Это позволяет реализовать сценарий: команда backend имеет Editor-доступ к папке "Backend Services", но только Viewer-доступ к папке "Infrastructure".

    Fine-Grained RBAC (Enterprise)

    В Grafana Enterprise доступен расширенный RBAC с кастомными ролями:

    Шифрование и защита данных

    Шифрование секретов datasource

    Grafana шифрует пароли и токены datasource с помощью AES-256 перед сохранением в базу данных. Ключ шифрования задаётся через secret_key в grafana.ini.

    Ротация ключа шифрования: если нужно сменить secret_key, нужно использовать команду grafana-cli admin rotate-data-encryption-key. Простая замена ключа в конфиге сделает все существующие секреты нечитаемыми.

    Envelope Encryption (Enterprise)

    В Grafana Enterprise поддерживается Envelope Encryption — интеграция с внешними KMS (Key Management Service):

    При этом Grafana хранит в базе данных только зашифрованные ключи данных (DEK), а мастер-ключ хранится в AWS KMS. Это соответствует требованиям SOC 2, PCI DSS и другим compliance-стандартам.

    Аудит и логирование действий

    Grafana Enterprise логирует все действия пользователей: вход/выход, создание/изменение/удаление дашбордов, изменение datasource, управление пользователями. Логи записываются в JSON-формате и могут быть отправлены в Loki или Elasticsearch для анализа.

    Сетевая безопасность: что закрыть

    allow_embedding: false — важная настройка. По умолчанию Grafana запрещает встраивание в iframe через заголовок X-Frame-Options: deny. Если нужно встроить дашборд в корпоративный портал, нужно явно разрешить это и настроить Content-Security-Policy.

    !Смоделируйте назначение прав доступа в Grafana и посмотрите, что видит каждый пользователь