В предыдущей статье мы обзорно рассмотрели основные компоненты CI/CD Kubernetes платформы Gitorion. В данной статье подробнее остановимся на реализации хостинга кода, системы управления версиями и непрерывной интеграции CI.

Абстрактная постановка задачи

Абстрактно задача прозвучала так:

  1. Подобрать и установить Git-сервер в Self-hosted исполнении, чтобы не зависеть от коммерческих и облачных решений;

  2. Организовать совместное внесение правок в код группой разработчиков так, чтобы они не мешали друг другу;

  3. Предусмотреть возможность предварительной демонстрации внесенных изменений руководству;

  4. Разработать механизм доставки внесенных изменений в продакшен после одобрения руководством;

  5. Максимально автоматизировать все процессы;

  6. Проработать возможность отката до предыдущих версий в случае ошибок.

Упрощенная схема абстрактной постановки задачи
Упрощенная схема абстрактной постановки задачи

Выбор хостинга кода и системы управления версиями

После непродолжительного поиска нашли легковесный Open-Source продукт Gitea, реализующий функции хостинга кода и совместной разработки на базе Git. Gitea создан как Self-hosted решение, однако на нем также запущен публичный хостинг кода Codeberg. В 2022 году был взят курс на коммерциализацию Gitea, что вошло в противоречие с п.1 поставленной выше задачи. В ответ на коммерциализацию Gitea, часть разработчиков сделала форк Forgejo, который будет оставаться независимым, принадлежать сообществу, иметь независимую кодовую базу и развиваться самодостаточно. Мы заменим Gitea на Forgejo и напишем об этом отдельную статью. Ниже рассмотрим решения на базе функционала Gitea, поскольку тот же самый функционал есть и в Forgejo.

Распределение Git-веток по контурам

Начали с создания 3х изолированных контуров (они же namespase в Kubernetes) - development, staging и production с идентичным набором микросервисов (frontend, backend, mysql/postgresql, redis и т.д) в каждом из контуров.

  • development - контур для разработчиков. Каждый программист создает свою под-ветку от main-ветки и вносит изменения в код проекта только в пределах своей под-ветки. Выполнив задание, делает push в Gitea. Gitea шлет Web-хук в Jenkins. Jenkins собирает Docker-контейнер микросервиса с кодом данного программиста и доставляет в динамическое окружение на review. Так мы решили вторую задачу.

  • staging - контур для демонстрации изменений руководству. Изменения из веток программистов тимлид организованно вливает в main-ветку и делает push в Gitea. Gitea так же шлет Web-хук в Jenkins, который собирает Docker-контейнер и доставляет в staging контур для демонстрации руководству. Так мы решили третью задачу.

  • production - продакшен контур. После одобрения руководством тимлид вручную запускает пайплайн в Jenkins, выполняющий промоушен Docker-образа из staging контура в production контур. Так мы решили четвертую задачу, но это скорее относится к непрерывной доставке CD, о которой речь пойдет в следующей статье

Схема CI/CD платформы Gitorion
Схема CI/CD платформы Gitorion

Порядок действий разработчика

Тимлид создает новому программисту аккаунт в Gitea (например user3).

Cписок пользователей в Gitea
Cписок пользователей в Gitea

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

Cписок соавторов репозитория микросервиса backend
Cписок соавторов репозитория микросервиса backend

Программист user3 клонирует Git-репозиторий, создает под-ветку (например dev1).

Cписок веток репозитория микросервиса backend
Cписок веток репозитория микросервиса backend

И приступает к выполнению задания. Добавляет правки в код, делает push-в свою ветку. Jenkins автоматически собирает Docker-образы микросервиса с правками программиста и доставляет его на review в development контур. Предварительные результаты работы можно оценить по ссылке https://review-frontend-dev1.example.com (dev1 - ветка разработчика).

Выполнив задание, программист user3 создает запрос Pull Request на вливание изменений из своей ветки dev1 в main-ветку и докладывает тимлиду о выполнении задания.

Запрос на слияние в личном кабинете программиста
Запрос на слияние в личном кабинете программиста

Красным показан код, который разработчик удалил, а зеленым код, который добавил. Для примера мы просто сменили версию в коде сайта.

Порядок действий тимлида

В личном кабинете тимлида появится запрос на слияние от разработчика user3.

Запрос на слияние в личном кабинете тимлида
Запрос на слияние в личном кабинете тимлида

Тимлид выбирает запрос на слияние и получает подробную информацию о нем.

Подробная информация о запросе на слияние
Подробная информация о запросе на слияние

Переходит на вкладку "Измененные файлы" и изучает внесенные программистом правки.

Правки, внесенные программистом
Правки, внесенные программистом

Если все в порядке, и программист верно выполнил задание, тимлид нажимает на кнопку "Cоздать коммит на слияние" и вливает изменения из ветки разработчика dev1 в main-ветку. В случае успешного слияния появится такое сообщение.

Сообщение об успешном слиянии веток
Сообщение об успешном слиянии веток

Коммит на слияние инициирует Web-хук из Gitea в Jenkins. Jenkins автоматически соберет Docker-образ и доставит контейнер с наработками программиста в staging-контур, где тимлид сможет продемонстрировать внесенные изменения заказчику проекта.

Автоматизация

Для автоматизации задействовали механизм Web-хуков в Gitea и Jenkins. Все, что нужно сделать программисту или тимлиду для внесения изменений в микросервис, это добавить правки в код и сделать push. Дальнейшие процессы происходят автоматически. Gitea, получив push, посылает Web-хук в Jenkins. Jenkins по Web-хуку вытягивает Git-репозиторий из Gitea и запускает пайплайн для микросервиса, стадии которого заданы в Jenkinsfile. Компилирует код приложения, если микросервис написан на компилируемом языке программирования, или просто копирует код в Docker-образ, если на интерпретируемом языке. Cобирает Docker-образ в соответствии со слоями, заданными в Dockerfile, и помещает в приватный репозиторий Docker Registry. Доставляет микросервис при помощи helm в кластер Kubernetes. За всеми этими процессами можно наблюдать в Web-интерфейсе Jenkins и оценить время выполнения как всего пайплайна, так и отдельных его стадий.

Добавить web-хук можно в настройках репозитория.

Список доступных типов Web-хуков
Список доступных типов Web-хуков

Выберите Web-хук типа Gitea, задайте URL сервиса Jenkins и токен доступа.

Параметры Web-хука
Параметры Web-хука

Защита веток

Сделав программиста соавтором, тимлид дает ему право вносить изменения не только в свою ветку, но и в main-ветку. Если все программисты будут неконтролируемо вносить изменения в main-ветку напрямую, начнется путаница и конфликты, и мы не выполним требование в п.2 поставленной задачи. Перейдите в настройки репозитория и создайте правила защиты веток.

Правила защиты веток в Gitea
Правила защиты веток в Gitea

Для ветки main cоздайте правило, разрешающее прямое внесение правок и вливание изменений Pull Request Merge только пользователям из белого списка (тимлидам, руководителям проекта).

Ограничение доступа к main-ветке по белому списку пользователей
Ограничение доступа к main-ветке по белому списку пользователей

Платформа построена в соответствии с подходом инфраструктура как код IaC. В одном Git-репозитории рядом с исходным кодом микросервиса хранятся: Dockerfile для сборки Docker-образа микросервиса, Jenkinsfile с пайплайном сборки и доставки, конфигурационные файлы микросервиса для всех 3х контуров, helm-чарт развертывания микросервиса в кластер Kubernetes.

Типовой набор директорий и файлов в репозитории микросервиса
Типовой набор директорий и файлов в репозитории микросервиса

Чтобы программисты не "сломали" процессы сборки и доставки, мы ограничили им доступ ко всем файлам и директориям репозитория, кроме директории src/ с исходным кодом микросервиса, с которым программисты будут непосредственно работать. Создали правило для всех веток с префиксом dev** и перечислили директории и файлы, к которым доступ программистам запрещен.

Ограничение доступа программистов к директориям и файлам в репозитории микросервиса
Ограничение доступа программистов к директориям и файлам в репозитории микросервиса

Заключение

В следующей статье мы рассмотрим подробнее тонкости реализации непрерывной доставки CD при помощи Jenkins, а также вспомогательные инструменты, которые потребовалось интегрировать в платформу для построения Continuous Delivery. Спасибо.

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


  1. angrykirc
    20.03.2024 18:54

    Не совсем понятна цель статьи. Ближе всего это к обзору конкретных решений в "платформе".
    Язык сухой, мозгу не за что зацепиться. Много написано про конкретные решения в части CI/CD, но не написано, как поступить, к примеру, если я у себя на проекте захочу построить процесс разработки иначе, чем предлагается. Вроде удобно, когда всё настроено "за тебя", а с другой стороны, избыточность такой настройки может ограничивать конечного пользователя.
    Я вот точно из таких же компонентов (Gitea+Jenkins+k8s) у себя развернул такую же "платформу", только вместо let's encrypt использовал step-ca+certbot, так как не хочу "светить" свой интранет в какой-нибудь crt.sh, и SSO сделал через authentik.
    В gitea до сих пор, кстати, не приняли PR с возможностью полного отключения локальной аутентификации, у Вас это тоже, как вижу, не исправлено. Подумайте, что будет, если пользователь "по незнанию" попытается залогиниться используя форму в интерфейсе gitea, а не keycloak?


    1. gitorion Автор
      20.03.2024 18:54

      Цель цикла статей - осветить наш вариант решения поставленной задачи. Задача - создать замену GitLab CI из бесплатных OpenSource инструментов, принадлежащих и контролируемых сообществом. Язык сухой потому что, это архитектурные наброски, чтобы не перегружать обзоры. Платформу развертывали в Kubernetes, а он позволяет удалять и добавлять в платформу любы OpenSource инструменты на усмотрение заказчика - это на наш взгляд не ограничение, а скорее наоборот преимущество перед коробочными решениями. Про SSO и Keycloak мы расскажем в отдельной статье и под ней можно будет предметно обсудить нюансы и избыточность. А почему не стали использовать GitLab CI, если не секрет?