У нас в профсоюзе недавно появился сервис, который используется для создания публикаций в социальных сетях. Проект находится в GitLab, но с недавних пор использовать Shared Runners в GitLab не представляется возможным, поскольку для этого требуется подключить банковскую карту, а российские карты не принимаются. Открыть счёт в банке другой страны непросто, поэтому было решено развернуть GitLab Runner в Yandex Cloud, поскольку сервис уже развёрнут в Yandex Serverless Containers.

Развернуть GitLab Runner в Yandex Cloud можно в Managed Service for GitLab или на виртуальных машинах (далее ВМ). Сравнение этих сервисов в схожих конфигурациях:

Сервис

Конфигурация

Особенности

Стоимость, 

₽ / месяц

Managed Service for GitLab

vCPU: 2

RAM: 8 Гб

Disk: SSD 30 Гб

SaaS, предустановленный GitLab

5 401,50

ВМ с образом GitLab

vCPU: 4 Intel Ice Lake, 100%

RAM: 8 Гб

Disk: SSD 30 Гб

Предустановленный GitLab

5 166,90

Чистая ВМ

vCPU: 2 Intel Ice Lake, 100%

RAM: 8 Гб

Disk: SSD 30 Гб

Чистая ОС

3 654,90

Чистая ВМ — наиболее подходящий вариант, поскольку Managed Service for GitLab и ВМ с образом GitLab обходятся относительно дороже и имеют излишнюю функциональность для текущей задачи. Кроме того, чистая ВМ более гибкая в выборе вычислительных ресурсов, так что стоимость использования может быть ниже. Например, следующая конфигурация обойдётся в 754,65 ₽ / месяц:

  • vCPU: 2, Intel Ice Lake, 20%

  • RAM: 4 Гб

  • Disk: SSD 15 Гб

  • Прерываемая ВМ

Но было бы слишком расточительно оставлять ВМ запущенной круглые сутки, ведь работа GitLab Runner может занимать всего несколько минут. Поэтому после недолгих раздумий был придуман финт ушами функциями.

Суть финта: запускать ВМ только при создании нового пайплайна в проекте, а в остальное время держать в выключенном состоянии. В таком случае стоимость использования ВМ сократится до пары сотен рублей. Диаграмма последовательности для такой функциональности представлена ниже.

Пререквизиты

Необходим аккаунт в Yandex Cloud и репозиторий в GitLab. В этом примере репозиторий уже содержит приложение и Dockerfile к нему. Требуется собрать и протестировать приложение, затем собрать Docker-образ и опубликовать его в реестре проекта.

Заострять внимание на самом проекте нет смысла, так как приложение роли не играет. Если у вас другой стек, то изменения будут в Dockerfile и .gitlab-ci.yml. В данном случае приложение — это Web API на ASP.NET Core, сгенерированное командой:

dotnet new webapi –use-minimal-apis –no-openapi

Создание и настройка ВМ в Compute Cloud

Создание ВМ в Compute Cloud

Переходим в раздел Compute Cloud / Виртуальные машины и нажимаем «Создать ВМ».

Присваиваем имя, выбираем зону доступности и ОС, которая больше нравится. Например, Ubuntu:

Настраиваем диск и вычислительные ресурсы, исходя из потребностей. Для простых приложений, в том числе и для нашего примера, подойдёт 20% гарантированной доли двух vCPU и 4 Гб RAM.

Выбираем сервисный аккаунт с ролью compute.operator. Этой роли достаточно для запуска и остановки ВМ. Если такого сервисного аккаунта нет, то создаём. Этот аккаунт необходим для управления ВМ из функции, которая будет создана далее.

Вводим логин для пользователя ОС, SSH-ключ для подключения по SSH и нажимаем «Создать ВМ».

Дожидаемся создания ВМ и переходим к следующему шагу.

Установка GitLab Runner

Сперва подключимся к ВМ. Для этого копируем публичный IP-адрес ВМ и подключаемся по SSH.

Есть несколько способов установить GitLab Runner. В нашем примере будет использоваться Docker, так как это наиболее универсальный вариант. Инструкция по установке Docker Engine для разных ОС лежит тут

После завершения установки добавляем Docker в автозагрузки, чтобы не приходилось запускать каждый раз руками:

sudo systemctl enable docker

Осталось загрузить и запустить образ с GitLab Runner. Сделаем это с подключением локальных томов. 

docker run -d --name gitlab-runner --restart always \
  -v /srv/gitlab-runner/config:/etc/gitlab-runner \
  -v /var/run/docker.sock:/var/run/docker.sock \
  gitlab/gitlab-runner:latest

Отключаться от ВМ не нужно, так как ещё необходимо зарегистрировать раннер. Как это сделать, будет показано позже, при настройке GitLab.

Создание и настройка функции в Cloud Functions

Создание функции

Переходим в раздел Cloud Functions / Функции и нажимаем «Создать функцию».

Присваиваем имя функции и нажимаем «Создать»:

Выбираем среду выполнения. В этом примере используется Node.js. Затем снимаем галочку с «Добавить файлы с примерами кода» и нажимаем «Продолжить».

Настройка функции

Нажимаем «Создать файл», присваиваем файлу имя, например, index.js и вставляем код функции. Затем определяем точку входа. Формат должен быть такой:

<имя файла без расширения>.<имя функции>

Аналогичным образом создаём package.json. Этот файл необходим, чтобы указать зависимость на Node.js SDK от Yandex.

Результат выглядит примерно так:

В параметрах функции указываем сервисный аккаунт с ролью compute.operator, который был выбран при создании ВМ. Через этот аккаунт функция будет запускать и останавливать ВМ. Остальные значения оставляем по умолчанию:

Осталось нажать «Создать версию», дождаться обновления функции и сделать её публичной:

Прежде чем идти дальше, разберём, что происходит в index.js.

Функция handler:

  1. Сравнивает значение заголовка X-Gitlab-Token со значением в константе gitlabToken для того, чтобы функция обрабатывала запросы только от нашего репозитория. Значение токена можно сгенерировать любым удобным способом: GUID-генератор, генератор паролей и т.д.

  2. Парсит тело запроса и проверяет значение object_kind. Обрабатываться должны только события от pipeline. Остальные игнорируются.

  3. Проверяет значение detailed_status. Если в проекте создан новый pipeline, то статус у него будет pending. В таком случае запускаем ВМ. Если статус passed, значит, работа pipeline завершена успешно, можно останавливать ВМ.

Функции startInstance и stopInstance:

  1. Создают новую сессию с токеном сервисного аккаунта, который мы указали при создании функции. Данные этого аккаунта будут доступны в параметре context.

  2. Создают запрос на запуск и остановку ВМ соответственно.

  3. Отправляют запрос в инстанс, который указан в константе virtualMachineInstanceId.

Настройка проекта GitLab

Регистрация и настройка раннера

Возвращаемся к ВМ. Для регистрации необходимо выполнить одну из команд из этой инструкции. Для нашего примера:

docker run --rm -it -v /srv/gitlab-runner/config:/etc/gitlab-runner gitlab/gitlab-runner register

После чего будет предложено определить значения для параметров конфигурации.

URL и токен находим на странице Settings / CI/CD:

Указываем при регистрации теги, которые описаны в файле .gitlab-ci.yml, иначе раннер не будет брать джобы.

Если теги не используются, то после завершения регистрации указываем раннеру брать джобы без тегов:

В результате в проекте появится доступный раннер.

Поскольку в этом примере будет собираться Docker-образ, включаем privileged mode в настройках раннера. Для этого флагу privileged присваивается значение true в файле /srv/gitlab-runner/config/config.toml

Создание webhook

Переходим в раздел Settings / Webhook. Тут вводим URL функции, затем токен, который указали в константе gitlabToken, после чего выбираем триггер pipeline и нажимаем Add webhook:

Проверяем работу CI/CD

Сперва остановим ВМ. После этого создадим новую ветку в репозитории, изменим какой-нибудь файл и сделаем merge request.

Все три стейджа отработали без ошибок:

В реестре контейнеров создан Docker-образ:

В логах функции видно, что с момента запуска ВМ до завершения работы CI/CD прошло примерно 5 минут 20 секунд.

Анализ решения

Ниже приведена стоимость использования одной виртуальной машины с GitLab Runner в Compute Cloud за неделю. Если экстраполировать такое потребление на месяц, то выйдет примерно 200-250 рублей, что дешевле использования полноценной ВМ.

Основной ресурс, на который уходит бюджет — хранилище. Если сумма в 200-250 рублей — всё ещё много, то нужно сменить тип хранилища с SSD на HDD.Также в качестве платформы можно выбрать Intel Cascade Lake, так как она позволяет снизить гарантированную долю vCPU до 5%. Стоимость такой ВМ будет на 30-40% ниже, но и производительность её также будет ниже.

Плюсы такого решения:

  1. Относительно простая конфигурация, которая легко настраивается.

  2. Невысокая стоимость ресурсов облака, подходит для небольших pet-проектов.

Минусы:

  1. Если на одной ВМ развёрнуты раннеры от нескольких проектов, то нужно усложнять логику включения / отключения ВМ, так как ВМ может внезапно отключиться при завершении работы одного из раннеров.

Комментарии (13)


  1. screwer
    02.11.2022 11:37
    +1

    Как все сложно... За ~100тыс рублей собирается сервер с 72 vCPU, 256Gb RAM, 2Tb SSD и 10Tb HDD. Туда ставится собственная копия gitlab. И вы получаете мощное и быстрое железо с минимальным пингом в своей локальной сети. Без облаков и прочего.

    Даже не учитывая арендную плату, посчитайте сколько дней вы потратили на внедрение костылей, чтобы в итоге получить слабенькое решение.


    1. valery1707
      02.11.2022 13:32

      Сервер в "локальной сети" удобен, когда все разработчики тоже находятся в этой "локальной сети".


      1. screwer
        02.11.2022 14:25

        Конечно!
        Но даже если нет - SSH/VPN туннель в сеть работодателя будет ничем не хуже решений "с облаком".


        1. valery1707
          02.11.2022 18:19

          Да, именно - внешний доступ в сеть с таким сервером тоже нужно будет как-то обеспечивать, так же как и максимальный аптайм электричества и интернета вкупе с фиксированным IP для точки входа (или через dyn-dns привязывать его к домену) что превращается в кучу головняка с велосипедами, которые в итоге становятся не проще и не дешевле решения "с облаком".


          1. screwer
            02.11.2022 18:59

            точно также, как сейчас у фирмы функционируют другие сервера. Нету их ? Странно, что это за фирма такая... Впрочем, VPS за пару баксов/мес. справится с туннелированием.

            Только вот результат получаем разный, на несколько порядков. Могучий многопоток с огромным обьёмом оперативки и дисков. На который можно ещё пачку задач повесить - базы данных, виртуалки, Jira и т.д. Или дохлый облачный "сервер", который уступит даже современному ноуту из лоу-мид сегмента. Что вы на нём собирать будете, и как долго ? Как быстро упрётесь в ООМ ? Самое смешное - опасаясь "переплатить".


            1. valery1707
              03.11.2022 14:24

              Нету их ? Странно, что это за фирма такая...

              Ну нету - а чего странного?
              Конечно есть и хранилище исходников и система учёта задач и шаринг файлов, но всё это решается через "облака" и, в некоторых случаях, даже на бесплатных тарифах.
              Автор статьи, например, так и вовсе не совсем "фирма" и у них может и нет ничего кроме приведённых сервисов.
              А ещё есть стартапы, фирмы на начальном этапе организации и прочие и прочие.

              Только вот результат получаем разный, на несколько порядков.

              Как и их стоимость. Особенно с учётом этой ветки.

              Впрочем, VPS за пару баксов/мес. справится с туннелированием.

              А вот и велосипеды подъехали.

              Что вы на нём собирать будете, и как долго? Как быстро упрётесь в ООМ?

              Ну мало у кого занят сборочный сервер в режиме 24/7. Да и сам проект часто не требует много RAM для сборки. Причём в рамках рассмотренного решения никто не мешает заупскать сервер с большим количеством RAM, CPU и GPU - и это всё ещё будет иметь ценник подъёмный даже одиночному разработчику.

              И только не надо рассказывать как надёжны облака. Например, чем они рискуют, случайно уничтожив все ваши данные? Дадут $5 скидку на следующий заказ?

              И разве своё железо надёжнее "само по себе"? Сдохнет диск - кто-нибудь даст "хотя бы" скидку? Вынесут через окно? Уборщица "протрёт"? Тем более если брать б/у - оно может умереть даже без помощи извне.
              Возникают вопросы дублирования, бэкапов, активной поддержки.

              Естественно я понимаю что "облака" это просто "чужие сервера", но в них входит не "просто железо", а так же его поддержка, сопровождение, замена, обновление (включая софт) а так же возможность гибко управлять выделяемыми ресурсами (RAM, CPU, HDD/SSD, GPU).

              Вопрос переезда на bare-metal нужно решать тогда когда он реально себя проявляет, а не на начальном этапе организации компании - в этот момент ещё нет ни понимания требований к железу ни, собствено, средств которые можно "заморозить" в железе.
              Естественно крупная фирма существующая продолжительное время и имеющая план на ближашие несколько лет скорее всего получит профит от перехода на bare metal и self-hosted ПО.

              Напомню что статья рассказывает про решение для "создания публикаций в социальных сетях", используемом в неком "профсоюзе".
              И они получили требуемый им функционал за ~250 р./мес. что в год будет около 3к руб. Плюс время на ресёч и реализацию.
              Вы же предлагаете им сразу использовать bare metal за 100к, причём б/у, без дублирования, гарантий, поддержки, с необходимостью оплачивать Интернет и электричество для него, плюс сервер для реализации точки доступа в его сеть, плюс место для организации "серверной", плюс администрирование всего этого "счастья".
              И всё это - в ультимативной форме.
              Да, bare metal будет производительнее, но будет ли такое решение лучше удовлетворять изначальным требованиям?


    1. FlashHaos
      03.11.2022 08:56
      +1

      Где вы такой сервер за 100 тысяч купите? Только не предлагайте барахолки, в нормальных конторах предполагаются, что сервер будет работать пять лет с гарантией, а все проблемы решит вендор. И еще, пожалуйста, не забудьте георезерв для него.


      1. screwer
        03.11.2022 10:57
        +1

        На Али, списанные Зионы из датацентров. Иначе такую производительность на рубль не получить. Хотите гарантий - платите. Или урезайте ТТХ. Десктоп из магазина за те же 100тыс.будет всего в несколько раз слабее, но новый. И все ещё во много раз мощнее того мусора, что предлагался в статье.
        Какой нибудь 1 процессорный 10 ядерник с 32гб обойдется в смешные тысяч 13, за мать+память+мобо. Возьмите их пучок.

        И только не надо рассказывать как надёжны облака. Например, чем они рискуют, случайно уничтожив все ваши данные ? Дадут $5 скидку на следующий заказ ?


        1. zahnah
          03.11.2022 14:44

          Мне кажется тут основная экономия в первую очередь на обслуживании. В облаке один сотрудник может сделать в разы больше и поддерживать в разы больше, чем то же самое в своём личном физическом сервере.

          Я могу в одно лицо в aws и yandex.cloud содержать ну десяток-другой серверов(воркеры, балансировщик, фронтовые сервера, бд и т.п.), использовать бакеты, сертификаты, и т.п., не будучи девопсом. И я вижу миллион логов и статистики, что позволяет решить почти все проблемы без захода на сервер.

          В тоже самое время в Вилабаджо по старинке берут свой сервер и придумывают это всё самостоятельно, надеясь на то, что их личный девопс не рукожоп и не похоронит всё это в какой-то момент.

          Я вот почему-то больше верю яндекс облаку, чем этому девопсу-рукожопу


  1. sergeykons
    02.11.2022 15:54
    +2

    Вы придумали старую схему с раннером типа docker machine. Насколько я помню так довольно часто делали на том же амазоне


    1. AlexGluck
      04.11.2022 00:52
      +2

      Нормальные люди и сейчас делают ранеры с типом docker machine и не извращаются созданием собственных костылей.
      Вот дока гитлаба:
      https://docs.gitlab.com/runner/configuration/autoscale.html
      Вот офф плагин для ЯО:
      https://github.com/yandex-cloud/docker-machine-driver-yandex


      1. RoboNET
        04.11.2022 15:05

        Сейчас используем на работе как раз такое решение, однако есть проблема с тем, что иногда из-за каких-то проблем (не изучал глубоко их причины), docker-machine не может запустить или остановить VM в яндекс облаке, и она остается у него в подвисшем статусе, со временем эти записи в конфиге docker-machine достигают такого размера, что он начинает тормозить и перестает обрабатывать любые команды, и приходится руками удалять все записи о них из файловой системы основного раннера (легкого способа автоматически удалять я не придумал, так как если в момент удаления какая-то из созданных VM будет запущена в облаке, она уже не удалится средствами docker-machine). Не было ли у вас таких проблем, и если были, то как вы смогли их побороть?


  1. valmont2k
    03.11.2022 22:27

    В яндекс спот инстансы существуют?