JMeter роками був стандартом навантажувального тестування. Але k6, розроблений Grafana Labs, активно переймає позиції — особливо серед команд з DevOps культурою і CI/CD пайплайнами.
У цьому гайді: від встановлення до першого реального тесту і інтеграції в GitHub Actions.
Чому k6, а не JMeter
| JMeter | k6 | |
|---|---|---|
| Мова скриптів | Java/Groovy/XML | JavaScript |
| Інтерфейс | GUI (важкий) | CLI + код |
| CI/CD інтеграція | Складна | Нативна |
| Ресурси | Багато RAM | Легкий |
| Протоколи | HTTP, SOAP, JMS, FTP... | HTTP, WebSocket, gRPC |
| Open-source | ✅ | ✅ |
| Grafana інтеграція | Через плагіни | Нативна |
k6 написаний на Go і виконує JS-скрипти. Він споживає набагато менше пам'яті ніж JMeter при тих самих навантаженнях.
Встановлення
1# macOS
2brew install k6
3
4# Ubuntu/Debian
5sudo gpg -k
6sudo gpg --no-default-keyring --keyring /usr/share/keyrings/k6-archive-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69
7echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list
8sudo apt-get update
9sudo apt-get install k6
10
11# Windows (через Chocolatey)
12choco install k6
13
14# Docker
15docker run --rm -i grafana/k6 run - <script.jsПерший тест
Створіть файл basic-load-test.js:
1import http from 'k6/http';
2import { check, sleep } from 'k6';
3
4// Налаштування тесту
5export const options = {
6 vus: 10, // 10 віртуальних користувачів
7 duration: '30s', // тривалість 30 секунд
8};
9
10export default function () {
11 // Виконуємо GET запит
12 const response = http.get('https://api.example.com/users');
13
14 // Перевіряємо відповідь
15 check(response, {
16 'status is 200': (r) => r.status === 200,
17 'response time < 500ms': (r) => r.timings.duration < 500,
18 'has users array': (r) => JSON.parse(r.body).users !== undefined,
19 });
20
21 sleep(1); // пауза 1 секунда між ітераціями
22}Запуск:
1k6 run basic-load-test.jsРозуміння метрик
Після виконання k6 виводить метрики:
1 /\ |‾‾| /‾‾/ /‾‾/
2 /\ / \ | |/ / / /
3 / \/ \ | ( / ‾‾\
4 / \ | |\ \ | (‾) |
5 / __________ \ |__| \__\ \_____/ .io
6
7 scenarios: (100.00%) 1 scenario, 10 max VUs, 1m0s max duration
8 default: 10 looping VUs for 30s (gracefulStop: 30s)
9
10✓ status is 200
11✓ response time < 500ms
12✓ has users array
13
14checks.........................: 100.00% ✓ 300 ✗ 0
15data_received..................: 1.2 MB 40 kB/s
16data_sent......................: 45 kB 1.5 kB/s
17http_req_blocked...............: avg=1.2ms min=1µs med=3µs max=65ms p(90)=5µs p(95)=9µs
18http_req_connecting............: avg=456µs min=0s med=0s max=23ms p(90)=0s p(95)=0s
19http_req_duration..............: avg=234ms min=98ms med=210ms max=687ms p(90)=401ms p(95)=512ms
20http_reqs......................: 300 10/s
21iteration_duration.............: avg=1.23s min=1.1s med=1.21s max=1.69s p(90)=1.41s p(95)=1.51s
22iterations.....................: 300 10/s
23vus............................: 10 min=10 max=10Ключові метрики для розуміння:
http_req_duration— час відповіді. Дивіться наp(90)іp(95)— 90-й і 95-й перцентилі. Якщоp(95) = 512ms— 95% запитів виконались швидше ніж 512мс.http_reqs— кількість запитів на секунду (RPS/TPS)checks— скільки перевірок пройшло/впалоvus— кількість активних віртуальних користувачів
Сценарії навантаження
Spike test (стрибок навантаження)
1export const options = {
2 stages: [
3 { duration: '1m', target: 10 }, // розігрів до 10 users
4 { duration: '10s', target: 200 }, // різкий стрибок до 200
5 { duration: '1m', target: 200 }, // тримаємо навантаження
6 { duration: '10s', target: 0 }, // завершення
7 ],
8};Stress test (пошук точки зламу)
1export const options = {
2 stages: [
3 { duration: '2m', target: 50 },
4 { duration: '5m', target: 50 },
5 { duration: '2m', target: 100 },
6 { duration: '5m', target: 100 },
7 { duration: '2m', target: 200 },
8 { duration: '5m', target: 200 },
9 { duration: '2m', target: 0 },
10 ],
11};Soak test (тест на витривалість)
1export const options = {
2 stages: [
3 { duration: '5m', target: 50 }, // розігрів
4 { duration: '8h', target: 50 }, // 8 годин під навантаженням
5 { duration: '5m', target: 0 }, // завершення
6 ],
7};Тестування API з авторизацією
1import http from 'k6/http';
2import { check, sleep } from 'k6';
3
4const BASE_URL = __ENV.BASE_URL || 'https://api.example.com';
5
6// Отримуємо токен один раз на початку
7export function setup() {
8 const loginResponse = http.post(`${BASE_URL}/auth/login`, JSON.stringify({
9 email: 'test@example.com',
10 password: 'testpassword',
11 }), {
12 headers: { 'Content-Type': 'application/json' },
13 });
14
15 const token = JSON.parse(loginResponse.body).access_token;
16 return { token };
17}
18
19export default function (data) {
20 const headers = {
21 'Authorization': `Bearer ${data.token}`,
22 'Content-Type': 'application/json',
23 };
24
25 // Тест на отримання профілю
26 const profileRes = http.get(`${BASE_URL}/profile`, { headers });
27 check(profileRes, {
28 'profile: status 200': (r) => r.status === 200,
29 'profile: has email': (r) => JSON.parse(r.body).email !== undefined,
30 });
31
32 sleep(Math.random() * 2 + 1); // рандомна пауза 1-3 секунди
33}Інтеграція в GitHub Actions
1# .github/workflows/performance.yml
2name: Performance Tests
3
4on:
5 push:
6 branches: [main]
7 schedule:
8 - cron: '0 6 * * 1' # кожен понеділок о 6:00
9
10jobs:
11 k6-load-test:
12 runs-on: ubuntu-latest
13 steps:
14 - uses: actions/checkout@v4
15
16 - name: Run k6 load test
17 uses: grafana/k6-action@v0.3.1
18 with:
19 filename: tests/performance/load-test.js
20 env:
21 BASE_URL: ${{ secrets.STAGING_URL }}
22 K6_CLOUD_TOKEN: ${{ secrets.K6_CLOUD_TOKEN }}
23
24 - name: Upload results
25 uses: actions/upload-artifact@v4
26 with:
27 name: k6-results
28 path: results.jsonThresholds: автоматичний фейл при порушенні SLA
1export const options = {
2 thresholds: {
3 // 95% запитів швидше за 500мс
4 http_req_duration: ['p(95)<500'],
5 // менше 1% помилок
6 http_req_failed: ['rate<0.01'],
7 // всі checks пройдені
8 checks: ['rate>0.99'],
9 },
10};Якщо threshold порушено — k6 завершується з exit code 99, CI/CD пайплайн падає. Ідеально для quality gates.
Підсумок
k6 — сучасний вибір для performance testing у 2026. Код як тест, легка CI/CD інтеграція, низьке споживання ресурсів і нативна Grafana інтеграція роблять його кращим варіантом для DevOps-орієнтованих команд.
JMeter залишається актуальним для legacy систем і де потрібна підтримка екзотичних протоколів. Але для нових проектів і команд що прагнуть "testing as code" — k6 є очевидним вибором.
Наступний крок: спробуйте запустити базовий тест на вашому staging середовищі і подивіться на перцентилі часу відповіді. Це займе 15 хвилин і дасть реальне розуміння продуктивності вашого API.