Чому власні раннери CI/CD зривають релізи на піках
Загальні машини збірки обслуговують одразу всі проєкти — і це працює рівно до першого піку.
Варто збігтися кільком подіям: масовому злиттю гілок перед релізом, нічному прогону регресії та плановому оновленню залежностей — і черга збірки на піках зростає, а завдання довго стоять в очікуванні вільної машини.
Прогін, який у спокійні години вкладався в лічені хвилини, надвечір розтягується в рази, і передбачити його тривалість уже неможливо.
Поки в GitLab один пул із загальним тегом за замовчуванням, усі завдання претендують на ті самі ресурси. Машини ділять між собою кеш і робочі каталоги, тому перевірки починають падати на рівному місці — таймаути, нестача пам’яті, чуже сміття у директорії збірки.
Це нестабільні прогони перевірок: інженер перезапускає завдання, черга подовжується ще сильніше, а до червоного статусу зникає довіра — його звикають «дотягувати» повторним запуском.
Ціна такої схеми — зрив вікна релізу. Зміна, повністю готова до викатки, чекає збірку довше, ніж триває саме вікно, і вирушає в наступне; термінова правка йде поза регламентом, вручну й без повного набору перевірок.
Розбираємо, як це закривається: виділені раннери під профіль навантаження, розведення завдань за тегами та ізоляція робочих місць.
Що дає власний контур збірки: швидкість, ізоляція, контроль
Власний контур збірки — це пул машин під нашим керуванням, де завдання виконуються поряд із кодом, кешем залежностей і локальним дзеркалом пакетів.
Раннери GitLab у такій схемі стартують за секунди: образ середовища попередньо завантажений, встановлення залежностей зводиться до перевірки контрольних сум.
Час очікування в черзі перестає залежати від чужого навантаження — він визначається кількістю машин у пулі та пріоритетами, які ми задаємо самі.
Ізоляція завдань — другий ефект. Кожне завдання отримує одноразове середовище: контейнер або віртуальну машину, яка знищується після прогону. Паралельні гілки не ділять спільний каталог і змінні, тому збірка однієї команди не може вплинути на іншу.
Ліміти процесора, пам’яті та диска виставляються на рівні виконавця, і важке завдання не витісняє решту.
Звідси зникає цілий клас відмов — розбіжність середовищ і «брудний» стан між прогонами: недописані файли, чужі змінні, залиплі блокування, різні версії системних бібліотек.
На піках, коли за годину проходить серія змін від кількох команд, пул масштабується, а черга не зростає лавиноподібно.
У цифрах це виглядає так: частка прогонів, що потребують ручного перезапуску, падає в рази, медіанний час збірки скорочується завдяки кешу та паралельним крокам. Збій окремої машини не зупиняє контур — завдання переїжджає на вільного виконавця, і це видно за часом відновлення.
Варіанти розміщення раннерів: хмара, власні машини, гібрид
Раннер — це місце, де сходяться швидкість конвеєра, доступ до внутрішніх стендів і режим поводження з вихідними кодами. Три схеми нижче не теоретичний набір: кожну ми розгортали, і в кожної своя ціна в супроводі.
| Варіант | Коли підходить | Обмеження |
|---|---|---|
| Хмарні машини збірки | Навантаження нерівномірне, потрібен швидкий старт, залежності тягнуться з інтернету | Вихідні коди й секрети виходять за межі контуру, кеш втрачається разом із машиною, немає прямого доступу до внутрішніх реєстрів і стендів |
| Власне залізо під збірку | Потік завдань постійний, потрібні внутрішні реєстри, стабільний кеш і передбачуваний час збірки | Пікову паралельність задає парк машин, простій між релізами нічим зайняти, оновлення та ізоляцію завдань тримає власна команда |
| Гібридна схема збірки | Частина завдань чутлива до даних, частина ресурсомістка й не потребує внутрішніх залежностей | Потрібна явна маршрутизація завдань, два набори секретів, зведена картина за метриками збирається окремо |
Окремо варто згадати закритий контур розробки: якщо регламент забороняє вихід коду й артефактів назовні, хмарні машини відпадають цілком, а гібрид зводиться до власних потужностей із локальними дзеркалами залежностей.
Гібрид окупається лише тоді, коли маршрутизація описана явно — за мітками, шляхами або чутливістю даних.
Інакше команда отримує дві неузгоджені системи замість однієї: різні змінні середовища, різні правила кешування, і як наслідок — відтворюваність збірки, яку неможливо гарантувати.
Етапи впровадження: від аудиту збірки до передачі в експлуатацію
Впровадження починається не зі встановлення агентів, а з розбору того, що вже відбувається на контурі збірки: де втрачається час, які кроки дублюються, які завдання йдуть на спільних виконавцях із чужими правами доступу.
Ми йдемо фіксованою послідовністю — кожен етап завершується перевірюваним артефактом, тому проєкт не розтягується на невизначений термін.
- Аудит процесів збірки. Збираємо тривалість кроків, черги в пікові години, частку падінь через інфраструктуру, а не через код. Результат — карта вузьких місць і список завдань, які варто винести на виділені виконавці.
- Схема контуру збірки. Проєктуємо топологію: скільки груп раннерів потрібно, де вони розміщуються, як розділені мережі та доступи між командами, як влаштовані кеш залежностей і сховище образів.
- Налаштування раннерів. Розгортаємо виконавців з ізоляцією завдань, мітками під типи збірок, лімітами за ресурсами й автоскейлом під чергу. Секрети видаються на час завдання й не лежать на хості.
- Міграція збірок. Переводимо проєкти групами, починаючи з найменш ризикованих, із паралельною роботою старого контуру та швидким поверненням на нього в разі розбіжності результатів.
- Перевірка під навантаженням. Проганяємо кілька релізних циклів на піковій кількості одночасних збірок: дивимося деградацію кешу, поведінку автоскейла й час до старту завдання.
- Передача в експлуатацію. Віддаємо конфігурації, схему контуру, регламент оновлення та порядок дій у разі відмови, навчаємо чергових і фіксуємо метрики, за якими контур приймається.
Що залишається в команди: конфігурації, схеми, регламенти
Контур збірки передаємо як працюючу систему, а не як набір усних домовленостей: усе, що потрібно для підтримки й розвитку, лежить у вашому репозиторії та внутрішній документації.
Інженер вашої команди зможе змінювати кроки конвеєра, додавати нові проєкти й розбирати збої без звернення до нас.
- Конфігурації збірки — описи конвеєрів, шаблони для типових застосунків і набори змінних середовища. До кожного кроку додано коментар: навіщо він потрібен, що кешується та які перевірки блокують випуск.
- Схема доступу та ключів — карта, де зберігаються облікові дані, як агент отримує доступ до реєстру образів і сховища артефактів, які права в кожної ролі та як вони видаються новому інженеру.
- Регламент обслуговування — періодичність оновлення агентів, чищення кешів і старих образів, ротація секретів, порядок дій у разі вичерпання місця на диску або завислого виконавця.
- Документація щодо контуру — схема розміщення агентів, мережеві зони та правила доступу, точки відмови й що робити за недоступності зовнішнього сервісу.
- Інструкція з відновлення — як підняти агент з нуля покроково, де взяти конфігурацію та як перевірити, що конвеєр знову збирає й публікує артефакт.
- Передача знань команді — розбір контуру з вашими інженерами, включно з розбором типових збоїв і порядку їх діагностики, плюс запис зустрічі.
Окремо фіксуємо, що залишилося поза автоматизацією і чому: це список завдань на розвиток, а не прихований борг. Через місяць після здачі відповідаємо на запитання щодо переданих матеріалів — далі контур живе на вашій стороні.
Кейс: час збірки скоротили втричі, черга на піках зникла
Збірки йшли через спільний набір раннерів: коміт після злиття ставав в одну чергу з нічним регресом і збіркою образів. Середній прогін займав 14 хвилин, а на піках очікування сягало 22 хвилин — ресурси тримали завдання, яких уже ніхто не чекав.
Частка провалених прогонів трималася на 18%: таймаути й гонки за спільним кешем залежностей змушували перезапускати перевірки, і перезапуски ще сильніше подовжували чергу — пік накладався на пік.
Що змінили
Розвели раннери за групами навантаження: короткі перевірки, збірка образів і важкий нічний регрес отримали окремі набори машин і ліміти на одночасні завдання.
Автоматичне масштабування за довжиною черги на Kubernetes піднімає разових агентів під пік і прибирає їх у простій — середовище кожної збірки чисте, а кеш залежностей винесено на постійний том і не перетирається сусідніми завданнями.
Що стало
Середня збірка — 14 → 4 хвилини, очікування на піках — 22 хвилини → 40 секунд, частка провалених прогонів — 18 → 5%. Нічний регрес вкладається до початку робочого дня, а патч за інцидентом проходить повний прогін перед випуском, а не урізаний набір перевірок.
Черга перестала бути вузьким місцем: її довжина у звітах стабільна, а нові репозиторії підключаються без ручного розширення парку машин — агенти додаються під фактичне навантаження.
Що робити, якщо власні раннери CI/CD уже розгорнуто
Якщо контур уже розгорнуто, починати варто не з переписування, а з ревізії поточної схеми: інвентар машин, виконувані завдання, облікові записи, доступ до секретів.
Зазвичай виявляється, що частину раннерів запущено вручну, мітки проставлено «на око», а завдання ходять у продові сховища зі спільним токеном. Це перший шар проблем, і видно його лише на карті контуру, а не в окремих конфігураціях.
Другий крок — розподіл прав на машинах. Раннери розносять за пулами: збірка, тести, публікація артефактів і розгортання отримують різні облікові записи та різні області доступу.
Секрети видаються завданню на час виконання, а не лежать у змінних машини, а виконавці роблять одноразовими — після збірки робоче середовище знищується разом із тимчасовими даними.
Масштабування під навантаження тримається на чергах і мітках: машини додаються за довжиною черги, а не «на око», важкі збірки йдуть в окремий пул і не блокують швидкі перевірки.
Залежності та спільні томи виносяться назовні, тому новий виконавець включається в роботу одразу, без повторного завантаження всього середовища.
Доработка наявного контуру йде по одному пулу за раз із збереженням сумісності: старі завдання продовжують працювати, доки новий пул не підтвердить стабільність на реальному потоці, а відкат залишається можливим на будь-якому кроці.
Заодно контур перестає триматися на одному інженері: конфігурація зберігається як код у спільному репозиторії, проходить перевірку до застосування, а схема пулів, мережі та прав описана в документації. Тоді зміни перестають бути особистою відповідальністю однієї людини.
Технічні питання, які ставлять перед стартом
Перед стартом зазвичай виринає той самий набір сумнівів: чи не витечуть ключі, що буде з релізами в момент переїзду і хто відповідає за машини після запуску. Нижче — прямі відповіді на те, що найчастіше запитують до підписання плану робіт.
Куди потрапляють ключі доступу під час збірки?
Секрети не зберігаються в репозиторії й не прописуються в конфігурації збірки відкритим текстом. Вони лежать в окремому захищеному сховищі, а раннер отримує короткоживучий токен лише на час конкретного завдання — після його завершення доступ відкликається автоматично. Значення маскуються у виводі команд, тому витік через логи виключено.
Чи ізольовано контур збірки від решти інфраструктури?
Кожен запуск іде в чистому середовищі, яке видаляється після завдання, — код одного проєкту не залишається на машині й не потрапляє в чужу збірку. Раннер бачить лише ті реєстри образів і артефактів, що дозволені політикою, а доступу до внутрішніх сервісів і баз у нього немає. Мережеві правила описуються окремо й перевіряються на тестовому конвеєрі до виведення в роботу.
Що станеться з релізами під час переїзду?
Новий контур піднімаємо паралельно — попередній продовжує збирати й випускати. Кілька днів завдання йдуть на обох, артефакти звіряються, потім проєкти перемикаються по одному.
Вікно простою нульове: якщо збірка на новому раннері поводиться інакше, проєкт повертається на попередню адресу до розбору причини.
Хто обслуговує машини після запуску?
Регламент фіксуємо письмово: оновлення раннера й базових образів, моніторинг черги та вільних ресурсів, чищення старих артефактів, реакція на падіння завдання.
У тому ж документі межа: що залишається на нашій стороні, а що потребує участі вашої команди — доступи до внутрішніх систем, узгодження мережевих правил, випуск релізів. Так відповідальність не розмивається через місяць після передачі.
Обговоримо задачу: збірка без черг і витоків
Щоб повернутися з оцінкою та планом робіт, а не загальними міркуваннями, достатньо ввідних щодо збірки — цього вистачає, щоб порахувати конфігурацію раннерів, оцінити трудозатрати й запропонувати порядок старту.
- Кількість репозиторіїв і активних команд, типова частота комітів — за ними рахуємо паралелізм і запас за навантаженням.
- Де саме накопичується черга: поточний час збірки й тестів, у які години пік чекати доводиться найдовше.
- Як збірки йдуть зараз: хмарні раннери, локальні машини розробників або власний сервер.
- Вимоги до ізоляції: які завдання отримують доступ до секретів і артефактів, хто і що бачить у логах.
- Куди плануєте ставити раннери — власний контур, виділені машини або гібрид, — і які мережі їм доступні.
- Хто на вашій стороні відповідає за доступи, і хто супроводжує конфігурацію після запуску.
У відповідь надсилаємо оцінку та план робіт, схему розміщення раннерів і порядок старту. Першим кроком пропонуємо пілот на одному репозиторії: переносимо його збірку, заміряємо час і поведінку під навантаженням і лише після цього розгортаємо на решту. Опишіть задачу — повернемося з оцінкою та планом.







