Деплой LLM на Kubernetes: де ламається прод під навантаженням
Кластер спокійно тримає демонстраційне навантаження і розсипається на першому ж сплеску: виклики копіюються в чергу запитів до моделі, час відповіді зростає нелінійно, частина звернень відвалюється через перевищення очікування.
Причина зазвичай не в самій моделі — при деплої LLM на Kubernetes виявляється нестача ресурсів, яких у контурі або немає, або вони вже зайняті іншими задачами.
Прискорювачі — дефіцитний і неподільний ресурс. Якщо пристрої зосереджені на одному вузлі, навчання, донавчання і вивід конкурують за них: планувальник тримає репліки сервісу в очікуванні, черга зростає, а деградація часу відгуку проявляється вже за помірного трафіку. Масштабування тут не рятує — додати репліки без вільних прискорювачів неможливо.
Окрема точка відмови — конфлікт оновлень контуру. Розкатка нової версії моделі та супутніх сервісів іде в той самий кластер, що й робочий трафік, і на час прогріву пропускна здатність падає.
Без ізоляції середовищ тестові та продуктові навантаження ділять ті самі пристрої, тому експеримент одного інженера стає інцидентом для клієнта.
Усі ці збої передбачувані, і кожен закривається конфігурацією, а не героїзмом чергового: окремі пули вузлів, пріоритети черг, стратегія розкатки з прогрівом і швидким відкатом. Далі розбираємо, як це закривається на практиці — від планування ємності до регламенту оновлень.
Що дає керований інференс під піковим навантаженням
Керований інференс — це коли репліки моделі живуть на GPU-вузлах під керуванням оркестратора, а трафік приходить через єдину точку входу.
Планувальник сам знаходить вільні прискорювачі, піднімає нову репліку поряд із тією, що вже віддає відповіді, і знімає її, коли черга спорожніє. Розгортання перестає бути ручною операцією на конкретній машині й стає декларативним описом бажаного стану.
Стабільний час відгуку тримається не середнім значенням, а хвостом розподілу. Масштабування йде за глибиною черги та зайнятістю прискорювача, а не за завантаженням процесора: репліка додається до того, як запити почнуть чекати в буфері. Тому 95-й перцентиль залишається в заданому коридорі і на сплеску, і в спокійні години.
Частка успішних запитів зростає тому, що відмова перестає бути тотальною. Проби готовності не пускають трафік у ще не прогріту репліку, нездорові екземпляри виводяться з балансування, а таймаути й повтори налаштовані так, щоб клієнт отримав відповідь, а не помилку.
Автоматична розкатка версії моделі йде канареечним сценарієм: нове збирання отримує малу частку трафіку, метрики якості та затримок порівнюються з поточною, і лише потім ця частка зростає. Відкат — повернення на попередній образ, без перезбирання середовища й ручних правок.
Зворотний бік тієї ж механіки — зменшення ручних операцій експлуатації. Нічні перезапуски, ручне додавання вузлів під навантаження і правка конфігів переходять у декларативні політики, а інженер займається моделлю, а не чергуванням.
Варіанти розгортання моделей: порівняння режимів
Режим розгортання задає, як кластер ділить прискорювачі між моделями і як система поводиться на піку.
Вибір залежить від кількості моделей, вимог до ізоляції навантажень і передбачуваності трафіку: переїзд між варіантами після запуску обходиться болючіше, ніж одразу підібрати відповідний.
Порівняння режимів
| Варіант | Коли підходить | Обмеження |
|---|---|---|
| Одиночний вузол із прискорювачами | Одна-дві моделі, внутрішній контур, обкатка гіпотези | Ізоляції навантажень немає: важкий запит до однієї моделі просаджує сусідню; масштабування лише вгору, стеля — ресурс вузла |
| Спільний пул прискорювачів | Кілька моделей з різним профілем навантаження і спільним піком за часом | Потрібні квоти, пріоритети витіснення й ліміти на модель; галасливий сусід залишається ризиком, відмова одного вузла зачіпає всіх |
| Виділена група під модель | Продові моделі з жорсткими вимогами до відгуку й чутливими даними | За низького навантаження прискорювачі простоюють; дорожче в обслуговуванні, зате відмова локалізована однією моделлю |
| Модель, рознесена по кількох вузлах | Вага моделі не вміщується в один вузол або потрібен запас за одночасними запитами | Обмін між вузлами додає затримку; відмовостійкість і оновлення складніше планувати |
На практиці починають зі спільного пулу: він дає гнучкість і дозволяє виміряти реальний профіль запитів.
Виділену групу заводять під одну-дві моделі, де ціна простою вища за вартість прискорювачів, що простоюють, а ізоляцію навантажень підкріплюють окремими просторами імен, квотами й пріоритетами.
Обмеження масштабування варто зафіксувати заздалегідь — за якою ознакою навантаження переїжджає в окрему групу і що відбувається при відмові вузла.
Етапи впровадження: від аудиту контуру до передачі
Розгортання моделі в кластер — це не встановлення одного сервісу, а послідовність, де кожен крок спирається на попередній.
Якщо пропустити аудит і одразу перейти до налаштування, схема роз'їдеться на першій же зміні профілю навантаження: черги зростають, прискорювачі простоюють, а відкат збирають під тиском. Нижче — порядок робіт, який ми повторюємо на кожному проєкті.
- Аудит контуру виводу моделей — інвентаризація: які моделі та ваги використовуються, де вони працюють зараз, профіль запитів, обмеження за пам'яттю прискорювачів, список споживачів. На виході — карта поточного стану й перелік вузьких місць.
- Проєктування схеми розгортання — топологія пулів вузлів, розподіл реплік, квоти, автомасштабування, ізоляція середовищ. Результат — конфігурація, відтворювана з репозиторію, а не зібрана руками.
- Налаштування й базова перевірка — маніфести, кеш ваг, ліміти ресурсів, мережеві політики, збирання метрик і логів. Переконуємося, що сервіс відповідає й коректно переживає перезапуск.
- Перевірка під навантаженням — профіль, близький до бойового: паралельні запити, довгі контексти, пікові сплески, відмова окремого вузла. Дивимося затримку першого токена й пропускну здатність, фіксуємо поріг деградації.
- План відкату версії — як повернути попередній образ моделі й конфігурацію однією операцією, перевірено на стенді. Без відпрацьованого відкату реліз не випускаємо.
- Передача в експлуатацію — доступи, регламенти, алерти, документація, навчання чергової зміни. Далі систему веде команда супроводу.
Етапи йдуть строго по порядку: пропущений аудит повертається переробкою схеми, а неперевірений відкат — простоєм у найневдаліший момент.
Що залишається у вас: конфігурації, схеми, регламенти
Усе, що ми налаштовуємо при деплої, залишається у вашому репозиторії та кластері — без прив'язки до нашої команди. Передаємо не «папку з файлами», а робочий контур: ваш інженер піднімає стенд з нуля за документацією, не задаючи нам питань.
- Маніфести розгортання. Розгортання, сервіси, точки входу, квоти на GPU-вузли, автомасштабування за довжиною черги запитів. Застосування на чистому кластері відтворює середовище один в один.
- Схема відмовостійкості. Розміщення реплік за зонами, ліміти ресурсів, пороги проб готовності, поведінка при падінні вузла. Видно, яка деградація допустима і що відбувається з чергою.
- Регламент оновлення моделі. Канареечна частка трафіку, метрики порівняння якості відповідей, критерії відкату, точка неповернення. Оновлення перестає бути зупинкою сервісу.
- Політики доступу команд. Ролі в кластері, розділення просторів імен, доступи до секретів із ключами, ліміти ресурсів на команду.
- Документація з експлуатації. Схема архітектури, точки відмови, типові інциденти й порядок дій, метрики й логи, орієнтири при деградації.
- Скрипти збирання образів. Відтворюване збирання, тегування, перевірки перед розкаткою.
Далі ви ведете сервіс самі: змінюєте модель, додаєте команди, масштабуєте пул вузлів. Ми залишаємося на зв'язку з нових задач, але не як єдині, хто вміє торкатися конфігурації.
Кейс: стабільний інференс під піковим навантаженням
Замовник — сервіс генерації текстів на потоці звернень.
Середнє навантаження трималося рівно, але в ранкові години кількість запитів за хвилину зростала втричі, і ламалася саме ця картина: репліки інференсу не встигали прогріватися до включення в балансування, частина звернень закривалася помилкою, а розкатка нової версії моделі зупиняла прийом трафіку на весь час перезбирання середовища.
Метрики зняли перед втручанням і за місяць після:
| Показник | До | Після |
|---|---|---|
| Частка відмов запитів у пікові вікна | 11% | 0,4% |
| Час відгуку на 95-му перцентилі | 4,8 с | 1,3 с |
| Час розкатки нової версії моделі | 40 хв із зупинкою прийому | 5 хв без зупинки |
| Готовність репліки після старту | 6–9 хв | 25–40 с |
Зміни стосувалися трьох речей: прогріву, розподілу й розкатки. Прогріта вага моделі тепер лежить в образі, нова репліка не потрапляє в балансування, поки не готова приймати запити, а версія виїжджає на частину трафіку з поступовим розширенням частки.
При зростанні черги планувальник піднімає додаткові репліки, при спаді — знімає їх, тому постійний резерв під пік не тримається, а парк прискорювачів NVIDIA не зріс.
Відкат на попередню версію — одна команда, трафік повертається за хвилини, і це окремо перевірили на навчальному відкаті.
Чим відрізняється деплой інференсу від донавчання моделі?
Це два різні контури з протилежним профілем навантаження, і змішувати їх в одному середовищі — джерело постійних збоїв. Деплой інференсу обслуговує запити: трафік приходить нерівномірно, відповідь потрібна миттєво, простій видно користувачеві одразу.
Контур донавчання моделі працює пакетно: довгі прогони, повне завантаження прискорювачів, і зупинка на середині обходиться у втрачену добу розрахунку.
Розділення ресурсів диктує топологію. Інференсу потрібен гарантований резерв прискорювачів і запас пам'яті під чергу запитів — інакше на піку підуть відмови. Донавчанню вигідніше забирати вільне залізо цілком і відпускати його після завершення.
Тому ми розводимо контури за окремими пулами вузлів і за розкладом: навчання стартує у вікно низького навантаження і не віднімає продуктивність в обслуговування.
Частота оновлень теж різна. Ваги змінюються раз на кілька тижнів, а обв'язка навколо них — маршрутизація, ліміти, кеш, метрики — оновлюється постійно; у контурі донавчання цикл свій: експеримент, перевірка якості, викладка нової версії.
Вимоги до відмов дзеркальні. Інференсу потрібні плавна деградація і швидкий відкат на попередню версію: кілька копій, проби живучості, зняття трафіку з нездорового вузла.
Донавчанню важливіша збереженість прогресу — регулярні контрольні точки, щоб падіння вузла коштувало перезапуску останнього відрізка, а не всього прогону.
Обидва контури ми піднімаємо на Kubernetes як на спільній платформі, але з різними політиками: окремі пули, свої правила масштабування, різні пріоритети планувальника. Таке розділення знімає головний клас відмов — коли навчання витісняє обслуговування і продукт лягає цілком.
Технічні сумніви перед запуском інференсу
Перед запуском моделі в кластер команди ставлять майже ті самі питання — і правильно роблять: відповіді на них визначають, як сервіс поведеться при оновленні та в аварії. Нижче — короткі відповіді по суті, без загальних слів.
Як зрозуміти, що вузьке місце — не прискорювач?
Дивимося ланцюжок цілком: черга запитів, розмір пакета, підготовка вхідних даних, передача між сервісами. Часто прискорювач простоює, а час іде на передобробку й очікування в черзі. Якщо частка простою стабільно велика, оптимізувати потрібно не обчислення.
Як оновити модель без простою?
Нова версія піднімається поряд зі старою і отримує спочатку невелику частку трафіку — порівнюємо якість відповідей і затримку на живих запитах. Ваги зберігаються як окремий артефакт з версією, тому відкат — це перемикання трафіку назад, а не повторне збирання. Логи й відповіді завжди прив'язані до версії моделі.
Як дати командам доступ до контуру?
Через простори імен і ролі: розробник бачить логи й метрики свого сервісу, але не керує кластером і чужими навантаженнями. Облікові дані — лише у штатному сховищі секретів, не в конфігураціях і не в листуванні. Доступ видається ролі, а не людині — при зміні складу команди нічого не потрібно відкликати вручну.
Що відбувається при відмові прискорювача?
Вузол виводиться з балансування, а його навантаження переїжджає на вільні. Якщо резерву немає, запити стають у чергу з обмеженням за часом — сервіс сповільнюється, але не відповідає помилкою.
Одночасно спрацьовує план деградації: скорочуємо паралелізм і довжину вхідних даних, а критичні сценарії обслуговуються компактною моделлю.
Рівні деградації, їхні пороги та порядок перемикання ми описуємо заздалегідь і перевіряємо на навчаннях — тоді в аварії рішення ухвалює автоматика, а не черговий.
Обговоримо задачу: що надіслати для оцінки контуру
Щоб повернутися з оцінкою та планом робіт, а не із загальними міркуваннями, нам потрібен короткий зріз за вашим контуром: за ним видно, де вузькі місця, скільки прискорювачів реально знадобиться і які рішення доведеться ухвалити до першої розкатки. Надішліть те, що є — частина ввідних часто відсутня, і це нормально, доберемо разом на дзвінку.
- Модель і формат ваг: відкрита чи донавчена, розмір, допустима точність (повна чи квантована), чи потрібен доступ до приватних ваг і звідки їх забирати.
- Профіль навантаження: запитів за секунду в піку й у середньому, довжина контексту, частка потокової віддачі відповіді, чи є довгі пакетні задачі окремо від інтерактиву.
- Поточний контур розгортання: кластер і його мережа, наявність вузлів із прискорювачами, чим керуєте ресурсами, де зберігаються ваги і як збираються образи.
- Вимоги до доступності: цільова частка успішних запитів, допустимий час простою при оновленні, чи потрібен прогрів перед введенням нового екземпляра в роботу.
- Доступи й межі: хто володіє кластером, які зовнішні сервіси мають бути доступні, чи є вимоги до ізоляції запитів між командами.
- Спостережуваність: що вже збирається — завантаження прискорювачів, черга запитів, затримки, логи — і куди це складається.
- План розвитку: зростання навантаження на горизонті, поява нових моделей, потреба в тонкому налаштуванні під свої дані.
Цього достатньо, щоб запропонувати схему розміщення, політику оновлень і відкатів, а також план робіт з етапами й критеріями приймання. Опишіть задачу у зручному вигляді — повернемося з оцінкою та планом.







