Запуск GitLab Runner в Yandex Cloud Serverless Containers
Я Павел Елисеев, старший разработчик в команде Serverless в Yandex Cloud. Мы реализовали сценарий использования сервиса — Serverless GitLab Runner. В посте покажу архитектуру и поделюсь кодом решения.
GitLab Runner — агент, выполняющий задачи (jobs) из CI/CD‑пайплайнов GitLab. Он получает инструкции от GitLab, запускает сборку, тесты или деплой в нужной среде и передаёт результат обратно.
Раннер работает в разных окружениях:
на общих серверах GitLab (shared runners);
на выделенных VM;
в K8s‑кластере.
В первом варианте репозитории должны размещаться на gitlab.com. В случае Managed GitLab или self‑hosted GitLab развёртывание выполняется самостоятельно.
Для shared‑раннеров free‑tier ограничен 400 мин./мес. Учёт идёт по формуле (duration × price-factor), так что число доступных минут зависит от используемого типа раннера. А за пределами лимита нужна привязка не российской банковской карты.
Serverless‑сценарии пытались реализовать на Cloud Functions, что требовало отдельной VM и сложной конфигурации. А мы хотели объединить плюсы serverless‑модели с CI‑задачами:
оплата за время
масштабирование за секунды
изоляция выполнения
отсутствие инфраструктурной рутины
Архитектура
GitLab Runner работает по модели pull: запускает процесс, устанавливающий long‑polling‑соединение с GitLab API, и ожидает появления задач.
Пришла задача — раннер выбирает executor:
shell — job выполняется в текущем окружении
docker — под job создаётся отдельный контейнер со всеми зависимостями
Эта модель плохо подходит для serverless‑окружения, где нельзя держать постоянно активный процесс.
Для перехода на push‑модель используем GitLab Webhooks — HTTP‑уведомления о событиях. С появлением задач GitLab отправляет вебхук в Serverless Container, который:
запускает раннер;
получает информацию о задаче;
выполняет её и возвращает результат в GitLab.
Так, выполнение задачи инициируется событием, а не постоянным опросом API.

GitLab требует от обработчика вебхуков быстрого ответа без ошибки. А выполнение задачи может занимать часы. Поэтому вебхуки обрабатываются асинхронно:
GitLab отправляет вебхук.
Платформа проверяет авторизацию и сразу отвечает
202 Accepted.Обработка выполняется асинхронно в фоне.
Платформа решает, запускать ли новый экземпляр контейнера. Когда job завершается, контейнер остаётся активным какое‑то время, чтобы обработать вызовы без cold‑start.
GitLab не отправляет событие «создание job», поэтому раннер сперва проверяет, есть ли задачи со статусом pending.
Для docker‑executor требуется dockerd. Инициализация демона и подготовка окружения выполняются 1 раз при старте контейнера. Если job найдётся, запускается эфемерный раннер, исполняющий ровно 1 задачу.
Раннер загружает docker‑образ, выполняет команды, передаёт результат обратно через GitLab API.
Используемые возможности Serverless Containers
Эфемерные диски до 10 ГБ на контейнер
Docker внутри Serverless Containers. Это не Docker‑in‑Docker: внутри serverless‑контейнера jobs исполняются без отдельного демона Docker, но с аналогичной логикой. Примеры есть в исходном коде.
Важные особенности serverless‑подхода
Эфемерность: кеш между вызовами отсутствует. Для хранения артефактов используйте Object Storage или свои базовые образы.
Загрузка образов: выполняется при каждом запуске. Рекомендуем использовать оптимизированные образы и близкий реестр (Cloud Registry), а при критичных требованиях к скорости старта — перейти на shell‑executor, собрав образ с установленным раннером и нужными зависимостями.
Ограничение времени: не более 1 часа. Для длинных задач разделите пайплайн на этапы с промежуточным сохранением результатов.
Ограничение по диску: до 10 ГБ.
Сценарий Serverless GitLab Runner позволяет выполнять CI/CD‑задачи GitLab, оплачивая лишь время выполнения job. Serverless Containers дают возможности для CI‑нагрузок: асинхронные вызовы, часовой таймаут, эфемерный диск и поддержку docker‑executor внутри контейнера.













