TL;DR

  • k6 — современный, дружественный к разработчикам инструмент для нагрузочного тестирования — пишешь тесты на JavaScript
  • Установка через brew/apt/docker, пишешь скрипты, запускаешь из CLI
  • Определяй thresholds для критериев pass/fail: время ответа, процент ошибок
  • Встроенные метрики: http_req_duration, http_reqs, iterations, vus
  • Интеграция с CI/CD, Grafana Cloud, InfluxDB для дашбордов

Идеально для: Разработчиков, DevOps, команд, которые хотят performance-тесты как код Пропусти, если: Нужен GUI для дизайна тестов или экзотические протоколы (используй JMeter)

k6 — это современный open-source инструмент нагрузочного тестирования с более чем 20,000 звёздами на GitHub, созданный для разработчиков и интеграции с CI/CD. По данным State of DevOps Report 2024, 34% организаций теперь рассматривают тестирование производительности как обязательный этап CI-пайплайна. В отличие от XML-конфигураций JMeter, k6 использует JavaScript — тесты читаемы, хранятся в системе контроля версий и проверяются в pull request-ах. Один инстанс k6 может генерировать тысячи виртуальных пользователей с минимальным потреблением памяти. Этот туториал охватывает k6 от установки до продвинутой интеграции с CI/CD: написание скриптов на JavaScript, определение порогов производительности, параметризацию через переменные окружения и визуализацию результатов в Grafana Cloud.

Твоя команда хочет performance-тесты в CI/CD. XML-файлы JMeter сложно ревьюить в PR. Тесты должны запускаться headless в контейнерах.

k6 решает эту проблему. Тесты — это JavaScript-код — читаемый, версионируемый, ревьюируемый. Запускается из CLI, интегрируется со всем, отчёты в реальном времени.

Этот туториал научит k6 от установки до интеграции с CI/CD — всё, что нужно для поиска узких мест производительности.

Что такое k6?

k6 — это open-source инструмент для нагрузочного тестирования, созданный для современных рабочих процессов разработки. Тесты на JavaScript, выполнение на Go (быстро), результаты интегрируются с инструментами наблюдаемости.

Почему k6:

  • JavaScript-тесты — используй настоящий язык, не XML
  • Developer experience — отличный CLI, понятный вывод
  • Высокая производительность — одна машина обрабатывает тысячи VUs
  • Нативная CI/CD интеграция — запускается в контейнерах
  • Расширяемый — JavaScript APIs, расширения, протоколы

Установка

# macOS
brew install k6

# Ubuntu/Debian
sudo apt update && sudo apt install k6

# Docker
docker run --rm -i grafana/k6 run - <script.js

# Windows
choco install k6

Твой первый k6-тест

Создай script.js:

import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  vus: 10,           // 10 виртуальных пользователей
  duration: '30s',   // запуск на 30 секунд
};

export default function () {
  const res = http.get('https://test.k6.io');

  check(res, {
    'status is 200': (r) => r.status === 200,
    'response time < 500ms': (r) => r.timings.duration < 500,
  });

  sleep(1);
}

Запуск:

k6 run script.js

Концепции k6

Virtual Users (VUs)

VUs — это параллельные исполнители, запускающие твою тестовую функцию.

export const options = {
  vus: 100,        // одновременные пользователи
  duration: '5m',  // продолжительность теста
};

Stages (Ramp-up/down)

Постепенное увеличение и уменьшение нагрузки.

export const options = {
  stages: [
    { duration: '2m', target: 100 },  // ramp до 100 пользователей
    { duration: '5m', target: 100 },  // держим 100
    { duration: '2m', target: 200 },  // ramp до 200
    { duration: '5m', target: 200 },  // держим 200
    { duration: '2m', target: 0 },    // ramp down
  ],
};

Thresholds

Определяй критерии pass/fail.

export const options = {
  thresholds: {
    http_req_duration: ['p(95)<500'],     // 95% запросов < 500ms
    http_req_failed: ['rate<0.01'],       // процент ошибок < 1%
    checks: ['rate>0.99'],                // 99% проверок проходят
    http_reqs: ['rate>100'],              // минимум 100 RPS
  },
};

HTTP-запросы

GET-запрос

import http from 'k6/http';

export default function () {
  // Простой GET
  const res = http.get('https://api.example.com/users');

  // GET с headers
  const res2 = http.get('https://api.example.com/users', {
    headers: {
      'Authorization': 'Bearer token123',
      'Accept': 'application/json',
    },
  });
}

POST-запрос

import http from 'k6/http';

export default function () {
  const payload = JSON.stringify({
    name: 'John Doe',
    email: 'john@example.com',
  });

  const params = {
    headers: {
      'Content-Type': 'application/json',
    },
  };

  const res = http.post('https://api.example.com/users', payload, params);
}

Другие методы

// PUT
http.put(url, payload, params);

// PATCH
http.patch(url, payload, params);

// DELETE
http.del(url, params);

// Batch-запросы (параллельно)
const responses = http.batch([
  ['GET', 'https://api.example.com/users'],
  ['GET', 'https://api.example.com/products'],
  ['GET', 'https://api.example.com/orders'],
]);

Проверки и Assertions

import { check } from 'k6';

export default function () {
  const res = http.get('https://api.example.com/users');

  check(res, {
    'status is 200': (r) => r.status === 200,
    'response has users': (r) => r.json().length > 0,
    'response time OK': (r) => r.timings.duration < 500,
    'content-type is JSON': (r) =>
      r.headers['Content-Type'].includes('application/json'),
  });
}

Тестовые данные

Переменные окружения

const baseUrl = __ENV.BASE_URL || 'https://test.k6.io';

export default function () {
  http.get(`${baseUrl}/api/users`);
}
k6 run -e BASE_URL=https://staging.example.com script.js

JSON-файл

import { SharedArray } from 'k6/data';

const users = new SharedArray('users', function () {
  return JSON.parse(open('./data.json'));
});

export default function () {
  const user = users[Math.floor(Math.random() * users.length)];
  // использовать user.username, user.password
}

CSV-данные

import papaparse from 'https://jslib.k6.io/papaparse/5.1.1/index.js';
import { SharedArray } from 'k6/data';

const csvData = new SharedArray('users', function () {
  return papaparse.parse(open('./users.csv'), { header: true }).data;
});

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

Scenarios

Продвинутые паттерны выполнения.

export const options = {
  scenarios: {
    // Постоянная нагрузка
    constant_load: {
      executor: 'constant-vus',
      vus: 50,
      duration: '5m',
    },

    // Нагрузка с ramp
    ramping_load: {
      executor: 'ramping-vus',
      startVUs: 0,
      stages: [
        { duration: '2m', target: 100 },
        { duration: '5m', target: 100 },
        { duration: '2m', target: 0 },
      ],
    },

    // Постоянный arrival rate
    constant_rate: {
      executor: 'constant-arrival-rate',
      rate: 100,
      timeUnit: '1s',
      duration: '5m',
      preAllocatedVUs: 50,
    },
  },
};

Метрики и Output

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

МетрикаОписание
http_reqsОбщее количество HTTP-запросов
http_req_durationПродолжительность запроса
http_req_failedПроцент неудачных запросов
iterationsЗавершённые итерации
vusТекущие виртуальные пользователи
data_receivedПолученные данные
data_sentОтправленные данные

Кастомные метрики

import { Counter, Trend, Rate, Gauge } from 'k6/metrics';

const orderCounter = new Counter('orders_created');
const orderDuration = new Trend('order_duration');
const orderSuccess = new Rate('order_success_rate');

export default function () {
  const start = Date.now();
  const res = http.post('https://api.example.com/orders', orderPayload);

  orderCounter.add(1);
  orderDuration.add(Date.now() - start);
  orderSuccess.add(res.status === 201);
}

Output в InfluxDB + Grafana

# Output в JSON
k6 run --out json=results.json script.js

# Output в InfluxDB
k6 run --out influxdb=http://localhost:8086/k6 script.js

Интеграция с CI/CD

GitHub Actions

name: Load Test

on:
  push:
    branches: [main]

jobs:
  k6-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Run k6 test
        uses: grafana/k6-action@v0.3.1
        with:
          filename: tests/load-test.js
          flags: --out json=results.json

      - name: Upload results
        uses: actions/upload-artifact@v4
        with:
          name: k6-results
          path: results.json

Docker

FROM grafana/k6

COPY ./tests /tests

ENTRYPOINT ["k6", "run", "/tests/script.js"]
docker build -t my-k6-tests .
docker run my-k6-tests

Thresholds в k6 автоматически определяют exit code. Если threshold не пройден, k6 возвращает exit code 99 — CI/CD пайплайн блокирует деплой автоматически, без дополнительных скриптов проверки.

ИИ в k6-тестировании

ИИ-инструменты могут помочь писать и оптимизировать k6-тесты.

Что ИИ делает хорошо:

  • Генерация тестовых скриптов из API-спецификаций
  • Создание реалистичных тестовых данных
  • Предложение значений thresholds
  • Объяснение метрик и результатов

Что всё ещё требует людей:

  • Понимание архитектуры системы
  • Установка реалистичных целей нагрузки
  • Интерпретация результатов в контексте
  • Отладка проблем производительности

Полезный промпт:

Сгенерируй k6 скрипт для нагрузочного тестирования REST API с эндпоинтами: GET /users, POST /users, GET /users/{id}. Включи stages для ramp-up до 100 VUs, thresholds для p(95) response time менее 500ms и error rate ниже 1%, checks для status codes и валидацию JSON-ответов.

“k6 изменил наш подход к нагрузочному тестированию. Когда тесты — это JavaScript-код, разработчики их пишут и поддерживают. Мы перешли от «кто-то должен запустить нагрузочный тест» к автоматическим проверкам производительности в каждом PR.” — Yuri Kan, Senior QA Lead

References: Документация k6 | Grafana Cloud k6

FAQ

Что такое k6?

k6 — это современный open-source инструмент для нагрузочного тестирования, созданный для разработчиков. Ты пишешь тесты на JavaScript, запускаешь их из командной строки и получаешь детальные метрики производительности. Созданный Grafana Labs, k6 фокусируется на developer experience, интеграции с CI/CD и высокой производительности.

k6 бесплатный?

Да, k6 open-source (k6 OSS) полностью бесплатен. Grafana Cloud k6 предлагает облачное выполнение тестов, облачное хранилище и дополнительные функции с бесплатным и платными тарифами. Для большинства случаев open-source версия предоставляет всё необходимое.

k6 или JMeter — что лучше?

k6 лучше для разработчиков и CI/CD — тесты как код (JavaScript), быстрое выполнение, хорошая интеграция с современными инструментами. JMeter лучше для GUI-дизайна тестов и поддерживает больше протоколов из коробки. k6 обычно легче изучить и поддерживать командам, знакомым с JavaScript.

Может ли k6 тестировать браузерные взаимодействия?

Да, у k6 есть экспериментальный browser module, который позволяет тестировать в реальном браузере с Chromium. Однако сила k6 — в протокольном тестировании (HTTP, WebSocket, gRPC), которое намного эффективнее для нагрузочного тестирования. Используй browser module, когда нужно тестировать страницы с JavaScript-рендерингом или сложные браузерные взаимодействия.

Как запустить k6 в Docker?

Используй официальный образ Grafana k6: docker run --rm -i grafana/k6 run - <script.js. Для локальных скриптов монтируй директорию с тестами: docker run --rm -v $(pwd):/scripts grafana/k6 run /scripts/test.js. Docker — самый простой способ запускать k6 в CI/CD пайплайнах без установки на хост-машину.

Какие метрики k6 отслеживает по умолчанию?

k6 автоматически отслеживает http_reqs (общее количество запросов), http_req_duration (время ответа), http_req_failed (процент ошибок), iterations (завершённые итерации), vus (активные виртуальные пользователи), data_received и data_sent. Можно создавать кастомные метрики с помощью типов Counter, Trend, Rate и Gauge для бизнес-специфичных измерений вроде созданных заказов или процента успешных логинов.

Смотрите также