GPU-кластер для инференса LLM на отечественных серверах: архитектура, bottleneck'и и реальные цифры
Запустили первый production GPU-кластер на отечественных серверах под инференс LLM: делимся архитектурой, узкими местами и тем, что намерили в реальной нагрузке.
Рост спроса на локальные GPU-кластеры для инференса LLM в корпоративном секторе в H1 2025
Примерно с начала года у нескольких заказчиков из финансового и промышленного сектора появился один и тот же запрос: хотим гонять LLM локально, без облака, на своём железе, желательно отечественном. Причины у всех примерно одинаковые - ПДн, КИИ, нежелание слать внутренние документы куда-то во внешний мир. В итоге мы запустили первый такой кластер в production и теперь можем рассказать, как оно устроено и где реально болит.
Железо и отправная точка
Под задачу выбрали серверы на базе отечественных материнских плат - не буду называть конкретного вендора, скажу только, что это была не розничная сборка, а поставка через интегратора с соответствующей документацией для КИИ. GPU - NVIDIA A100 80GB, по четыре карты на узел, три узла в кластере. Да, GPU не отечественный - пока альтернатив под такую задачу с нужными характеристиками по fp16-производительности на рынке нет, берём что есть.
Сеть между узлами - 25GbE на первом этапе, без InfiniBand. Это первое место, где мы наступили на грабли, - но об этом дальше.
Стек и оркестрация
Под инференс выбрали vLLM - на момент запуска это наиболее зрелое решение с поддержкой PagedAttention и continuous batching. Поверх - Kubernetes 1.33 с поддержкой GPU через NVIDIA device plugin. Оркестрацию развернули на Deckhouse, как и на других наших кластерах.
Схема упрощённо выглядит так:
клиент -> nginx (балансировщик) -> vLLM serving pods -> GPU workers
Модели хранятся на локальном S3-совместимом хранилище (Ceph) и монтируются в поды при старте. Это добавляет задержку при холодном старте пода - загрузка модели на 70B занимает несколько минут, - поэтому под production-модели поды не скейлятся в ноль.
Автоматизацию инфраструктуры через AWX уже описывали в посте про AWX 25, кластер вписался в тот же подход с Execution Environments.
Где оказались реальные bottleneck'и
Первое - память, не вычисления. Интуитивно кажется, что GPU-кластер будет упираться в FLOPS. На деле при инференсе главный ресурс - HBM-память. 70B-модель в fp16 занимает примерно 140 ГБ только для весов, плюс KV-cache под активные сессии. Четыре A100 по 80 ГБ - 320 ГБ суммарно, и это уже не так просторно, как кажется при планировании. Модели меньшего размера (13B, 34B) умещаются удобнее, там KV-cache получает ощутимо больше места.
Второе - сеть между узлами при tensor parallelism. Когда модель не помещается в GPU одного узла и нужно раскидывать слои по нескольким картам разных серверов (pipeline или tensor parallelism) - 25GbE становится узким горлом. Задержки на межузловой коммуникации начинают ощутимо влиять на время ответа. Мы это видели на 70B с tensor_parallel_size=8 поверх двух узлов: latency первого токена заметно выросла по сравнению с конфигурацией, где всё умещается на одном узле. Вывод: если есть возможность - берите InfiniBand или хотя бы 100GbE для межузловых линков под такие задачи. Экономия на сети отыгрывается неудобством потом.
Третье - прогрев KV-cache. vLLM реализует PagedAttention, который хорошо работает при повторяющихся prefix-последовательностях. У заказчика оказалась типичная RAG-архитектура: системный промпт + документ + вопрос пользователя. Системный промпт один и тот же почти всегда. После того как включили prefix caching в vLLM, время до первого токена на повторных запросах с тем же системным промптом упало существенно - кэш начинает работать уже через несколько минут после старта под реальной нагрузкой.
Четвёртое - мониторинг GPU. Стандартный Prometheus + Grafana работает, но NVIDIA DCGM exporter на отечественных серверах потребовал возни с драйверами и версиями CUDA. Не всё встало из коробки - пришлось чинить совместимость. Зато когда заработало - метрики нормальные: gpu_utilization, memory_used, sm_active, nvlink_bandwidth.
Что по производительности
Без конкретных цифр конкретного заказчика (NDA), но порядки такие: на задаче суммаризации документов средней длины с моделью ~34B на двух A100 получаем десятки токенов в секунду на запрос при умеренной конкурентности. При росте числа одновременных пользователей throughput растёт до определённой точки, потом упирается в память и KV-cache. Continuous batching vLLM здесь реально помогает - пропускная способность при batched-режиме заметно лучше, чем при naive подходе по одному запросу.
Отечественные серверы: что было неожиданным
Сами серверы по стабильности претензий не вызвали - железо работает. Неожиданности были в другом. Документация от вендора на русском и местами неполная - некоторые BIOS-параметры, критичные для производительности GPU (PCIe Gen5, NUMA topology), пришлось выяснять опытным путём и через поддержку. Драйвера тоже потребовали внимания: не все версии NVIDIA driver проходили без проблем на конкретных версиях ядра, которые поставляются с сертифицированной ОС заказчика.
В целом - работаемо, но без опыта с Linux-серверами под GPU-задачи первый запуск занял бы значительно больше времени.
Где находимся сейчас
Кластер работает в production несколько недель, заказчик гоняет через него свою RAG-систему. Следующий шаг - добавить автоматическое масштабирование на уровне vLLM реплик в зависимости от очереди запросов и поработать над cold start при добавлении новых моделей (снизить время загрузки за счёт предзагрузки весов в RAM).
Если вас интересует похожая задача - запуск LLM-инференса на своём железе в рамках managed-сопровождения - мы готовы обсудить архитектуру под ваши требования.