中文翻译暂不可用,显示俄语原文。

Как вы деплоите LLM на spot instances в облаке?

Краткий тезис

Деплой LLM на spot instances (прерываемых экземплярах) позволяет экономить 60–90% затрат по сравнению с on-demand instances, но требует специальной архитектуры для обработки внезапных прерываний. Оптимальная стратегия — гибридная: использовать spot для batch inference (offline) и on-demand для критических real-time API. Ключевой элемент — graceful shutdown с checkpointing состояния модели, чтобы после прерывания быстро восстановить работу на другом экземпляре. Инструменты: Kubernetes с pod priority и cluster autoscaler, Terraform для управления инфраструктурой, Docker для контейнеризации, скрипты обработки сигнала SIGTERM.


1. Термины

  • Spot instances (AWS), preemptible VMs (GCP), low-priority VMs (Azure) — вычислительные ресурсы, доступные со скидкой 60–90% по сравнению с on-demand, но которые облако может отозвать в любой момент (обычно с предупреждением за 30 секунд — 2 минуты). Идеальны для fault-tolerant, stateless или batch-задач.

  • On-demand instances — стандартные виртуальные машины, работающие непрерывно по фиксированной цене. Гарантированная доступность, но дороже.

  • Preemptible — синоним spot в GCP.

  • Graceful shutdown — корректная обработка сигнала завершения (SIGTERM) с сохранением состояния (checkpointing) и освобождением ресурсов перед остановкой.

  • Checkpointing — периодическое сохранение текущего состояния модели (весов, кэша KV) и промежуточных результатов (например, для длительных batch-инференсов) в постоянное хранилище (S3, GCS, NFS).

  • Batch inferenceасинхронная обработка группы запросов без строгих требований к задержке (секунды-минуты). LLM может обрабатывать данные в режиме очереди.

  • Real-time inference — синхронные ответы с низкой задержкой (< 1 сек). Требует постоянной доступности и быстрого времени отклика.


2. Почему spot instances выгодны для LLM

LLM инференс — ресурсоёмкая задача. Использование GPU-инстансов (например, p4d, A100, H100) на on-demand может стоить $3–30+ в час. Spot предлагает скидку 60–90%:

Тип инстансаЦена on-demand (за час)Цена spot (типично)Экономия
AWS p4d.24xlarge (8×A100)$32.77~$9.83 (70%)~70%
AWS g5.2xlarge (A10G)$1.21~$0.36 (70%)~70%
GCP a2-highgpu-8g (8×A100)~$29.00~$9.28 (preemptible)~68%

Однако LLM инференс часто требует стабильности: прерывания могут нарушить ответы пользователей. Поэтому spot используют для batch inference (генерация embedding для RAG, офлайн-аналитика) или для non-critical real-time (например, для A/B тестирования). Критичные production-системы идут на on-demand.


3. Архитектура гибридного деплоя

Рекомендуемая архитектура:

  • Spot pool для batch-задач (например, ночная индексация документов, массовая генерация ответов для логов).
  • On-demand pool для real-time API, которые обслуживают пользователей.

При этом spot pool может быть primary, а on-demand — fallback для критических запросов (если spot прерван). Пример flow:

  1. Запрос приходит на API Gateway.
  2. Если запрос real-time (latency-critical) → маршрутизируется на on-demand кластер.
  3. Если запрос batch (например, большой датасет) → отправляется в очередь (SQS, RabbitMQ), обрабатывается spot-воркерами.
  4. При прерывании spot-воркер сохраняет checkpoint, и сообщение возвращается в очередь для повторной обработки на другом экземпляре.

4. Graceful shutdown и checkpointing

При получении сигнала SIGTERM (в облаке обычно даётся 30–120 секунд до остановки) процесс должен:

  1. Прекратить приём новых задач.
  2. Завершить текущую обработку, сохраняя промежуточные состояния.
  3. Сохранить checkpoint модели (если она обучалась или работала в режиме online fine-tuning) или кэш KV для длинных контекстов (если используется caching для ускорения).
  4. Записать метаданные (например, позицию в очереди) в постоянное хранилище (S3, Redis).
  5. Завершить процесс.

Пример обработчика на Python:

import signal
import sys
import boto3

def checkpoint_save(state):
    s3 = boto3.client('s3')
    s3.put_object(Bucket='llm-checkpoints', Key='state.pt', Body=state)

def shutdown_handler(signum, frame):
    print("SIGTERM received, starting graceful shutdown...")
    checkpoint_save(model.state_dict())
    # save KV cache or queue position
    queue.save_position()
    sys.exit(0)

signal.signal(signal.SIGTERM, shutdown_handler)
# основной цикл обработки
while True:
    model.infer(...)

Важно: checkpointing должно быть частым (каждые N шагов или по времени), чтобы минимизировать потери при прерывании.


5. Инструменты и конфигурация

5.1 Kubernetes + Spot

Используйте node pools с разными приоритетами:

  • Spot node pool для batch workload (label: instance-type=spot)
  • On-demand node pool для критических сервисов

Настройте pod priority и cluster autoscaler, чтобы при нехватке ресурсов низкоприоритетные pod'ы на spot вытеснялись первыми. Pod Disruption Budgets (PDB) можно использовать для минимального количества работающих реплик.

5.2 Terraform / Pulumi

Управление инфраструктурой:

resource "aws_eks_node_group" "spot" {
  cluster_name    = aws_eks_cluster.this.name
  node_group_name = "spot-llm"
  instance_types  = ["p4d.24xlarge"]
  capacity_type   = "SPOT"  # AWS
  scaling_config {
    desired_size = 2
    max_size     = 10
  }
}

5.3 Docker-образ

Контейнер должен быть stateless (всё состояние — в volumes/сетевых хранилищах). При старте загружает последний checkpoint из S3.


6. Стратегии для batch inference

Для batch-инференса (например, генерация эмбеддингов для 10 млн документов) spot идеален:

  • Запросы разбиваются на микробатчи.
  • Каждый микробатч обрабатывается на spot-инстансе.
  • Если инстанс прерван, микробатч возвращается в очередь и перезапускается на новом spot (или on-demand, если spot мало).

Cost-оптимизация: использование spot instance diversity (AWS Spot Fleet с несколькими типами инстансов: p4d, p3, g5) снижает шанс, что все будут прерваны одновременно.


7. Мониторинг и автоматическое восстановление

  • CloudWatch / Cloud Logging — логирование событий прерывания (EC2 Spot Instance Interruption Notice).
  • Lifecycle hooks (AWS Auto Scaling) — задержка перед завершением для graceful shutdown.
  • Health checks — если инстанс не ответил, перезапуск на on-demand.
  • Metrics: цена за инференс, частота прерываний, доля успешных batch-задач.

Пример скрипта для обработки interruption notice (метаданные инстанса):

# curl AWS metadata endpoint
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 60")
curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/spot/termination-time
# если ответ не пустой — начать graceful shutdown

8. Практические рекомендации

  • Не используйте spot для сервисов с SLA > 99.9% без надёжного fallback.
  • Checkpointing делайте в асинхронном режиме (даже если модель большая, сохраняйте только кэш состояния обработки, а не всю модель при каждом шаге).
  • Batch inference — идеальный кандидат: потеря одного батча не критична, можно повторить.
  • Training LLM (fine-tuning) также может использовать spot с checkpointing (каждые N шагов), но риск выше — потеря нескольких часов вычислений. Используйте spot for training только если есть бюджет на повторный запуск.
  • Используйте managed services (AWS SageMaker Batch Transform на spot, GCP Vertex AI Batch Prediction) — они уже имеют встроенную поддержку preemption.

9. Пример расчёта экономии

Допустим, production-система требует 10 GPU-инстансов (A100) для batch-задач. On-demand цена ~$3/час за инстанс = $30/час. Spot даёт $0.9/час за инстанс = $9/час. При 8-часовом batch-окне экономия в день: (30-9)*8 = $168. В месяц ~$5000. Плюс on-demand для real-time — ещё 2 инстанса = $6/час. Итого общая стоимость ~$15/час вместо $36/час (экономия 58%).


10. Выводы

Деплой LLM на spot — это баланс между стоимостью и надёжностью. Ключевые принципы:

  • Graceful shutdown с checkpointing.
  • Гибридная архитектура (spot + on-demand).
  • Мониторинг и автоматическое восстановление.
  • Использование batch для spot и real-time для on-demand.

Пет-проект для закрепления

Задача: Развернуть эмуляцию LLM инференса на spot-подобных экземплярах локально.

Инструменты: Docker, Python, AWS CLI (или эмуляция через kill сигналы).

Шаги:

  1. Напишите Python-скрипт llm_server.py, который слушает очередь (Redis/файл) и обрабатывает запросы. Каждый запрос — генерация текста (можно симулировать time.sleep(2)).
  2. Добавьте обработчик SIGTERM, который сохраняет текущий запрос в JSON-файл и завершается.
  3. Запустите скрипт в Docker-контейнере.
  4. Используйте docker kill --signal=SIGTERM <id> в случайные моменты.
  5. Напишите скрипт-оркестратор, который при завершении контейнера запускает новый, передавая незавершённый запрос (загружает checkpoint).
  6. Реализуйте простой балансировщик: если запрос real-time (метка), то шёл на всегда работающий llm-server-on-demand (другой порт).

Ожидаемый результат: Система, которая корректно обрабатывает внезапные прерывания, сохраняя прогресс, и не теряет ни одного запроса (все завершаются на другом экземпляре).


Связь с другими вопросами

ВопросТема
250Общие стратегии деплоя LLM в production
252Масштабирование LLM инференса (горизонтальное/вертикальное)
248Инфраструктура для Agentic RAG (CI/CD, инференс, кэши)
249CI/CD для RAG-систем
253Мониторинг LLM (latency, throughput, cost)
254Использование очередей (для batch inference)

Навигация