Настройка автоскейлинга GPU-инфраструктуры для AI

Проектируем и внедряем системы искусственного интеллекта: от прототипа до production-ready решения. Наша команда объединяет экспертизу в машинном обучении, дата-инжиниринге и MLOps, чтобы AI работал не в лаборатории, а в реальном бизнесе.
Показано 1 из 1 услугВсе 1566 услуг
Настройка автоскейлинга GPU-инфраструктуры для AI
Сложная
~3-5 рабочих дней
Часто задаваемые вопросы
Направления AI-разработки
Этапы разработки AI-решения
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1218
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    853
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1047
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    561
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    825

Настройка автоскейлинга GPU для AI-нагрузок

Автоскейлинг GPU — автоматическое добавление и удаление GPU-инстанций в зависимости от нагрузки. Сложнее CPU-автоскейлинга: GPU-инстанции дороже, время cold start 3–10 минут (загрузка модели), нельзя дробить GPU между сервисами.

Специфика GPU autoscaling

Cold start проблема: запуск нового GPU pod занимает 3–10 минут. За это время очередь запросов может переполниться. Решения:

  • Keepalive-инстанция (минимум 1 pod всегда работает)
  • Pre-warming: превентивный запуск при росте нагрузки до порогового значения
  • Request queuing: буферизация запросов во время скейла

GPU utilization vs request queue: GPU utilization — плохая метрика для LLM-скейлинга. Во время обработки длинного запроса GPU загружен на 100%, но новые запросы ожидают. Правильная метрика — queue depth или pending requests.

Scale-to-zero: полное отключение при отсутствии трафика. Подходит для batch workloads и dev/staging, опасно для production из-за cold start.

Kubernetes HPA с кастомными метриками

# Prometheus Adapter для кастомных метрик
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: vllm-autoscaler
  namespace: ai-serving
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: vllm-llama3
  minReplicas: 1
  maxReplicas: 8
  metrics:
    # Основная метрика: очередь ожидающих запросов
    - type: Pods
      pods:
        metric:
          name: vllm_pending_requests
        target:
          type: AverageValue
          averageValue: "5"          # скейл при > 5 запросов в очереди на pod

    # Дополнительная: GPU utilization (для scale-down)
    - type: Pods
      pods:
        metric:
          name: nvidia_gpu_duty_cycle
        target:
          type: AverageValue
          averageValue: "70"         # scale-down при < 70% утилизации

  behavior:
    scaleUp:
      stabilizationWindowSeconds: 30     # быстрый scale-up
      policies:
        - type: Pods
          value: 2
          periodSeconds: 60              # +2 пода каждую минуту
    scaleDown:
      stabilizationWindowSeconds: 600    # медленный scale-down (10 минут)
      policies:
        - type: Pods
          value: 1
          periodSeconds: 300             # -1 pod каждые 5 минут

KEDA для event-driven autoscaling

KEDA (Kubernetes Event-Driven Autoscaling) поддерживает скейлинг по Prometheus, Kafka, RabbitMQ, SQS:

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: vllm-keda-scaler
  namespace: ai-serving
spec:
  scaleTargetRef:
    name: vllm-llama3
  minReplicaCount: 1
  maxReplicaCount: 10
  cooldownPeriod: 300
  triggers:
    - type: prometheus
      metadata:
        serverAddress: http://prometheus.monitoring.svc.cluster.local:9090
        metricName: vllm_queue_size
        query: sum(vllm_num_requests_waiting{namespace="ai-serving"})
        threshold: "10"           # 1 replica на каждые 10 ожидающих запросов

    - type: prometheus
      metadata:
        serverAddress: http://prometheus.monitoring.svc.cluster.local:9090
        metricName: request_rate
        query: rate(http_requests_total{job="vllm"}[2m])
        threshold: "20"           # дополнительный триггер по RPS

Cloud-native autoscaling

AWS Auto Scaling Group для GPU инстанций:

import boto3

autoscaling = boto3.client('autoscaling', region_name='us-east-1')

# Создание scaling policy
autoscaling.put_scaling_policy(
    AutoScalingGroupName='llm-gpu-asg',
    PolicyName='scale-on-queue-depth',
    PolicyType='TargetTrackingScaling',
    TargetTrackingConfiguration={
        'CustomizedMetricSpecification': {
            'MetricName': 'LLMQueueDepth',
            'Namespace': 'Custom/LLMMetrics',
            'Statistic': 'Average',
        },
        'TargetValue': 5.0,
        'ScaleInCooldown': 300,
        'ScaleOutCooldown': 60,
        'DisableScaleIn': False,
    }
)

Публикация кастомных метрик из vLLM

from prometheus_client import Gauge, start_http_server
import requests
import time

QUEUE_SIZE = Gauge('llm_queue_depth', 'Number of pending requests')
GPU_MEMORY = Gauge('llm_gpu_memory_used_gb', 'GPU memory usage in GB', ['gpu_id'])

def collect_metrics():
    # vLLM метрики
    response = requests.get("http://localhost:8000/metrics").text
    for line in response.split('\n'):
        if 'vllm:num_requests_waiting' in line and not line.startswith('#'):
            queue_size = float(line.split()[-1])
            QUEUE_SIZE.set(queue_size)

    # NVIDIA SMI метрики
    import subprocess
    result = subprocess.run(
        ['nvidia-smi', '--query-gpu=memory.used', '--format=csv,noheader,nounits'],
        capture_output=True, text=True
    )
    for i, mem_mb in enumerate(result.stdout.strip().split('\n')):
        GPU_MEMORY.labels(gpu_id=str(i)).set(float(mem_mb) / 1024)

start_http_server(9091)
while True:
    collect_metrics()
    time.sleep(15)

Pre-warming стратегия

class PreWarmingStrategy:
    def __init__(self, warmup_threshold: float = 0.7, warmup_lead_time: int = 180):
        self.warmup_threshold = warmup_threshold  # 70% от max queue
        self.warmup_lead_time = warmup_lead_time  # начинаем за 3 минуты

    def should_scale_up(self, current_queue: int, max_queue: int, forecast: list) -> bool:
        # Немедленный scale-up если очередь заполнена
        if current_queue / max_queue >= self.warmup_threshold:
            return True

        # Pre-warming: forecast показывает рост через 3 минуты
        future_queue = forecast[self.warmup_lead_time // 15]  # прогноз через 3 мин
        return future_queue / max_queue >= self.warmup_threshold

Сроки внедрения

Неделя 1: Настройка метрик (vLLM + DCGM exporter), Prometheus, базовый HPA

Неделя 2: KEDA, тюнинг thresholds, pre-warming логика

Неделя 3–4: Load testing, calibration скейлинг политик, документация

Месяц 2: Cost monitoring, spot/preemptible интеграция, multi-region failover