Перейти к содержимому
К программе курса
k6: нагрузочное тестирование как система
3 / 1718%

Стенды, безопасность и базовая линия

20 минут

📋 Вы точно готовы?

Обязательные знания:

  • Урок 02: понимаете типы тестов (smoke/load/stress) и требования к стендам
  • ✅ Базовое знание окружений: dev, stage, production
  • ✅ Понимание концепции CI/CD pipelines

Опционально:

  • Опыт с Docker/Kubernetes для запуска тестовых окружений
  • Доступ к pre-prod или staging окружению вашего приложения

⏱️ Estimated time:

  • Чтение + кейс: 10 минут
  • Практика (sanity-check + baseline): 10 минут
  • Итого: 20 минут

Выбор стенда

  • Dev — только быстрый feedback для разработчика. Без смысла гонять RPS.
  • Stage — для smoke/load на флоу, но часто урезаны ресурсы и отключены сторонние интеграции.
  • Pre-prod — зеркальный прод по конфигу, сюда выносим stress/spike/soak. Если его нет — делайте prod с feature flag и ограничением трафика.
  • Prod — допускается для smoke/breakpoint перед big sale, но только с feature flag, отключенными платёжными действиями и уведомлениями пользователям.

Никогда не бейте 3rd-party (платежи, CRM, рассылки) без sandbox или мока. Реальные смс/платежи во время теста — быстрый способ потерять деньги и друзей.

Проверка, что уперлись не в генератор

  • Смотрите на CPU/RAM/Network машины с k6. Если CPU > 85% или dropped_iterations появляется — это генератор, а не сервис.
  • При constant-arrival-rate держите maxVUs с запасом. Если http_req_sending/receiving растут, а сервис молчит — вероятно, уперлись в клиентскую сеть.
  • Для больших тестов используйте отдельную машину/VM только под k6, не запускайте браузеры/IDE рядом.
  • Отражайте факт использования ramp-up (warmup) в сценарии, чтобы избежать cold start в сервисах.

Подготовка данных и безопасности

  • Идемпотентность: предусмотреть очистку (teardown) или работу на тестовых ресурсах.
  • Данные платежей/PII: только synthetic или маскированные, прокинутые через SharedArray/env переменные.
  • Feature flags: отключаем побочные эффекты (письма, webhooks), включаем кэширование, которое будет в проде.
  • Управление тестовыми данными: шаблоны пользователей/заказов в фикстурах, уникальные id на итерацию (__VU + __ITER), периодический reset снапшота БД и cleanup jobs после теста, чтобы параллельные запуски не конфликтовали.

Baseline стенда

  • Фиксируем: версии сервисов, конфиги (лимиты connection pool, cache TTL), объем данных в БД, включенные интеграции, дата создания снапшота.
  • Перед тестом — здоровье стенда: алертов нет, бэкапы/cron jobs отключены, автоскейлер в нужном режиме.
  • После теста — сохраняем k6 summary + ссылку на Grafana/Prometheus + короткий вывод: «узкое место — очередь в payment-service (latency p99: +250ms), CPU 40%».

Используем k6 с опорой на стенд

// sanity-check.js — быстрый прогонищик стенда перед основным тестом
import http from "k6/http";
import { check } from "k6";
 
export const options = {
  vus: 3,
  duration: "2m",
  thresholds: {
    http_req_failed: ["rate<0.02"],
    http_req_duration: ["p(95)<800"],
  },
};
 
export default function () {
  const res = http.get(`${__ENV.BASE_URL}/health`);
  check(res, {
    "status ok": (r) => r.status === 200,
    "has build id": (r) => r.json("buildId") !== undefined,
  });
}

Запускаем sanity перед load/stress, чтобы не тратить время на некорректный стенд. Summary sanity-теста кладем рядом с основным, baseline обновляем только при стабильном состоянии.

📊 Реальный кейс: Финтех-стартап и "тест на production"

Контекст: Стартап в сфере lending (выдача микрозаймов) запланировал маркетинговую кампанию с участием знаменитости → прогноз 50x traffic spike за 2 часа.

Проблема: Единственный стенд — production. Pre-prod не существовал, staging работал на 1/10 ресурсов и без реальных данных.

Что пошло не так (первая попытка):

  1. Запустили k6 "stress test" на staging:

    • ✅ Выдержал 200 RPS (цель: 2000 RPS)
    • ❌ CPU staging-сервера: 95% (vs 25% на production при 40 RPS)
    • ❌ БД staging: 500K записей (production: 45M)
    • Вывод: Staging не репрезентативен → цифры бесполезны
  2. Решили протестировать production:

    • ⚠️ Включили feature flag load_test_mode=true
    • ⚠️ Настроили mock для SMS-провайдера... но забыли про webhook в CRM
    • 🔴 Инцидент: k6 создал 15K "заявок на займы" → CRM отправил sales team 15K лидов
    • 🔴 Sales manager: "Мы весь день обзванивали несуществующих клиентов!"
  3. Потери:

    • 8 часов работы sales team ($3K)
    • Cleanup базы: 4 часа DBA времени
    • Репутационный риск: клиенты получили email "Ваша заявка одобрена" (baч spam filters, но всё равно)

Что сделали правильно (вторая попытка):

  1. Создали minimal pre-prod за 5 дней:

    • Kubernetes namespace с production-конфигом, но 50% ресурсов
    • Snapshot production БД (45M записей) → восстановили на pre-prod
    • Настроили mocks для: SMS, CRM webhooks, платежные gateway
    • Feature flag environment=pre-prod → отключает email/push уведомления
  2. Провели sanity-check перед stress:

    // sanity-preprod.js
    export default function () {
      const res = http.post(`${BASE_URL}/api/loan/apply`, payload);
      check(res, {
        "no real SMS sent": (r) => r.json("sms_sent") === false,
        "no CRM webhook": (r) => r.json("crm_notified") === false,
        "loan created in DB": (r) => r.json("loan_id") !== null,
      });
    }
  3. Stress-тест на pre-prod:

    • ✅ Выдержали 2500 RPS (запас 25% сверх прогноза)
    • ✅ p95 loan application: 420ms (SLO: <500ms)
    • ✅ Нашли bottleneck: credit scoring service (external API rate limit 1000 req/s) → добавили circuit breaker
  4. Проверили генератор k6:

    • CPU k6-машины: 68% (норма)
    • dropped_iterations: 0
    • Network saturation: нет

Результат маркетинговой кампании:

  • Peak traffic: 2200 RPS (в прогнозе 2000)
  • p95 latency: 465ms
  • Error rate: 0.12%
  • Zero инцидентов, conversion rate +18% vs обычного дня
  • Sales team обработал реальные лиды, не тестовые

ROI:

  • Стоимость pre-prod setup: $15K (Kubernetes + snapshot restore + 5 дней работы)
  • Избежали: повторный инцидент ($10K+ потери времени + репутация), potential downtime во время кампании ($200K убытков по конверсии)
  • ROI: 14x

War story: После инцидента с CRM, CTO ввел правило: "Любой тест на production требует checklist из 12 пунктов + подпись двух senior инженеров". Через месяц всё равно создали pre-prod, потому что checklist занимал больше времени, чем поднять стенд.

Урок: "У нас нет pre-prod" — это не оправдание, а технический долг с конкретной ценой. Baseline на неподходящем стенде — это иллюзия безопасности, хуже, чем отсутствие тестов. Лучше 2 недели на minimal pre-prod, чем годы жизни без уверенности в production.

✅ Чек-лист завершения урока

После этого урока вы должны уметь:

Выбор стенда:

  • Понимать разницу между dev/stage/pre-prod/prod для нагрузочного тестирования
  • Знать, какой стенд выбрать для каждого типа теста (smoke/load/stress/soak)
  • Понимать риски тестирования на production и как их минимизировать

Безопасность и данные:

  • Настроить feature flags для отключения побочных эффектов (emails, SMS, webhooks)
  • Подготовить тестовые данные (synthetic или маскированные)
  • Убедиться, что 3rd-party интеграции отключены или используют sandbox

Проверка генератора:

  • Мониторить CPU/RAM генератора k6 (должно быть < 85%)
  • Проверять метрику dropped_iterations (должна быть 0)
  • Понимать, когда bottleneck в генераторе, а когда в сервисе

Baseline:

  • Задокументировать baseline: версии, конфиг, объем данных, дата
  • Запустить sanity-check перед основным тестом
  • Сохранить summary.json + ссылку на Grafana dashboard

Практическое задание:

  • Создайте sanity-check.js для вашего проекта (как в примере выше)
  • Запустите на staging и зафиксируйте baseline
  • Запишите: версия сервиса, конфиг БД, дата создания snapshot

Если чек-лист пройден — вы готовы к уроку 04: научимся работать с тест-данными и параметризацией.

🎯 Что дальше

Следующий урок: Урок 04: Тест-данные и параметризация

Что вы изучите:

  • Как генерировать реалистичные тест-данные для ваших сценариев
  • SharedArray для эффективного использования памяти
  • Управление пулами тестовых пользователей и сущностей
  • Parametrization patterns для масштабируемых тестов

⏱️ Estimated time: 20 минут

Связанные уроки:

Стенды, безопасность и базовая линия — k6: нагрузочное тестирование как система — Potapov.me