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

Проектуємо та впроваджуємо системи штучного інтелекту: від прототипу до production-ready рішення. Наша команда поєднує експертизу в машинному навчанні, дата-інжинірингу та MLOps, щоб AI працював не в лабораторії, а в реальному бізнесі.
Показано 1 з 1 послугУсі 1566 послуг
Налаштування автоскейлінгу GPU-інфраструктури для AI
Складна
~3-5 робочих днів
Часті питання
Напрямки AI-розробки
Етапи розробки AI-рішення
Останні роботи
  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_logo-advance_0.png
    Розробка логотипу компанії B2B Advance
    563
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831

Налаштування автоскейлінгу 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