Развёртывание LLM на Kubernetes с GPU: полное руководство

Инференс под нагрузкой падает первым: пользователи ждут ответа, а контур не справляется с пиком обращений. Мы настраиваем развёртывание языковых моделей на Kubernetes под ключ — от конфигурации до регламентов — и сокращаем срок запуска в разы. Обсудим задачу и вернёмся с оценкой и планом.
Часто задаваемые вопросы

Деплой LLM на Kubernetes: где ломается прод при нагрузке

Кластер спокойно держит демонстрационную нагрузку и рассыпается на первом же всплеске: вызовы копируются в очередь запросов к модели, время ответа растёт нелинейно, часть обращений отваливается по превышению ожидания. Причина обычно не в самой модели — при деплое LLM на Kubernetes вскрывается нехватка ресурсов, которых в контуре либо нет, либо они уже заняты другими задачами.

Ускорители — дефицитный и неделимый ресурс. Если устройства сосредоточены на одном узле, обучение, дообучение и вывод конкурируют за них: планировщик держит реплики сервиса в ожидании, очередь растёт, а деградация времени отклика проявляется уже при умеренном трафике. Масштабирование здесь не спасает — добавить реплики без свободных ускорителей нельзя.

Отдельная точка отказа — конфликт обновлений контура. Выкатка новой версии модели и сопутствующих сервисов идёт в тот же кластер, что и рабочий трафик, и на время прогрева пропускная способность падает. Без изоляции сред тестовые и продуктовые нагрузки делят одни и те же устройства, поэтому эксперимент одного инженера становится инцидентом для клиента.

Все эти сбои предсказуемы, и каждый закрывается конфигурацией, а не героизмом дежурного: раздельные пулы узлов, приоритеты очередей, стратегия выката с прогревом и быстрым откатом. Дальше разбираем, как это закрывается на практике — от планирования ёмкости до регламента обновлений.

Что даёт управляемый инференс под пиковой нагрузкой

Управляемый инференс — это когда реплики модели живут на GPU-узлах под управлением оркестратора, а трафик приходит через единую точку входа. Планировщик сам находит свободные ускорители, поднимает новую реплику рядом с той, что уже отдаёт ответы, и снимает её, когда очередь пустеет. Развёртывание перестаёт быть ручной операцией на конкретной машине и становится декларативным описанием желаемого состояния.

Стабильное время отклика держится не средним значением, а хвостом распределения. Масштабирование идёт по глубине очереди и занятости ускорителя, а не по загрузке процессора: реплика добавляется до того, как запросы начнут ждать в буфере. Поэтому 95-й перцентиль остаётся в заданном коридоре и на всплеске, и в спокойные часы.

Доля успешных запросов растёт потому, что отказ перестаёт быть тотальным. Пробы готовности не пускают трафик в ещё не прогретую реплику, нездоровые экземпляры выводятся из балансировки, а таймауты и повторы настроены так, чтобы клиент получил ответ, а не ошибку.

Автоматический выкат версии модели идёт канареечным сценарием: новая сборка получает малую долю трафика, метрики качества и задержек сравниваются с текущей, и только затем эта доля растёт. Откат — возврат на предыдущий образ, без пересборки окружения и ручных правок.

Обратная сторона той же механики — снижение ручных операций эксплуатации. Ночные перезапуски, ручное добавление узлов под нагрузку и правка конфигов уходят в декларативные политики, а инженер занимается моделью, а не дежурством.

Варианты развёртывания моделей: сравнение режимов

Режим развёртывания задаёт, как кластер делит ускорители между моделями и как система ведёт себя на пике. Выбор зависит от числа моделей, требований к изоляции нагрузок и предсказуемости трафика: переезд между вариантами после запуска обходится больнее, чем сразу подобрать подходящий.

Сравнение режимов

Вариант Когда подходит Ограничения
Одиночный узел с ускорителями Одна-две модели, внутренний контур, обкатка гипотезы Изоляции нагрузок нет: тяжёлый запрос к одной модели просаживает соседнюю; масштабирование только вверх, потолок — ресурс узла
Разделяемый пул ускорителей Несколько моделей с разным профилем нагрузки и общим пиком по времени Нужны квоты, приоритеты вытеснения и лимиты на модель; шумный сосед остаётся риском, отказ одного узла задевает всех
Выделенная группа под модель Продовые модели с жёсткими требованиями к отклику и чувствительными данными На низкой нагрузке ускорители простаивают; дороже в обслуживании, зато отказ локализован одной моделью
Модель, разнесённая по нескольким узлам Вес модели не помещается в один узел или нужен запас по одновременным запросам Обмен между узлами добавляет задержку; отказоустойчивость и обновления сложнее планировать

На практике начинают с разделяемого пула: он даёт гибкость и позволяет измерить реальный профиль запросов. Выделенную группу заводят под одну-две модели, где цена простоя выше стоимости простаивающих ускорителей, а изоляцию нагрузок подкрепляют отдельными пространствами имён, квотами и приоритетами. Ограничения масштабирования стоит зафиксировать заранее — по какому признаку нагрузка переезжает в отдельную группу и что происходит при отказе узла.

Этапы внедрения: от аудита контура до передачи

Развёртывание модели в кластер — это не установка одного сервиса, а последовательность, где каждый шаг опирается на предыдущий. Если пропустить аудит и сразу перейти к настройке, схема разъедется на первом же изменении профиля нагрузки: очереди растут, ускорители простаивают, а откат собирают под давлением. Ниже — порядок работ, который мы повторяем на каждом проекте.

  1. Аудит контура вывода моделей — инвентаризация: какие модели и веса используются, где они работают сейчас, профиль запросов, ограничения по памяти ускорителей, список потребителей. На выходе — карта текущего состояния и перечень узких мест.
  2. Проектирование схемы развёртывания — топология пулов узлов, распределение реплик, квоты, автомасштабирование, изоляция окружений. Результат — конфигурация, воспроизводимая из репозитория, а не собранная руками.
  3. Настройка и базовая проверка — манифесты, кэш весов, лимиты ресурсов, сетевые политики, сбор метрик и логов. Убеждаемся, что сервис отвечает и корректно переживает перезапуск.
  4. Проверка под нагрузкой — профиль, близкий к боевому: параллельные запросы, длинные контексты, пиковые всплески, отказ отдельного узла. Смотрим задержку первого токена и пропускную способность, фиксируем порог деградации.
  5. План отката версии — как вернуть предыдущий образ модели и конфигурацию одной операцией, проверено на стенде. Без отработанного отката релиз не выпускаем.
  6. Передача в эксплуатацию — доступы, регламенты, алерты, документация, обучение дежурной смены. Дальше систему ведёт команда сопровождения.

Этапы идут строго по порядку: пропущенный аудит возвращается переделкой схемы, а непроверенный откат — простоем в самый неудобный момент.

Что остаётся у вас: конфигурации, схемы, регламенты

Всё, что мы настраиваем при деплое, остаётся в вашем репозитории и кластере — без привязки к нашей команде. Передаём не «папку с файлами», а рабочий контур: ваш инженер поднимает стенд с нуля по документации, не задавая нам вопросов.

  • Манифесты развёртывания. Развёртывания, сервисы, точки входа, квоты на GPU-узлы, автомасштабирование по длине очереди запросов. Применение на чистом кластере воспроизводит окружение один в один.
  • Схема отказоустойчивости. Размещение реплик по зонам, лимиты ресурсов, пороги проб готовности, поведение при падении узла. Видно, какая деградация допустима и что происходит с очередью.
  • Регламент обновления модели. Канареечная доля трафика, метрики сравнения качества ответов, критерии отката, точка невозврата. Обновление перестаёт быть остановкой сервиса.
  • Политики доступа команд. Роли в кластере, разделение пространств имён, доступы к секретам с ключами, лимиты ресурсов на команду.
  • Документация по эксплуатации. Схема архитектуры, точки отказа, типовые инциденты и порядок действий, метрики и логи, ориентиры при деградации.
  • Скрипты сборки образов. Воспроизводимая сборка, тегирование, проверки перед выкатом.

Дальше вы ведёте сервис сами: меняете модель, добавляете команды, масштабируете пул узлов. Мы остаёмся на связи по новым задачам, но не как единственные, кто умеет трогать конфигурацию.

Кейс: стабильный инференс при пиковой нагрузке

Заказчик — сервис генерации текстов на потоке обращений. Средняя нагрузка держалась ровно, но в утренние часы число запросов в минуту вырастало втрое, и ломалась именно эта картина: реплики инференса не успевали прогреваться до включения в балансировку, часть обращений закрывалась ошибкой, а выкат новой версии модели останавливал приём трафика на всё время пересборки окружения.

Метрики сняли перед вмешательством и через месяц после:

Показатель До После
Доля отказов запросов в пиковые окна 11% 0,4%
Время отклика на 95-м процентиле 4,8 с 1,3 с
Время выката новой версии модели 40 мин с остановкой приёма 5 мин без остановки
Готовность реплики после старта 6–9 мин 25–40 с

Изменения касались трёх вещей: прогрева, распределения и выката. Прогретый вес модели теперь лежит в образе, новая реплика не попадает в балансировку, пока не готова принимать запросы, а версия выезжает на часть трафика с постепенным расширением доли.

При росте очереди планировщик поднимает дополнительные реплики, при спаде — снимает их, поэтому постоянный резерв под пик не держится, а парк ускорителей NVIDIA не вырос. Откат на предыдущую версию — одна команда, трафик возвращается за минуты, и это отдельно проверили на учебном отказе.

Чем отличается деплой инференса от дообучения модели?

Это два разных контура с противоположным профилем нагрузки, и смешивать их в одной среде — источник постоянных сбоев. Деплой инференса обслуживает запросы: трафик приходит неравномерно, ответ нужен мгновенно, простой виден пользователю сразу. Контур дообучения модели работает пакетно: длинные прогоны, полная загрузка ускорителей, и остановка на середине обходится в потерянные сутки расчёта.

Разделение ресурсов диктует топологию. Инференсу нужен гарантированный резерв ускорителей и запас памяти под очередь запросов — иначе на пике пойдут отказы. Дообучению выгоднее забирать свободное железо целиком и отпускать его по завершении. Поэтому мы разводим контуры по отдельным пулам узлов и по расписанию: обучение стартует в окно низкой нагрузки и не отнимает производительность у обслуживания.

Частота обновлений тоже разная. Веса меняются раз в несколько недель, а обвязка вокруг них — маршрутизация, лимиты, кэш, метрики — обновляется постоянно; в контуре дообучения цикл свой: эксперимент, проверка качества, выкладка новой версии.

Требования к отказам зеркальны. Инференсу нужны плавная деградация и быстрый откат на предыдущую версию: несколько копий, пробы живости, снятие трафика с нездорового узла. Дообучению важнее сохранность прогресса — регулярные контрольные точки, чтобы падение узла стоило перезапуска последнего отрезка, а не всего прогона.

Оба контура мы поднимаем на Kubernetes как на общей платформе, но с разными политиками: отдельные пулы, свои правила масштабирования, разные приоритеты планировщика. Такое разделение снимает главный класс отказов — когда обучение вытесняет обслуживание и продукт ложится целиком.

Технические сомнения перед запуском инференса

Перед запуском модели в кластер команды задают почти одни и те же вопросы — и правильно делают: ответы на них определяют, как сервис поведёт себя при обновлении и в аварии. Ниже — короткие ответы по существу, без общих слов.

Как понять, что узкое место — не ускоритель?

Смотрим цепочку целиком: очередь запросов, размер пакета, подготовка входных данных, передача между сервисами. Часто ускоритель простаивает, а время уходит на предобработку и ожидание в очереди. Если доля простоя устойчиво велика, оптимизировать нужно не вычисления.

Как обновить модель без простоя?

Новая версия поднимается рядом со старой и получает сначала небольшую долю трафика — сравниваем качество ответов и задержку на живых запросах. Веса хранятся как отдельный артефакт с версией, поэтому откат — это переключение трафика обратно, а не повторная сборка. Логи и ответы всегда привязаны к версии модели.

Как дать командам доступ к контуру?

Через пространства имён и роли: разработчик видит логи и метрики своего сервиса, но не управляет кластером и чужими нагрузками. Учётные данные — только в штатном хранилище секретов, не в конфигурациях и не в переписке. Доступ выдаётся роли, а не человеку — при смене состава команды ничего не нужно отзывать вручную.

Что происходит при отказе ускорителя?

Узел выводится из балансировки, а его нагрузка переезжает на свободные. Если резерва нет, запросы встают в очередь с ограничением по времени — сервис замедляется, но не отвечает ошибкой. Одновременно срабатывает план деградации: сокращаем параллелизм и длину входных данных, а критичные сценарии обслуживаются компактной моделью.

Уровни деградации, их пороги и порядок переключения мы описываем заранее и проверяем на учениях — тогда в аварии решение принимает автоматика, а не дежурный.

Обсудим задачу: что прислать для оценки контура

Чтобы вернуться с оценкой и планом работ, а не с общими соображениями, нам нужен короткий срез по вашему контуру: по нему видно, где узкие места, сколько ускорителей реально потребуется и какие решения придётся принять до первой выкатки. Пришлите то, что есть — часть вводных часто отсутствует, и это нормально, доберём вместе на созвоне.

  • Модель и формат весов: открытая или дообученная, размер, допустимая точность (полная или квантованная), нужен ли доступ к приватным весам и откуда их забирать.
  • Профиль нагрузки: запросов в секунду в пике и в среднем, длина контекста, доля потоковой отдачи ответа, есть ли длинные пакетные задачи отдельно от интерактива.
  • Текущий контур развёртывания: кластер и его сеть, наличие узлов с ускорителями, чем управляете ресурсами, где хранятся веса и как собираются образы.
  • Требования к доступности: целевая доля успешных запросов, допустимое время простоя при обновлении, нужен ли прогрев перед вводом нового экземпляра в работу.
  • Доступы и границы: кто владеет кластером, какие внешние сервисы должны быть доступны, есть ли требования к изоляции запросов между командами.
  • Наблюдаемость: что уже собирается — загрузка ускорителей, очередь запросов, задержки, логи — и куда это складывается.
  • План развития: рост нагрузки на горизонте, появление новых моделей, необходимость тонкой настройки под свои данные.

Этого достаточно, чтобы предложить схему размещения, политику обновлений и откатов, а также план работ с этапами и критериями приёмки. Опишите задачу в удобном виде — вернёмся с оценкой и планом.

Направления AI-разработки

Последние работы

  • Разработка сайта компании B2B ADVANCE
    Разработка сайта компании B2B ADVANCE
    1542
  • Разработка веб-приложения для компании FEEDME
    Разработка веб-приложения для компании FEEDME
    1394
  • Разработка веб-сайта для компании БЕЛФИНГРУПП
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1081
  • Разработка интернет магазина для компании FURNORO
    Разработка интернет магазина для компании FURNORO
    1369
  • Разработка логотипа компании B2B Advance
    Разработка логотипа компании B2B Advance
    816
  • Разработка веб-приложения для компании Enviok
    Разработка веб-приложения для компании Enviok
    1142