Автор: Антон Алексеев · HighLoad++ 2024
Доклад с HighLoad++ 2024 о том, как Selectel собирал инференс-платформу на базе open source-сервера NVIDIA Triton и Kubernetes. Triton решает базовую задачу: позволяет обслуживать ML-модели в продакшне без написания отдельного сервиса для каждой модели с нуля.
Сценарий типичный: модель сначала заворачивают в FastAPI, а затем обвязка постепенно обрастает batching, управлением инстансами, распределением GPU-ресурсов, обновлением версий и маршрутизацией трафика. Triton закрывает существенную часть этой базовой работы: умеет динамический batching, поддерживает модели в форматах PyTorch, TensorFlow, ONNX и TensorRT, а ensemble позволяет собрать цепочку моделей внутри одной ноды с одной GPU.
Но production-инференс начинается там, где заканчивается сам сервер моделей. Канареечное распределение трафика в платформе сделано через Istio, графы моделей на нескольких нодах — через Ray, а автоскейлинг GPU-ресурсов — средствами Kubernetes и дополнительными компонентами. Важная деталь: на момент доклада платформа Selectel ещё находилась в beta, поэтому это не история про «готовое решение из одной коробки», а разбор того, как такую систему собирают на практике.
Кому смотреть: ML-инженерам, MLOps- и DevOps-командам, которые обслуживают несколько моделей на GPU и хотят понять границу между возможностями inference-сервера и задачами всей платформы.
Из этого можно взять в работу: при внедрении Triton заранее разделите требования на две группы — что должен делать сам сервер моделей, а что потребует Kubernetes, service mesh, автоскейлинга, GPU-оператора или отдельного control plane.
В основе платформы лежит Triton с его динамическим batching и управлением инстансами моделей. Сервер может накапливать запросы и обрабатывать их пачками, подбирая размер batch и задержку накопления под конкретную модель. Это помогает эффективнее использовать GPU, но не является универсальным решением: для систем с минимальной задержкой дополнительное ожидание запросов может быть неприемлемым.
Ensemble в Triton подходит для графа, который целиком помещается на одной ноде и GPU. Например, одна модель может передавать результат следующей внутри inference-сервера. Если же разные части графа нужно разнести по нескольким GPU-нодам, одного Triton уже недостаточно. В платформе для этого используют Ray, который запускает Triton как часть распределённого графа и управляет взаимодействием между сервисами.
Автоскейлинг GPU-платформы устроен заметно сложнее обычного добавления CPU-пода. Сначала растёт метрика очереди запросов, затем Kubernetes создаёт новую реплику, autoscaler поднимает виртуальную машину с GPU, а GPU Operator устанавливает драйверы и необходимые инструменты. Только после этого реплика Triton получает возможность обслуживать трафик. В докладе вся цепочка может занимать около десяти минут, поэтому отдельно рассматриваются хранение весов вне образа, подключение общего хранилища и оптимизация загрузки тяжёлых контейнеров.
Для распределения трафика между версиями моделей команда использует Istio и канареечный деплой: на новую версию можно отправить только часть запросов, проверить ошибки и затем изменить соотношение трафика. В интерфейсе платформы видны версии моделей, endpoints, состояние ресурсов, задержки в очереди, загрузка GPU и ошибки; процент трафика между версиями можно менять непосредственно оттуда.
Последняя часть посвящена оптимизации. Model Analyzer подбирает конфигурацию Triton — dynamic batching и количество инстансов модели. Model Navigator конвертирует модели между форматами, выполняет квантизацию и помогает сравнивать получившиеся варианты. В отдельных случаях переход к TensorRT заметно увеличивает производительность, но конкретный результат зависит от модели и инфраструктуры.
Если Triton рассматривается как замена самописной обвязке, полезно считать не только время запуска первой модели. Не менее важны границы ответственности: какие функции даёт inference-сервер, а какие всё равно придётся строить вокруг него.