Автомасштабування CI/CD ранерів: налаштування та оптимізація

Збірки стоять у черзі, релізи зсуваються, а команда чекає, доки звільниться виконавець. Ми налаштовуємо автомасштабування ранерів під ключ: пул зростає під навантаженням і стискається в простої. Час очікування збірки скорочується в рази, а пікові періоди більше не гальмують випуск.
Часті запитання

Чому збірки стають у чергу: автомасштабування раннерів на практиці

Статичний пул агентів збірки розрахований на середній потік комітів. Кожен агент одночасно виконує одне завдання, тому сплеск — серія комітів в одну гілку, масове злиття, нічний прогін за розкладом — миттєво забирає вільних виконавців.

Завдання, які хвилину тому стартували одразу, стають у чергу збірок і чекають агента з відповідними мітками.

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

Далі вмикається зворотний зв’язок по спіралі: час очікування конвеєра зростає, результат приходить із затримкою, розробник перемикається на інше завдання й втрачає контекст.

Помилка в основній гілці виявляється через кілька злиттів, кількість повторних прогонів збільшується, а черга стає самопідтримуваною — конвеєр перестає працювати як інструмент контролю якості.

Збільшення пулу «на око» проблему не знімає: поза піками агенти простоюють, а розрахунковий пік усе одно виявляється вищим за фактичний. Потрібен пул, який зростає за довжиною черги й стискається після її розбору, — автомасштабування раннерів. Розбираємо, як це влаштовано і що дає на практиці.

Що дає автомасштабування раннерів: вимірювані ефекти

Швидкість зворотного зв’язку

Статичний пул збирають під пік: у спокійні години половина агентів простоює, а в момент масового розгортання вишиковується черга. Автомасштабування піднімає раннери під фактичний потік завдань, і прогін стартує одразу після надсилання змін. Час від коміту до результату перевірок падає з десятків хвилин до одиниць.

Утилізація раннерів

Масштабування за довжиною черги та кількістю зайнятих агентів утримує рівно стільки виконавців, скільки потрібно зараз: Kubernetes додає й знімає їх за метрикою, без ручного чергування. Утилізація зростає кратно, бо резерв під пік більше не тримається марно.

Простій збірки

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

Передбачуваність розгортання

Чисте однакове середовище на кожен прогін прибирає розкид часу збірки між машинами. Розгортання планують за стабільним бюджетом часу, а не за найгіршим випадком.

Усунений клас відмов

Зникають відмови вичерпання статичного пулу: загублені з черги завдання, таймаути очікування агента, «залиплі» прогони на деградованому виконавці. Залишаються відмови коду — їх і має ловити конвеєр.

Режими масштабування: постійний пул, за потреби, гібрид

Три схеми відрізняються не кількістю машин, а тим, звідки береться агент і скільки часу минає між постановкою завдання та початком його виконання.

Постійний пул утримує фіксований набір виконавців: затримка запуску агента близька до нуля, зате стеля масштабування дорівнює розміру пулу — пік стає в чергу, а в простої ресурси зайняті й образи потрібно оновлювати одразу на всіх вузлах.

Масштабування за потреби створює агента під конкретне завдання й знімає його після — простою немає, середовища можна тримати різнорідними.

Плата за це — холодний старт: затримка запуску агента складається з виділення ресурсу, реєстрації в системі та підготовки образу, тому потік дрібних комітів починає впиратися в очікування.

Гібридна схема тримає невеликий теплий пул під базове навантаження й добирає динамічні агенти на піках, але потребує правил витіснення — інакше з’являються залиплі агенти й подвійна витрата на образи.

Порівняння схем

Схема Коли підходить Обмеження
Постійний пул Рівний потік збірок, короткі завдання, критична затримка старту Стеля масштабування задана заздалегідь; простій у години затишшя; синхронне оновлення образів
Масштабування за потреби Нерівномірне навантаження, різнорідні середовища, рідкісні важкі збірки Затримка запуску агента на першому завданні; пік упирається в зовнішню квоту
Гібридна схема Базовий потік плюс регулярні піки, різні класи завдань Складніше налаштування й спостережуваність: правила витіснення, залиплі агенти, дублювання образів

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

Впровадження кроками: аудит черги, схема, перевірка, передача

Порядок робіт вибудувано так, щоб схема спиралася на вимірювання, а не на припущення. Спочатку знімаємо фактичні дані черги та профіль збірок, потім задаємо розрахункові ліміти масштабування, перевіряємо поведінку під навантаженням і передаємо налаштовану схему вашій команді.

  1. Аудит черги. Збираємо час очікування завдання, частку простоюючих виконавців і піки за годинами — видно, де черга зростає від нестачі потужності, а де від повільної збірки.
  2. Профіль збірок. Розкладаємо завдання за тривалістю, споживанням пам’яті та частотою запуску; короткі й важкі потрапляють у різні групи, щоб не блокувати одне одного.
  3. Ліміти масштабування. Задаємо верхню й нижню межі, крок додавання та час утримання вільного виконавця: пік розбирається швидко, а простій не накопичує зайві машини.
  4. Схема й конфігурація. Описуємо правила запуску, кеш залежностей і розмежування прав. Конфігурація зберігається як код і переноситься між середовищами без ручних правок.
  5. Перевірка під навантаженням. Проганяємо серію паралельних завдань і звіряємо з вихідними метриками: час очікування в черзі, частка відмов, час до готовності першого виконавця.
  6. Передача в експлуатацію. Віддаємо документацію, панелі моніторингу й регламент змін, розбираємо схему з вашими інженерами та супроводжуємо перші правки.

Конфігурації, схеми й регламенти, які залишаються у вас

Передаємо не архів із налаштуваннями, а робочий контур: конфігурацію раннерів, прив’язану до ваших репозиторіїв, схему масштабування з порогами та регламент обслуговування.

До кожного артефакту додається пояснення, який параметр за що відповідає і що зміниться за його правки, — команді не доведеться відновлювати логіку за історією змін.

  • Файли конфігурації раннерів — теги, ліміти паралельних завдань, образи, правила повторного використання кешу; версіонуються в репозиторії та проходять перевірку змін, а не правляться руками на сервері.
  • Схема масштабування — метрика, за якою піднімаються виконавці, нижня й верхня межі, час простою до відкликання, поведінка при піковому навантаженні та при відмові вузла.
  • Політики доступу — ролі команд і сервісних облікових записів, розмежування за проєктами, обмеження на запуск завдань із зовнішніх гілок, термін життя тимчасових ключів.
  • Регламент обслуговування — що і за яким розкладом оновлюється, як перевіряються черги й насичення вузлів, у якому порядку виводиться несправний виконавець.
  • Інструкція для команди — як додати раннер, змінити ліміти, підключити новий репозиторій, відкотити конфігурацію до попередньої версії.
  • Карта діагностики — зняття метрик і типові відмови: черга зростає, завдання не забираються, кеш не перевикористовується, — з кроками перевірки для кожного.
  • Порядок відкату — яка версія вважається опорною, як повернутися до неї без зупинки збірок.

Приймання — спільний прогін на вашому стенді: даємо навантаження, дивимося, як відпрацьовує масштабування, і правимо пороги на місці. Далі зміни вносить ваша команда за інструкцією.

Кейс: як прибрали чергу збірок і простій конвеєрів

До впровадження збірки йшли через фіксований пул із чотирьох агентів на всі репозиторії. У ранкові години навантаження зростало втричі, завдання стояли в черзі по 20 з лишком хвилин, інженери або чекали, або відкривали паралельні гілки й потім розбирали конфлікти при злитті.

Частка зірваних збірок трималася на рівні 12% — переважно через таймаути й нестачу ресурсів на перевантажених агентах.

Перевели збірку на еластичний пул у GitLab CI: агенти піднімаються під фактичне навантаження й гасяться після простою, обмеження на кількість одночасних завдань задається на рівні проєкту, а не всього сервера.

Важкі перевірки та швидкі перевірки коду розвели за різними профілями агентів, залежності кешуються між прогонами.

Метрики до й після: очікування в черзі — з 21 хвилини до 40 секунд, кількість одночасно працюючих агентів — з 4 до 34 у піку навантаження, частка зірваних збірок — з 12% до 1,5%.

Повний прогін перевірок скоротився з 34 до 12 хвилин, а час від зміни в репозиторії до готового артефакту перестав залежати від пори доби.

Окремо зник клас відмов, який раніше списували на «нестабільні тести»: агенти більше не конкурують за ресурси, тому падіння за таймаутом майже зникли. Звільнений час інженери витрачають на завдання, а не на ручний перезапуск збірок.

Чим автомасштабування за потреби відрізняється від резервного пулу?

Масштабування за потреби створює агента під конкретне завдання, резервний пул тримає кількох агентів уже прогрітими. Різниця видна в трьох місцях: затримка старту, вартість прогріву образу й поведінка на сплеску завдань.

При масштабуванні за потреби агент з’являється на кожне завдання: планувальник вибирає вузол, образ тягнеться з реєстру, піднімаються робочі залежності. Затримка старту складається з цих кроків, і основна її частка — прогрів агента.

Скорочують її попереднім завантаженням шарів образу й кешем реєстру поруч із кластером, а витрата ресурсів у простої залишається нульовою: платимо лише за час виконання завдання.

Резервний пул дає іншу криву: агенти вже запущені й прогріті, завдання стартує майже одразу після постановки. Плата — постійна витрата ресурсів на простоюючих агентах, навіть коли навантаження немає.

На раптовому сплеску пул віддає миттєво лише свій розмір, далі вмикається масштабування за потреби — просто з меншою чергою.

Відрізняється й поведінка на спаді. За потреби зайві агенти йдуть після останнього завдання, і кластер повертається до вихідного споживання. Пул живе до кінця вікна утримання: короткий сплеск залишає прогріті агенти займати ресурси марно.

На практиці в Kubernetes збирають гібрид: невеликий прогрітий мінімум закриває регулярний потік, автомасштабування добирає решту за довжиною черги.

Налаштування перевіряють за двома метриками — час від постановки завдання до старту агента й частка завдань, що простояли в черзі довше за поріг.

Кеш, секрети й ізоляція збірок: технічні обмеження

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

Ізоляція збірок тримається на тому, що кожен агент отримує власну файлову систему й не бачить артефакти сусідніх завдань.

Плата за таку схему — перший запуск після простою: кеш не прогрітий, агентів у пулі немає. Далі працюють правила, які знімають основні сумніви.

Що відбувається з кешем залежностей, коли навантаження спадає?

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

Як секрети потрапляють на динамічний агент і не залишаються на ньому?

Секрет видається на час одного завдання й монтується в його середовище, а не пишеться в образ агента. Після завершення агент знищується разом із середовищем, доступ відкликається, значення в журналах маскуються. Тому кількість одночасно працюючих агентів не впливає на те, скільки живуть секрети.

Що буде, якщо агент упав посеред завдання?

Завдання позначається перерваним і йде в повторний запуск: незавершені кроки виконуються з початку, готові артефакти підхоплюються з кешу. Якщо причина — нестача ресурсів, планувальник піднімає заміну. Ліміт повторів не дає збою крутитися нескінченно.

Обговоримо вашу схему раннерів і повернемося з оцінкою

Оцінка впровадження автомасштабування спирається на факти, а не на середні по ринку: схеми раннерів у всіх різні, і різниця в конфігурації змінює і архітектуру, і трудозатрати.

Тому спочатку збираємо вихідні дані — зазвичай достатньо однієї розмови з інженером, який експлуатує ці раннери.

  • Система контролю версій і те, як запускаються завдання: за подією, за розкладом або вручну.
  • Де зараз живуть раннери й чим керуються: окремі машини, хмарні віртуальні машини, кластер.
  • Профіль завдань — збірка, тести, публікація артефактів — та їхня типова тривалість.
  • Пікове навантаження: скільки завдань приходить одночасно і як часто це повторюється.
  • Вимоги до мережевих зон, секретів і прав доступу до репозиторіїв і реєстрів образів.
  • Що вже налаштовували і де саме впирається: простій завдань у черзі, нестача потужностей, ручний підйом машин.
  • Обмеження на зміни: вікна обслуговування, погодження, ізольовані контури.

За цими даними описуємо цільову схему раннерів під ваш потік завдань і повертаємося з оцінкою впровадження: план робіт за етапами, строки налаштування, порядок викочування без зупинки поточних збірок і список того, що потрібно з вашого боку.

Якщо даних не вистачає — скажемо прямо, а не закладемо запас. Опишіть завдання, і ми повернемося з планом.

Наші компетенції:

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1542
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1393
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1368
  • Розробка логотипу компанії B2B Advance
    Розробка логотипу компанії B2B Advance
    815
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1139