TL;DR
- Валидируйте политики auto-scaling реальными нагрузочными тестами до production—K6 для JavaScript/TypeScript команд, Locust для Python команд
- Используйте Terraform для provisioning эфемерной инфраструктуры нагрузочного тестирования: поднять, протестировать, уничтожить—платите только за время теста
- Тестируйте минимум три сценария: устойчивая нагрузка (baseline), пиковая нагрузка (trigger auto-scaling) и восстановление (поведение scale-down)
Идеально для: Команд с auto-scaling инфраструктурой, которым нужно валидировать политики масштабирования и понимать лимиты ёмкости Не подходит если: Вы запускаете инфраструктуру фиксированной ёмкости без auto-scaling (фокусируйтесь на планировании ёмкости) Время чтения: 14 минут
Политики auto-scaling, которые работают в теории, часто отказывают под реальной нагрузкой. Политика, срабатывающая при 70% CPU, может масштабироваться слишком медленно, заставляя пользователей ждать. Или может масштабироваться слишком агрессивно, тратя бюджет. Единственный способ узнать, что ваша инфраструктура правильно обрабатывает нагрузку—протестировать её.
Для связанного тестирования инфраструктуры смотрите Стратегии Тестирования Terraform и Тестирование Сетевой Конфигурации.
Подходы с Использованием ИИ
Инструменты ИИ отлично справляются с генерацией скриптов нагрузочных тестов и анализом паттернов производительности.
Генерация сценариев нагрузочного теста K6:
Напиши скрипт нагрузочного теста K6, который валидирует поведение auto-scaling:
Целевое приложение: REST API с endpoints /api/users, /api/orders
Инфраструктура: AWS ALB + Auto Scaling Group (min: 2, max: 10, target CPU: 70%)
Включи три этапа теста:
1. Прогрев: Постепенное увеличение до 100 VUs за 2 минуты
2. Устойчивая нагрузка: Поддержание 500 VUs 10 минут (должен сработать scale-up)
3. Пик: Всплеск до 2000 VUs на 1 минуту, затем обратно к 500
4. Охлаждение: Постепенное снижение до 0 за 5 минут (должен сработать scale-down)
Добавь thresholds для:
- p95 время ответа < 500ms
- Частота ошибок < 1%
- Кастомные метрики для отслеживания событий scaling
Включи интеграцию с CloudWatch для корреляции нагрузки с количеством инстансов ASG.
Анализ поведения auto-scaling:
Проанализируй эти результаты нагрузочного теста и метрики auto-scaling:
Timeline нагрузочного теста:
- 0-2min: Рост до 100 VUs, p95=120ms
- 2-12min: 500 VUs устойчиво, p95 начался с 150ms, вырос до 800ms к минуте 8
- ASG масштабировался с 2 до 4 инстансов на минуте 6, до 6 инстансов на минуте 10
- 12-13min: Пик до 2000 VUs, p95=2500ms, частота ошибок 15%
Вопросы:
1. Политика scaling слишком медленная? Каким должно быть значение target tracking?
2. Почему latency выросла до того, как произошёл scaling?
3. Что объясняет высокую частоту ошибок во время пика?
4. Рекомендуй конкретные изменения в конфигурации auto-scaling.
Создание распределённых нагрузочных тестов Locust:
Создай нагрузочный тест Locust для flow checkout e-commerce:
1. Просмотр продуктов (70% трафика)
2. Добавление в корзину (20% трафика)
3. Checkout (10% трафика)
Включи:
- Реалистичные think times между действиями
- Обработку сессий для состояния корзины
- Кастомные метрики для каждого этапа flow
- Конфигурацию распределённого setup для запуска на Kubernetes
Покажи как запустить это с 10 worker подами для генерации 50,000 concurrent users.
Когда Использовать Разные Подходы к Тестированию
Фреймворк Принятия Решений по Стратегии Тестирования
| Тип Теста | Инструмент | Цель | Когда Запускать |
|---|---|---|---|
| Smoke test | K6/Locust | Проверить работу системы под минимальной нагрузкой | Каждый deployment |
| Load test | K6/Locust | Валидировать производительность при ожидаемой нагрузке | Еженедельно, перед релизами |
| Stress test | K6/Locust | Найти точки отказа | Ежемесячно, после изменений инфраструктуры |
| Spike test | K6/Locust | Валидировать поведение auto-scaling | После изменений политик scaling |
| Soak test | K6/Locust | Найти memory leaks, исчерпание соединений | Ежеквартально |
Чеклист Валидации Auto-Scaling
| Валидация | Что Проверять | Критерий Успеха |
|---|---|---|
| Trigger scale-up | Время от breach порога до нового инстанса | < 3 минут |
| Ёмкость scale-up | Новые инстансы обрабатывают трафик немедленно | Без отказов запросов |
| Trigger scale-down | Инстансы удаляются при снижении нагрузки | В пределах cooldown периода |
| Безопасность scale-down | Нет преждевременного завершения во время трафика | Ноль потерянных запросов |
| Максимальная ёмкость | Система обрабатывает нагрузку максимума инстансов | Соответствует SLA при макс. масштабе |
K6 для Тестирования Масштабируемости
Базовый Тест Валидации Auto-Scaling
// tests/autoscaling-validation.js
import http from 'k6/http';
import { check, sleep } from 'k6';
import { Rate, Trend } from 'k6/metrics';
// Кастомные метрики
const errorRate = new Rate('errors');
const scalingLatency = new Trend('scaling_latency');
export const options = {
scenarios: {
// Этап 1: Прогрев
warmup: {
executor: 'ramping-vus',
startVUs: 0,
stages: [
{ duration: '2m', target: 100 },
],
gracefulRampDown: '0s',
exec: 'defaultScenario',
},
// Этап 2: Устойчивая нагрузка (должен сработать scale-up)
sustained: {
executor: 'constant-vus',
vus: 500,
duration: '10m',
startTime: '2m',
exec: 'defaultScenario',
},
// Этап 3: Пик (stress test auto-scaling)
spike: {
executor: 'ramping-vus',
startVUs: 500,
stages: [
{ duration: '30s', target: 2000 },
{ duration: '1m', target: 2000 },
{ duration: '30s', target: 500 },
],
startTime: '12m',
exec: 'defaultScenario',
},
// Этап 4: Охлаждение (должен сработать scale-down)
cooldown: {
executor: 'ramping-vus',
startVUs: 500,
stages: [
{ duration: '5m', target: 0 },
],
startTime: '14m',
gracefulRampDown: '30s',
exec: 'defaultScenario',
},
},
thresholds: {
http_req_duration: ['p(95)<500'], // 95% запросов под 500ms
errors: ['rate<0.01'], // Частота ошибок под 1%
http_req_failed: ['rate<0.01'], // Неудачные запросы под 1%
},
};
const BASE_URL = __ENV.TARGET_URL || 'https://api.example.com';
export function defaultScenario() {
// Симуляция реалистичного использования API
const endpoints = [
{ path: '/api/users', weight: 0.5 },
{ path: '/api/orders', weight: 0.3 },
{ path: '/api/products', weight: 0.2 },
];
const random = Math.random();
let cumulative = 0;
let selectedEndpoint = endpoints[0].path;
for (const endpoint of endpoints) {
cumulative += endpoint.weight;
if (random <= cumulative) {
selectedEndpoint = endpoint.path;
break;
}
}
const response = http.get(`${BASE_URL}${selectedEndpoint}`);
const success = check(response, {
'status is 200': (r) => r.status === 200,
'response time < 500ms': (r) => r.timings.duration < 500,
});
errorRate.add(!success);
// Реалистичное время ожидания
sleep(Math.random() * 2 + 1);
}
Locust для Тестирования Масштабируемости
Конфигурация Распределённого Нагрузочного Теста
# locustfile.py
from locust import HttpUser, task, between, events
from locust.runners import MasterRunner
import time
import logging
class WebsiteUser(HttpUser):
wait_time = between(1, 3)
def on_start(self):
"""Инициализация сессии пользователя."""
self.client.headers = {'Content-Type': 'application/json'}
@task(5)
def browse_products(self):
"""70% трафика - Просмотр продуктов."""
with self.client.get("/api/products", catch_response=True) as response:
if response.status_code == 200:
response.success()
else:
response.failure(f"Got status {response.status_code}")
@task(2)
def view_product_detail(self):
"""20% трафика - Просмотр деталей продукта."""
product_id = self.get_random_product_id()
self.client.get(f"/api/products/{product_id}")
@task(1)
def checkout_flow(self):
"""10% трафика - Полный flow checkout."""
# Добавление в корзину
self.client.post("/api/cart", json={
"product_id": self.get_random_product_id(),
"quantity": 1
})
# Checkout
with self.client.post("/api/checkout", json={
"payment_method": "card"
}, catch_response=True) as response:
if response.status_code in [200, 201]:
response.success()
elif response.status_code == 503:
response.failure("Сервис недоступен - проблема scaling?")
def get_random_product_id(self):
import random
return random.randint(1, 1000)
# Кастомные метрики для анализа scaling
@events.request.add_listener
def track_response_time(request_type, name, response_time, response_length, **kwargs):
if response_time > 1000: # Логирование медленных запросов
logging.warning(f"Медленный запрос: {name} занял {response_time}ms")
Kubernetes Deployment для Распределённого Locust
# locust-master.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: locust-master
spec:
replicas: 1
selector:
matchLabels:
app: locust
role: master
template:
metadata:
labels:
app: locust
role: master
spec:
containers:
- name: locust
image: locustio/locust:2.20.0
args:
- --master
- -f
- /mnt/locust/locustfile.py
- --host
- $(TARGET_HOST)
ports:
- containerPort: 8089
- containerPort: 5557
---
# locust-worker.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: locust-worker
spec:
replicas: 10 # 10 workers для распределённого тестирования
selector:
matchLabels:
app: locust
role: worker
template:
metadata:
labels:
app: locust
role: worker
spec:
containers:
- name: locust
image: locustio/locust:2.20.0
args:
- --worker
- --master-host=locust-master
- -f
- /mnt/locust/locustfile.py
Terraform для Инфраструктуры Нагрузочного Тестирования
Эфемерная Среда Нагрузочного Тестирования
# modules/load-test-infra/main.tf
variable "run_load_test" {
description = "Установить в true для provisioning инфраструктуры тестирования"
type = bool
default = false
}
variable "worker_count" {
description = "Количество K6/Locust workers"
type = number
default = 5
}
# ECS кластер для генераторов нагрузки
resource "aws_ecs_cluster" "load_test" {
count = var.run_load_test ? 1 : 0
name = "load-test-cluster"
setting {
name = "containerInsights"
value = "enabled"
}
tags = {
Purpose = "LoadTesting"
AutoClean = "true"
}
}
Интеграция CI/CD
GitHub Actions Workflow для Нагрузочного Тестирования
name: Тестирование Масштабируемости
on:
schedule:
- cron: '0 4 * * 1' # Еженедельно Понедельник 4 утра
workflow_dispatch:
inputs:
test_duration:
description: 'Длительность теста (напр., 10m, 1h)'
default: '20m'
max_vus:
description: 'Максимум виртуальных пользователей'
default: '1000'
jobs:
load-test:
runs-on: ubuntu-latest
environment: load-test
steps:
- uses: actions/checkout@v4
- name: Настройка AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.LOAD_TEST_ROLE_ARN }}
aws-region: us-east-1
- name: Setup K6
run: |
sudo apt-get update && sudo apt-get install k6
- name: Запуск нагрузочного теста
run: |
k6 run tests/autoscaling-validation.js \
--env TARGET_URL=${{ vars.TARGET_URL }} \
--duration ${{ inputs.test_duration || '20m' }} \
--vus ${{ inputs.max_vus || '1000' }} \
--out json=results/k6-results.json
Измерение Успеха
| Метрика | Цель | Как Отслеживать |
|---|---|---|
| Латентность scale-up | < 3 минут от trigger | Метрики CloudWatch ASG |
| P95 латентность во время scale | < 500ms | Результаты K6/Locust |
| Частота ошибок во время пика | < 1% | Результаты K6/Locust |
| Точность scale-down | В пределах 2x cooldown периода | Логи активности ASG |
| Эффективность затрат | Без избыточного provisioning | AWS Cost Explorer |
Сигналы, что ваше тестирование масштабируемости не работает:
- Тесты проходят, но production всё ещё имеет проблемы scaling
- Политики scaling никогда не срабатывают во время тестов (слишком низкая нагрузка)
- Тестовая среда не соответствует production (разные типы инстансов, лимиты)
- Результаты сильно варьируются между запусками тестов (непостоянный baseline)
Заключение
Эффективное тестирование масштабируемости инфраструктуры требует реалистичных сценариев и подходящих инструментов:
- Тестируйте минимум три сценария: устойчивая нагрузка, пик и восстановление
- Используйте эфемерную инфраструктуру с Terraform для экономичного тестирования
- Интегрируйте с CI/CD для регулярной валидации
- Коррелируйте метрики между результатами нагрузочных тестов и scaling инфраструктуры
- Документируйте thresholds и оповещайте при провале тестов
Ключевая идея: политики auto-scaling нуждаются в валидации под реальными условиями нагрузки. Теоретических расчётов недостаточно—тестируйте вашу инфраструктуру до того, как это сделают ваши пользователи.
Смотрите также
- Стратегии Тестирования Terraform - Основы тестирования инфраструктуры
- Тестирование Сетевой Конфигурации - Валидация способности сети обрабатывать масштаб
- Тестирование Backup и Disaster Recovery - Обеспечение работы DR на масштабе
- Тестирование Инфраструктуры AWS - Более широкие стратегии тестирования AWS
- Стратегии Тестирования Kubernetes - Тестирование оркестрации контейнеров
