CI: распределение нагрузки — где на самом деле уходит время (AD-1293)
Статус: research, только замеры и выводы. Ничего в конфигурации CI,
раннеров и машин этим документом не менялось.
Окно замера: 2026-07-30 02:17 UTC → 2026-07-31 02:17 UTC (24 часа).
Источник чисел: GitLab REST API проектаagadron/aero-forge(81171473),
эндпоинты/jobs,/pipelines,/runners,/pipeline_schedules,
/jobs/:id/trace; конфигурации раннеров прочитаны по ssh сnasиbuildbox.
Выборка: 243 пайплайна, 1731 джоба.
0. Короткий ответ на постановку
Постановка звучала как «разгрузить единственный shell-раннер и равномернее
распределить нагрузку». Замеры этого не подтверждают.
Shell-раннер aero-forge-runner занят 202 минуты из 1440 — 14% суток.
Он не является узким местом. Раздача нагрузки по машинам уже сделана в AD-706:
build, test, build-images, ci-base и youtrack-* давно уезжают на
docker-раннеры, и половина из них — на buildbox.
Три вещи, которые действительно стоят времени:
test— 638 из 961 раннер-минуты в сутки (66% всего CI) и 138 секунд
из 231 секунды медианного develop-пайплайна. 12121 теста, pytest — 88%
времени джобы. Всё остальное вместе меньше.- Прод-машина несёт 629 мин/сут CI против 331 у простаивающего buildbox —
и почти вся эта нагрузка идёт не через shell-раннер, а через
docker-раннер на той же машине. Конкуренция с продом реальна, но её
источник не тот, который назван в постановке. - Ядра переподписаны в 2–4 раза.
pytest -n autoв docker-executor видит
ядра хоста, а не долю раннера; приlimit=4на buildbox это 64 процесса
на 16 ядер. Отсюда разброс времениtestв 3.2 раза на одном и том же
наборе тестов.
Если делать что-то одно — это не перенос джоб между машинами, а потолок
параллелизма у pytest. Если делать что-то второе — закрепить test за
buildbox, чтобы снять его с прод-машины.
1. Инвентаризация раннеров
Проектных раннеров у agadron/aero-forge три (групповых нет; общие
GitLab SaaS-раннеры доступны, но не используются — все джобы имеют теги).
| id | описание | хост | executor | теги | run_untagged |
limit |
|---|---|---|---|---|---|---|
| 52629726 | (без описания) | nas | shell | aero-forge-runner |
нет | 1 |
| 54345107 | docker-build on tartarus (aero) | nas | docker | docker-build |
да | 2 |
| 54373997 | buildbox (andrey-ms7e06, 16c/32G) | buildbox | docker | docker-build |
нет | 4 |
concurrent — 5 на nas (там же живут два раннера чужого проекта
build-version-counter: bvc-runner shell и docker-build (bvc)), 4 на buildbox.
Машины
| nas (tartarus) | buildbox (andrey-ms7e06) | botter | |
|---|---|---|---|
| ядер / RAM | 12 / 31 ГБ | 16 / 31 ГБ | 4 / 7 ГБ |
| load average | 14.40 / 11.39 / 11.19 | 3.48 / 12.62 / 11.92 | — |
| диск свободно | 284 ГБ из 457 | 806 ГБ из 931 | — |
| что ещё крутится | aero-web, aero-cad, cortex-mongo, registry, uptime-kuma, netdata, build-version-counter, весь Nextcloud AIO (14 контейнеров), Ollama, GPU |
только раннер | MCP-стек |
LA 14.4 при 12 ядрах на nas — машина перегружена до учёта CI.
Nextcloud AIO на прод-машине к CI отношения не имеет, но в конкуренции за
ядра участвует; при разговоре о «конкуренции CI с продом» это стоит держать
в голове.
Про постановку: утверждение «buildbox простаивает, неизвестно на какой
проект зарегистрирован» неверно. Он зарегистрирован на agadron/aero-forge
с 2026-07-16, активен, тег docker-build, и за сутки отработал 307 джоб.
На машине есть следы параллельной подготовки другим агентом (пользователи
cortex, runner, aagafonov) — не трогались.
Сколько джоб реально может идти параллельно
Шесть: 1 (shell) + 2 (nas-docker) + 4 (buildbox), с оговоркой, что
docker-build — общий тег для двух раннеров и GitLab раздаёт между ними
произвольно.
Узкое место — не количество слотов. За сутки медиана ожидания в очереди
у всех джоб, кроме ci-base-tag, ниже 3 секунд. Узкое место — длина
критического пути одной джобы (test) и последовательность стадий.
2. Профиль пайплайна
2.1. Куда уходят раннер-минуты (24ч)
| джоба | прогонов | суммарно | медиана | p90 | где идёт |
|---|---|---|---|---|---|
| test | 245 | 638.3 мин | 145.2с | 246.8с | docker (nas 124 / buildbox 112) |
| scan | 105 | 138.3 мин | 94.0с | 137.0с | shell |
| youtrack-sync | 112 | 43.8 мин | 49.8с | 77.4с | docker |
| build-images | 106 | 33.7 мин | 11.5с | 16.6с | docker |
| deploy | 104 | 31.1 мин | 17.4с | 59.3с | shell |
| build | 243 | 30.8 мин | 7.5с | 9.7с | docker |
| ci-base-tag | 243 | 19.4 мин | 4.8с | 5.4с | shell |
| youtrack-reconcile | 112 | 11.9 мин | 14.9с | 15.7с | docker |
| healthcheck | 104 | 4.8 мин | 3.5с | 3.9с | shell |
| deploy-mcp-stack | 114 | 4.2 мин | 37.5с | — | shell (86 — кнопка) |
| i18n-translate | 1 | 1.9 мин | 111.3с | — | shell |
| infra-prune | 114 | 1.7 мин | 24.6с | — | shell (90 — кнопка) |
| deploy-infra | 115 | 0.5 мин | 3.7с | — | shell (87 — кнопка) |
| apply-kuma-monitors | 7 | 0.4 мин | 9.1с | — | shell |
| designer-kernel-tests | 6 | 0.0 мин | — | — | ни разу не выполнялась |
| ИТОГО | 960.6 мин |
Статусы за сутки: 1123 success, 271 manual, 185 canceled, 89 created,
34 skipped, 25 failed, 4 running.
Пайплайнов: 130 MR + 112 develop-push + 1 schedule.
2.2. Критический путь develop-деплоя
Трассировка типового полного пайплайна (2718223339), время от старта первой джобы:
+0с .. +5с ci-base-tag .pre shell-nas
+8с .. +15с build build nas-docker
+18с .. +156с test test nas-docker ← критический путь
+18с .. +28с build-images build-images nas-docker
+33с .. +129с scan scan shell-nas ← спрятан за test
+161с .. +170с deploy deploy shell-nas
+173с .. +176с healthcheck healthcheck shell-nas ← ПРОД УЖЕ ОБНОВЛЁН
+180с .. +231с youtrack-sync notify nas-docker ← +51с хвоста
+181с .. +197с youtrack-reconcile notify buildbox
Агрегат по 106 develop-пайплайнам: wall-clock медиана 231с, p90 351с.
Сумма длительностей джоб медианно 309с → параллелизм всего 1.34x.
По 130 MR-пайплайнам: медиана 161с, p90 272с. Здесь test — практически
весь пайплайн.
Что из этого следует.
test= 60% wall-clock develop. Всё остальное вместе — 40%.scan(96с на shell-раннере) полностью спрятан заtest— идёт с 33-й
по 129-ю секунду, покаtestидёт до 156-й. Переносscanна другую машину
не ускорит пайплайн ни на секунду. Это надо сказать прямо, потому что
ровно этот перенос выглядит очевидным.deployзанимает 9 секунд. Собственно раскатка прода — не проблема.- Хвост
youtrack-sync— 51с после того, как прод уже обновлён и проверен
healthcheck'ом. Это 22% wall-clock, потраченные на закрытие тикетов. build(7.5с) стоит междуci-base-tagиtestи стоит пайплайну ~10с
накладных расходов планировщика на каждом прогоне.
2.3. Что съедает время внутри test
Разбор лога джобы 15636804059 (успешный прогон, 224с):
| фаза | время |
|---|---|
| подъём контейнера + git checkout | 3.4с |
| lint незапиненных зависимостей + напоминание про changelog | ~4с |
JS-юнит-тесты (node tests/test_*.js, AD-624) |
~11с |
| pytest (12121 passed, 6 skipped) | 196.0с |
scripts/coverage_ratchet.py |
1.0с |
| выгрузка артефактов | 6.0с |
Вывод простой: test — это pytest, а pytest — это 12121 теста.
Никакой обвязки, которую имело бы смысл резать, внутри джобы нет.
Ускорять здесь можно только двумя способами — меньше тестов (AD-966 уже про
это) или лучше параллелизм (см. §4.1).
3. Где shell-executor вредит — и где нет
3.1. Занятость shell-раннера (24ч, limit=1)
| джоба | прогонов | минут |
|---|---|---|
| scan | 87 | 138.3 |
| deploy | 80 | 31.1 |
| ci-base-tag | 239 | 19.4 |
| healthcheck | 80 | 4.8 |
| deploy-mcp-stack | 8 | 4.2 |
| i18n-translate | 1 | 1.9 |
| infra-prune | 4 | 1.7 |
| deploy-infra | 8 | 0.5 |
| apply-kuma-monitors | 3 | 0.4 |
| итого | 510 | 202.2 мин = 14% суток |
14% занятости — это не бутылочное горло. Но limit=1 означает, что даже
при низкой занятости конкуренция бывает: из 510 джоб 70 ждали дольше 10
секунд, суммарно 65 минут очереди. Три худших случая — ci-base-tag с
ожиданием 237с, 214с и 200с. То есть .pre-джоба на 5 секунд, от которой
через needs зависит весь пайплайн, стояла в очереди четыре минуты за
единственным слотом, занятым scan.
3.2. Что обязано остаться на shell
deploy— доступ к docker-демону прода и/opt/cortex,resource_group: production.healthcheck— проверяет реальный прод после раскатки.deploy-infra,infra-prune,deploy-mcp-stack,apply-kuma-monitors—
инфра-операции на конкретных хостах (sudoers-wrapper для nginx, compose
в/opt/infra, ssh на botter).
Суммарно это 42.7 мин/сут — 3% суток. Прод-специфичная часть shell-раннера
почти ничего не стоит.
3.3. Что уедет без разговоров
ci-base-tag—sha256sumчетырёх файлов. Прод-докер не нужен. Держать
джобу, гейтящую весь пайплайн, на раннере сlimit=1— прямой вред,
измеренный в 237 секундах худшего ожидания.i18n-translate— ходит в Ollama по сети.
3.4. scan — отдельный случай
AD-706 закрыт (Done, Major) с формулировкой «перенести build-images + scan
на buildbox-раннер». Перенесён только build-images. В .gitlab-ci.yml у
scan стоит явный комментарий, что он остаётся на shell, потому что
«Trivy sibling-контейнеры маунтят host-пути».
Это 138 мин/сут — 68% всей нагрузки shell-раннера. Но, как показано в §2.2,
перенос не ускорит пайплайн: scan спрятан за test. Выигрыш от переноса —
освобождение единственного слота (то самое ожидание ci-base-tag) и снятие
нагрузки с прод-машины, а не wall-clock.
Отдельно стоит отметить расхождение: тикет закрыт целиком, а сделана половина.
3.5. Общее состояние между джобами
Заявленный в постановке риск «общее состояние shell-раннера — кеши, .venv,
мусор» на практике не подтвердился. Все джобы, где такое состояние
накапливалось бы (build, test, сборки образов), уже в docker-executor;
на shell остались короткие джобы без установки зависимостей. В логе
deploy-infra видно Reinitialized existing Git repository in
/home/gitlab-runner/builds/... — переиспользуемый рабочий каталог есть,
но с git depth 20 и чекаутом в detached HEAD; следов протухания в выборке
не найдено.
4. Куда распределять
4.1. Сначала — потолок параллелизма (важнее любого переноса)
.python-test гоняет pytest -n auto. В docker-executor без cpu-лимита
auto определяет число воркеров по ядрам хоста, а не по доле раннера.
Ни у nas-docker, ни у buildbox в [runners.docker] не заданы ни cpus,
ни memory — проверено чтением /etc/gitlab-runner/config.toml на обеих
машинах.
| раннер | ядер | limit |
воркеров при полной загрузке |
|---|---|---|---|
| buildbox | 16 | 4 | 4 × 16 = 64 процесса на 16 ядер |
| nas-docker | 12 | 2 | 2 × 12 = 24 процесса на 12 ядер + весь прод |
Измеренное следствие — разброс времени test на неизменном наборе тестов:
| раннер | n | min | медиана | p90 | max |
|---|---|---|---|---|---|
| buildbox | 93 | 90.6с | 134.5с | 215.2с | 289.4с |
| nas-docker | 114 | 132.2с | 152.1с | 273.1с | 317.5с |
От 90.6с до 317.5с — 3.5x на одних и тех же 12121 тестах. Это не тесты,
это конкуренция за ядра.
→ AD-1294: заменить -n auto на явный бюджет, согласованный с limit.
Правка в несколько строк, ничего не переносится, эффект — на самой дорогой
джобе CI.
4.2. Предлагаемая раскладка по тегам
| тег | раннеры | джобы | обоснование |
|---|---|---|---|
aero-forge-runner (shell, nas, limit 1) |
52629726 | deploy, healthcheck, deploy-infra, deploy-mcp-stack, infra-prune, apply-kuma-monitors |
доступ к проду обязателен; 43 мин/сут |
heavy-test (новый, buildbox) |
54373997 | test, designer-kernel-tests |
снять 638 мин/сут с прод-машины; на buildbox быстрее на 18с медианы |
docker-build (nas-docker + buildbox) |
54345107, 54373997 | ci-base, ci-base-tag, build, build-images, youtrack-sync, youtrack-reconcile, i18n-translate |
лёгкие, резервируются двумя машинами |
docker-build — кандидат |
scan |
если Trivy получится увести с host-путей (§3.4) |
4.3. Ограничение (а): агенты основателя на buildbox
Забирать все 16 ядер нельзя. Сегодня потолка нет вообще: limit=4,
concurrent=4, без cpus/memory — CI способен занять машину целиком.
Предложение — бюджет вместо «кто успел»:
* задать cpus в [runners.docker] раннера buildbox (потолок CI);
* согласовать с ним -n у pytest;
* остаток явно закрепить за агентами и записать в docs/dev/.
Порядок величин: за сутки buildbox отработал 331 минуту = 23% времени одного
слота. Даже после переезда всего test (638 мин) суммарно выходит ~970
мин/сут на 4 слота — примерно 17% ёмкости. Запас под агентов есть, но его
надо зафиксировать конфигурацией, а не надеждой.
→ AD-1304.
4.4. Ограничение (б): деплой остаётся у прода
Соблюдено: deploy/healthcheck/инфра-джобы в раскладке не двигаются.
4.5. Совместимость с переходом develop на resource_group
Решение (в работе у другого агента) — пайплайны на develop перестают отменять
друг друга и идут последовательно. Что это меняет для чисел выше:
- Пропускная способность develop становится равна
1 / wall-clock. Сегодня
wall-clock = 231с медиана → потолок ~15 пайплайнов в час. За измеренные сутки
было 112 develop-пайплайнов, ночью — плотнее; запас есть, но не кратный. - Хвост
youtrack-syncв 51с бьёт напрямую: это 22% времени
последовательного окна, потраченные после того, как прод уже обновлён.
При 112 пайплайнах — около 1.6 часа последовательного окна за сутки (AD-1301). - Отмены перестанут освобождать слоты. За сутки 185 джоб отменены,
на них сожжено 17.4 раннер-минуты — сама по себе величина малая, но
shell-раннер сlimit=1будет занят чаще, а значит ожидание
ci-base-tag(сегодня до 237с) станет типичным, а не редким (AD-1295).
Ни одно предложение этого документа переходу не противоречит; два из них
(AD-1295, AD-1301) становятся после перехода заметно ценнее.
5. Что можно просто не делать
Отдельный раздел, как и просили. Здесь честно: большого выигрыша по времени
тут нет, вопреки ожиданию. Path-based gating (AD-707) и build-once/deploy-many
(AD-526) уже сняли самое очевидное.
5.1. Что уже не делается (и работает)
- AD-707: из 106 develop-пайплайнов 26 (25%) пропустили
build-images/scan/deploy/healthcheck как docs-only. Механизм живой и
экономит примерно четверть тяжёлых прогонов. - AD-599:
ci-baseза сутки не пересобиралась ни разу (нет прогонов в
выборке) — хэш-тег работает, пересборка образа без изменений не происходит. - AD-526:
build-imagesмедиана 11.5с — образы тянутся по tree-hash,
а не собираются заново.
5.2. Артефакты, которые никто не читает
Единственная явно лишняя работа, которую удалось измерить.
артефакт test |
размер | потребитель |
|---|---|---|
artifacts.zip (report.html + coverage_html/) |
6.3 МБ | не найден |
job.log |
3.76 МБ | человек, изредка |
junit.xml.gz |
0.22 МБ | MR-виджет GitLab |
cobertura-coverage.xml.gz |
0.08 МБ | бейдж покрытия (AD-967) |
10.37 МБ × 245 прогонов = 2.54 ГБ/сут. job_artifacts_size проекта —
7.06 ГБ из 7.14 ГБ всего storage. Выгрузка стоит 6с в каждой джобе.
--cov-report=json трогать нельзя — его читает scripts/coverage_ratchet.py
(AD-968). Речь только про self-contained HTML и coverage_html/. → AD-1302.
5.3. Джоба build
7.5с полезной работы (compileall) ценой полного цикла планировщика, git
checkout и подъёма контейнера — ~10с накладных на каждом из 243 пайплайнов.
Сливается в test первой секцией. → AD-1303.
5.4. Джобы, которые всегда allow_failure и потому бессмысленны
Искалось отдельно. Найдено следующее.
designer-kernel-tests — механизм есть, но покрасить ничего не может.
Джоба заведена AD-1274 по итогам AD-1273 («179 node-тестов ядра v2 не гоняются
нигде»). Её правила:
- на MR и develop —
when: manual+allow_failure: true.
За сутки 6 экземпляров, статусmanual, длительность 0 — ни разу не нажата; - единственный автоматический путь —
$CI_PIPELINE_SOURCE == "schedule".
В проекте ровно одно расписание —i18n, cron19 2 * * * Asia/Yerevan; allow_failure: trueстоит и на уровне джобы, и в каждомrules-ветвлении —
то есть даже отработав по расписанию и упав, она оставит пайплайн зелёным.
Проверено по последнему schedule-пайплайну (2720217201, 2026-07-30 23:07 UTC):
там семь джоб — ci-base-tag, build, test, build-images, scan, infra-prune,
i18n-translate. designer-kernel-tests отсутствует (вмержена позже).
На момент замера джоба не выполнялась ни разу.
Оговорка честности ради: allow_failure у ручной джобы поставлен осознанно
по AD-1276 (ручная джоба без него блокирует пайплайн), и это верно. Дефект —
в комбинации: единственный авто-путь раз в сутки + флаг, гасящий результат
и на этом пути тоже. → AD-1300.
deploy-infra — уже известно, дополнено замером. За сутки создавалась 115
раз: 87 остались кнопкой, 20 отменены, 8 стартовали — 7 упали, 1 прошла.
Все падения — docker compose up -d в /opt/infra, конфликт container_name
(registry уже занят контейнером вне compose-проекта). nginx-часть при этом
проходила успешно, что дополнительно маскировало проблему.
Уже покрыто AD-1251 (миграция контейнеров выполнена 2026-07-31); замер
добавлен туда комментарием. Дубль не заводился.
Ручные инфра-джобы. infra-prune (90 из 114 — кнопка), deploy-mcp-stack
(86 из 114), apply-kuma-monitors — висят кнопкой в каждом develop-пайплайне.
Это осознанное решение канона (.claude/rules/cicd.md), не дефект; но стоит
знать, что 271 из 1731 джобы за сутки (16%) — это ненажатые кнопки.
youtrack-sync срабатывает реже, чем кажется. Создана 112 раз, реально
выполнена 47: 41 осталась в статусе created, 19 отменены, 5 skipped.
То есть штатный механизм закрытия тикетов отрабатывает менее чем в половине
develop-пайплайнов. Под эту дыру заведена youtrack-reconcile (AD-810) —
у неё ровно та же картина (47 из 112). Покрывает ли она пропуски полностью,
из этих чисел не видно; отмечено в AD-1301.
6. Риски второго раннера
Тег docker-build носят два раннера, и GitLab раздаёт джобы между ними
произвольно. Одна и та же джоба может быть зелёной на одном и красной на
другом, и механизма, который бы это заметил, нет.
Что дрейф уже закрывает: общий образ $CI_BASE_IMAGE_HASH (AD-599) —
версии Python и зависимостей приезжают из registry по хэш-тегу, разъехаться
не могут. Это главный источник, и он закрыт.
Что остаётся открытым:
- число ядер — 12 против 16, а
pytest -n autoот него зависит напрямую
(§4.1). Тест, чувствительный к параллелизму или таймингу, будет флапать
«через раз» и выглядеть случайным; - локальный кэш образов —
pull_policy = ["if-not-present"]на обоих;
на buildbox уже 8 теговci-baseи десяткиcortex-aero-web:tree-*; /cache-том — свой на каждой машине, содержимое не сверяется;- docker-сокет — на nas в контейнер джобы прокинут прод-демон
(/var/run/docker.sock, там жеaero-web,cortex-mongo, Nextcloud);
на buildbox — отдельный. Джоба, собирающая образ, работает в разном окружении; - ретенция — на nas есть
infra-prune, на buildbox нет ничего.
Сигнал, который уже виден в числах
Падения test за сутки распределены неравномерно:
| раннер | success | failed | доля падений |
|---|---|---|---|
| nas-docker | 114 | 5 | 4.2% |
| buildbox | 93 | 12 | 11.4% |
Разница в 2.7 раза. Это наблюдение, а не вывод: раннеры выбираются не
случайно относительно веток (какой свободен, тот и берёт), и ночью на buildbox
могли попасть более «сырые» MR. Но проверить стоит — если перекос подтвердится,
это не тесты, а машина.
Чем лечится и чего стоит
Два взаимоисключающих пути:
- Держать паритет двух машин — постоянные накладные расходы навсегда:
сверка ядер, кешей, ретенции, штамп окружения в логе. - Прибить каждую джобу к одному раннеру (
heavy-test→ только buildbox) —
разовая правка тегов, класс «у меня зелёно, у него красно» исчезает целиком.
Цена: теряется резервирование, падение buildbox блокирует все MR,
потому чтоtest— гейт мержа.
Выбор за основателем. Замеры говорят в пользу второго (выигрыш от закрепления
измерим, выигрыш от резервирования — нет), но это решение про риск, а не
про производительность. → AD-1305.
7. Что проверить не удалось
Раздел обязательный, здесь без сглаживания.
- MCP-сервер
ciне работает — отвечаетInvalid request parametersна
любой вызов. Обошли прямым GitLab REST API с токеном из.mcp.secrets.json.
Отсутствие ответа MCP за отсутствие проблемы не принималось. - MCP-сервер
youtrackне работает — та же ошибка на всех действиях,
включаяyoutrack_projects. Дополнительно:YOUTRACK_TOKENв
.mcp.secrets.jsonпротух — YouTrack REST отвечаетInvalid token.
Рабочий токен взят из окружения MCP-стека на botter. Это отдельная
проблема, тикет по ней не заводился (вне рамок исследования), но
зафиксировать стоит. - Эффект предложений не измерен — по условию задачи ничего не менялось.
Все цифры выигрыша (−18с медианыtestна buildbox, −10с на слиянии
build, −6с на артефактах) получены сравнением наблюдений, а не A/B.
Нужен повторный замер после каждой правки. - Не проверено, что именно требует host-путей у Trivy — вывод про
scan
опирается на комментарий в.gitlab-ci.yml, не на попытку запуска в
docker-executor (это была бы правка CI). designer-kernel-testsне наблюдалась в работе ни разу — вывод о том,
что она стартует по расписанию, сделан из чтенияrules, а не из факта.
Первый настоящий прогон — в ближайший nightly; результат надо посмотреть.- Влияние Nextcloud AIO на LA nas не разделено — 14 контейнеров на
прод-машине участвуют в конкуренции за ядра, но их вклад отдельно от CI
и отaero-webне замерялся. - Перекос падений
testпо раннерам (4.2% vs 11.4%) не объяснён —
выборка не контролировалась по веткам. См. §6. - Расписание
i18nпоказываетlast_pipeline: nullчерез API, хотя
schedule-пайплайны исправно создаются каждый день в 23:07 UTC. Похоже на
особенность API, но исключить проблему с привязкой расписания нельзя. concurrent = 5на nas при суммеlimit= 5 (1 shell + 2 aero-docker +
1 bvc-shell + 2 bvc-docker = 6) — потолок ниже суммы лимитов, то есть
раннеры чужого проектаbuild-version-counterконкурируют за те же слоты.
Влияние на очередь aero-forge не измерялось.
8. План (заведённые тикеты)
Порядок — по отношению выигрыша к риску.
| # | тикет | что | выигрыш | риск |
|---|---|---|---|---|
| 1 | AD-1294 | убрать pytest -n auto, задать явный бюджет воркеров |
самая дорогая джоба CI, p90 вдвое хуже медианы | правка конфигурации, ничего не переносится |
| 2 | AD-1295 | ci-base-tag → тег docker-build |
убирает худшее наблюдавшееся ожидание (237с) у джобы, гейтящей весь пайплайн | минимальный |
| 3 | AD-1296 | test → отдельный тег на buildbox |
−638 раннер-минут/сут с прод-машины, −18с медианы | buildbox становится единственным носителем гейта мержа |
| 4 | AD-1300 | designer-kernel-tests не может ничего покрасить |
тесты ядра v2 снова окажутся невыполняемыми (AD-1273 повторно) | нет |
| 5 | AD-1301 | хвост youtrack-sync — 22% wall-clock develop |
важно к переходу на resource_group |
трогает закрытие тикетов — делать аккуратно |
| 6 | AD-1304 | бюджет ядер buildbox между CI и агентами | предотвращает конфликт с AD-1291 до его возникновения | подбирать замером |
| 7 | AD-1297 | scan остался на shell вопреки закрытому AD-706 |
освобождает 68% нагрузки shell-раннера; wall-clock не меняет | неизвестно, снимается ли зависимость Trivy от host-путей |
| 8 | AD-1302 | выбросить нечитаемые HTML-артефакты | −2.5 ГБ/сут, −6с на прогон | проверить бейджи AD-967 |
| 9 | AD-1303 | слить build в test |
−10с на пайплайн, −1 слот | проверить AD-452 (пустой develop-пайплайн) |
| 10 | AD-1305 | паритет двух раннеров либо закрепление джоб | убирает класс «у меня зелёно, у него красно» | решение про риск, а не про скорость |
Смежное, дубль не заводился: AD-1251 (deploy-infra, дополнен замером),
AD-966 (аудит 12121 теста — единственный реальный путь сократить test
кардинально), AD-1291 (агенты на buildbox), AD-1273 (тесты ядра v2).
9. Как воспроизвести замеры
# токен — из .mcp.secrets.json (GITLAB_TOKEN)
for p in $(seq 1 30); do
curl -sS -H "PRIVATE-TOKEN: $GT" \
"https://gitlab.com/api/v4/projects/81171473/jobs?per_page=100&page=$p" \
-o jobs_$p.json &
done; wait
Дальше — агрегация по name / runner.id / duration / queued_duration
с окном 24 часа по created_at. Критический путь строится по started_at
и finished_at джоб одного pipeline.id. Конфигурации раннеров:
sudo cat /etc/gitlab-runner/config.toml на nas и buildbox.