Kubernetes для AI/ML: GPU Scheduling с NVIDIA GPU Operator

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

Почему GPU в Kubernetes простаивает и срывает релизы

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

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

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

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

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

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

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

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

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

Режимы выделения GPU в Kubernetes: что выбрать

Режим доступа к ускорителям задаётся не в манифесте пода, а на уровне плагина устройств и планировщика. Планировщик видит ускоритель как расширенный ресурс: сколько единиц объявил узел, столько подов он и разместит. Отсюда напрямую следуют плотность упаковки, разброс задержек и то, как поведут себя сервисы, когда один процесс заберёт всю память.

Ниже — четыре варианта, между которыми реально выбирают. NVIDIA GPU Operator разворачивает драйверы и плагин устройств, но сам режим доступа вы задаёте конфигурацией.

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

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

Как мы внедряем планирование ускорителей: этапы

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

  1. Аудит кластера и инвентаризация нагрузок. Собираем, какие задания просят ускорители, как долго живут, сколько устройств держат и сколько простаивают. Фиксируем пиковые окна и места, где очередь уже растёт.
  2. Схема размещения заданий. Делим кластер на группы узлов под обучение, вывод и пакетную обработку, задаём профили устройств и квоты, чтобы одна команда не занимала все ускорители.
  3. Настройка планировщика. Ставим NVIDIA GPU Operator — драйвер, плагин устройств и метрики обновляются как единое целое. Затем приоритеты, метки и правила размещения, по которым задание попадает только на подходящий узел.
  4. Проверка отказоустойчивости. По очереди выводим узел из строя, роняем драйвер, упираемся в память ускорителя — смотрим, перепланируется ли задание и не тянет ли за собой соседей.
  5. Прогон на реальной нагрузке. Гоняем сценарии заказчика на боевых объёмах, сверяем расчётное время с фактическим и правим лимиты там, где планировщик держит задание в очереди без причины.
  6. Передача в эксплуатацию. Отдаём схему кластера, конфигурации, правила квот, набор оповещений и инструкции для дежурных — и разбираем с командой типовые сбои.

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

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

  • Конфигурации планировщика — манифесты с политиками размещения задач, резервированием ускорителей под конкретные нагрузки и приоритетами для очередей обучения и вывода моделей.
  • Схема кластера — топология узлов с ускорителями, разбиение на пулы, зоны отказов и связи между сервисом планирования, хранилищем и системой мониторинга.
  • Политики доступа команд — разграничение пространств имён, квоты на ускорители и роли: кто может запускать обучение, кто менять общие настройки, кто только смотреть метрики.
  • Инструкция дежурному инженеру — что проверять при деградации, как найти задачу, удерживающую ускоритель, как вывести узел на обслуживание и вернуть его в работу.
  • Регламент обновления — порядок смены драйверов и версий NVIDIA GPU Operator: сначала тестовый пул, затем ограниченный, затем весь кластер, с заранее описанными критериями отката.
  • Каталог метрик и правила оповещений — какие показатели ускорителей, очередей и узлов считаются нормой и в какой момент дежурный получает сигнал, а не шум.
  • Журнал решений — почему выбран такой профиль планирования, какие ограничения он накладывает и что менять при росте нагрузки или смене парка оборудования.

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

Кейс: очередь заданий перестала ждать освобождения ускорителя

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

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

Метрики до и после

Показатель До После
Загрузка ускорителей 40–50% 82–88%
Ожидание задания в очереди до 6 часов 15–20 минут
Задачи, упавшие из-за занятого узла каждая пятая единичные

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

Чем отличается общий доступ к ускорителю от личного?

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

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

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

Технические сомнения перед началом работ

Часть вопросов возникает ещё до старта: кластер уже работает, часть узлов настроена вручную, и менять всё «в один день» никто не готов. Ниже — то, что чаще всего обсуждаем на этапе оценки.

Кластер уже частично настроен — пересобирать с нуля?

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

Придётся ли править код моделей?

Как правило, нет. Меняется описание запуска: запрос ресурса, лимиты, приоритет, привязка к типу узла. Тренировочные скрипты и сервисы вывода остаются прежними — их достаточно переупаковать и перевести на новые правила запуска.

Как ограничить доступ к дорогим ресурсам?

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

Что будет при отказе узла с GPU?

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

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

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

  • Профиль нагрузок. Что именно выполняется — обучение, дообучение или вывод моделей; соотношение режимов, средняя и пиковая загрузка ускорителей, требования к памяти на один процесс.
  • Форма запуска задач. Кто и как их ставит: исследователи вручную, сервис по расписанию или внешняя система. От этого зависит, нужны ли квоты по командам и раздельные пространства имён.
  • Требования к отклику. Допустимое время ожидания в очереди, скорость выхода задачи на ускоритель, приоритеты, готовность вытеснять низкоприоритетные задания ради срочных.
  • Текущее состояние. Kubernetes и его топология, состав узлов, развёрнутые компоненты для работы с ускорителями, способ установки драйверов и то, насколько конфигурация повторяема.
  • Данные и сеть. Где лежат датасеты, чекпоинты и артефакты моделей, как быстро они читаются, хватает ли пропускной способности между узлами.
  • Доступы и контроль. Кто владелец изменений, как разграничены права, что требуется журналировать и какие проверки обязательны перед выкатом.
  • Передача команде. Кому уходит эксплуатация — платформенной команде или исследователям, нужны ли регламенты, схемы и обучение дежурных.

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

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

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

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