ПостСредне ⏱ ~5 мин

Нагрузочное тестирование: InfluxDB и Grafana для метрик

Оглавление

В предыдущих частях я разобрал, когда гонять нагрузку, как поставить k6 и как собирать сценарии. Теперь — про то, куда складывать результаты, чтобы они не терялись в терминале, и как смотреть на них так, чтобы видеть картину, а не цифры.

Мои первые прогоны заканчивались тем, что я копировал вывод k6 из терминала в заметки. Потом хотел сравнить с прогоном недельной давности — а где тот вывод? Потерялся. Потом стал писать в CSV, но открывать их в Excel и строить графики руками — тоска. Так я пришёл к связке InfluxDB + Grafana.

Здесь расскажу, как я это настраиваю минимально — без Kubernetes, без Helm, просто Docker Compose на машине рядом с генератором.

Зачем вообще что-то кроме терминала

Терминал показывает итоговые цифры: среднее, p95, количество запросов. Но он не показывает:

  • Как менялась latency во время прогона — была ли пила, был ли рост к концу.
  • Как коррелирует рост VU с ростом ошибок.
  • Что происходило в конкретную секунду, когда всё упало.
  • Как сравнить два прогона друг с другом.

Графики отвечают на эти вопросы. Но чтобы они появились, метрики нужно куда-то складывать.

Почему не PostgreSQL с TimescaleDB

До InfluxDB я пробовал связку PostgreSQL + TimescaleDB — расширение, превращающее Postgres в базу временных рядов (кстати, компания Timescale в июне 2025 переименовалась в TigerData, но само расширение по-прежнему называется TimescaleDB). Сама по себе она хороша: hypertables, continuous aggregates, привычный SQL, не надо учить новый язык запросов.

Но с k6 всё уперлось в схему записи. Встроенного вывода в Postgres у k6 нет, работаешь через расширение xk6-output-postgres, а оно складывает сэмплы строками, где теги метрики лежат в JSONB-поле. На коротких прогонах терпимо. На 12-часовом soak-тесте с миллионами точек любая агрегация превращается в разбор JSONB по миллионам строк — база начинает подлагивать, дашборды отваливаются по таймауту, и вместо анализа результатов я чинил хранилище результатов.

InfluxDB под модель k6 заточен из коробки: каждая метрика складывается в свой measurement с отдельными полями и тегами, а схема расширяется сама, когда появляются новые метрики — ничего проектировать не надо.

Честности ради: проблема была не в TimescaleDB как таковой. Спроектируй я собственную схему — отдельные колонки вместо JSONB, hypertable, continuous aggregates — она бы справилась. Но это уже работа уровня «спроектировать и поддерживать схему БД», а мне нужно было «записал → открыл графики». Для этого сценария InfluxDB оказался проще.

InfluxDB: база для метрик

InfluxDB — хранилище временных рядов. Оно заточено под данные, где каждая точка привязана к времени: CPU в 14:03:15, latency в 14:03:16. k6 умеет писать в InfluxDB из коробки, но с нюансом.

Встроенный вывод --out influxdb работает только с InfluxDB 1.x. Для 2.x и 3.x придётся собирать k6 с расширением xk6-output-influxdb.

Мне для домашнего стенда это было избыточно, поэтому ниже ставлю 1.8: для наших задач она ничем не хуже, а связка с k6 и Grafana работает без единого лишнего шага.

Запуск через Docker Compose

Я использую простой compose-файл:

version: '3.8'
services:
  influxdb:
    image: influxdb:1.8
    ports:
      - "8086:8086"
    environment:
      - INFLUXDB_DB=k6
    volumes:
      - influxdb-data:/var/lib/influxdb

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=grafanapass
    volumes:
      - grafana-data:/var/lib/grafana

volumes:
  influxdb-data:
  grafana-data:

Запускаю:

docker-compose up -d

Через пару минут InfluxDB доступна на порту 8086, Grafana — на 3000.

База k6 создаётся автоматически из переменной INFLUXDB_DB — отдельно настраивать ничего не надо. По умолчанию 1.8 работает без авторизации, что для стенда в закрытой сети приемлемо. Если InfluxDB доступна снаружи — включите INFLUXDB_HTTP_AUTH_ENABLED и заведите пользователя.

Запуск k6 с записью в InfluxDB

k6 умеет отправлять метрики через флаг --out influxdb:

k6 run --out influxdb=http://localhost:8086/k6 script.js

Формат адреса: http://хост:порт/имя_базы. Больше ничего настраивать не нужно — k6 сам разложит метрики по measurements.

Важно: если InfluxDB на другой машине, указывайте реальный IP, а не localhost. И проверьте, что порт 8086 открыт в firewall.

Grafana: дашборды, которые я использую

После первого прогона я захожу в Grafana (admin / grafanapass), добавляю InfluxDB как datasource (тип InfluxDB, язык запросов InfluxQL, база k6) и импортирую готовый дашборд для k6. Есть официальный дашборд от Grafana Labs — ищите по ID 2587 в разделе Import.

Ключевые панели

Я обычно настраиваю такие панели:

  • RPS (requests per second) — сколько запросов в секунду обрабатывает приложение. Смотрю на плато и на провалы.
  • Response time (p50, p95, p99) — три графика одним стеком. Видно, как растёт «хвост».
  • VU (virtual users) — сколько пользователей сейчас активно. Должно совпадать с тем, что задано в скрипте.
  • HTTP errors — количество и типы ошибок по статус-кодам.
  • Data transfer — сколько данных передаётся. Полезно, если тестируете API с тяжёлыми ответами.

Свои панели для бизнес-метрик

Помимо стандартных метрик k6, я иногда добавляю кастомные метрики прямо в скрипте:

import { Trend } from 'k6/metrics';

const checkoutDuration = new Trend('checkout_duration');

export default function () {
  const start = Date.now();
  // ... сценарий оформления заказа ...
  checkoutDuration.add(Date.now() - start);
}

Эта метрика появится в InfluxDB и её можно визуализировать отдельно — например, «время оформления заказа» вместо общего response time.

Сравнение прогонов

Чтобы сравнить два прогона, я помечаю их системным тегом testid при запуске (именно --tag, а не --env: env-переменная видна только внутри скрипта, а тег приклеивается к каждой метрике):

k6 run --out influxdb=http://localhost:8086/k6 --tag testid=before-optimization script.js
k6 run --out influxdb=http://localhost:8086/k6 --tag testid=after-optimization script.js

В Grafana фильтрую по этому тегу и накладываю графики друг на друга. Сразу видно, помогла оптимизация или нет.

Что часто ломается

InfluxDB не принимает данные

Проверяю: правильный ли токен, правильная ли организация и бакет, доступен ли порт. Частая ошибка — указать localhost, когда InfluxDB в Docker, а k6 на хосте. В Docker localhost — это контейнер, а не машина.

Grafana не видит datasource

Проверяю URL InfluxDB в настройках datasource. Если Grafana тоже в Docker, использую http://influxdb:8086 (имя сервиса из docker-compose).

Слишком много данных

При больших прогонах k6 генерирует миллионы точек. InfluxDB может начать тормозить. Я ограничиваю частоту записи через переменную окружения K6_INFLUXDB_PUSH_INTERVAL=5s — k6 будет скидывать метрики пачками раз в пять секунд вместо непрерывного потока.

Минимальный рабочий набор

Чтобы получить работающую визуализацию:

  1. InfluxDB и Grafana в Docker Compose.
  2. Бакет k6 и токен записи.
  3. Grafana datasource на InfluxDB.
  4. Импортированный дашборд k6 (ID 2587).
  5. Запуск k6 с --out influxdb.
  6. Проверка, что графики появились после первого прогона.

К следующей части

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

НазадДалее

Обсуждение

Комментариев пока нет — начните тему.

Комментариев пока нет — начните тему.

Оставить комментарий

Комментарии публикуются сразу после отправки.