В предыдущей статье мы обзорно рассмотрели основные компоненты CI/CD Kubernetes платформы Gitorion. В данной статье подробнее остановимся на реализации хостинга кода, системы управления версиями и непрерывной интеграции CI.
Абстрактная постановка задачи
Абстрактно задача прозвучала так:
Подобрать и установить Git-сервер в Self-hosted исполнении, чтобы не зависеть от коммерческих и облачных решений;
Организовать совместное внесение правок в код группой разработчиков так, чтобы они не мешали друг другу;
Предусмотреть возможность предварительной демонстрации внесенных изменений руководству;
Разработать механизм доставки внесенных изменений в продакшен после одобрения руководством;
Максимально автоматизировать все процессы;
Проработать возможность отката до предыдущих версий в случае ошибок.
![Упрощенная схема абстрактной постановки задачи Упрощенная схема абстрактной постановки задачи](https://habrastorage.org/getpro/habr/upload_files/da8/fb4/173/da8fb41739ade1b54c631049754d6ef2.png)
Выбор хостинга кода и системы управления версиями
После непродолжительного поиска нашли легковесный 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](https://habrastorage.org/getpro/habr/upload_files/91d/f7a/622/91df7a62287d7e01f40cd03f81b54329.png)
Порядок действий разработчика
Тимлид создает новому программисту аккаунт в Gitea (например user3).
![Cписок пользователей в Gitea Cписок пользователей в Gitea](https://habrastorage.org/getpro/habr/upload_files/e26/693/297/e266932974f76ac74d3c991fc8159ef1.png)
Делает разработчика соавтором репозитория микросервиса, в код которого программист будет вносить изменения.
![Cписок соавторов репозитория микросервиса backend Cписок соавторов репозитория микросервиса backend](https://habrastorage.org/getpro/habr/upload_files/28d/d6e/b88/28dd6eb88c875dac40600e015f7d4a00.png)
Программист user3 клонирует Git-репозиторий, создает под-ветку (например dev1).
![Cписок веток репозитория микросервиса backend Cписок веток репозитория микросервиса backend](https://habrastorage.org/getpro/habr/upload_files/b2f/b77/f04/b2fb77f04261cfb73afd159c2c627879.png)
И приступает к выполнению задания. Добавляет правки в код, делает push-в свою ветку. Jenkins автоматически собирает Docker-образы микросервиса с правками программиста и доставляет его на review в development контур. Предварительные результаты работы можно оценить по ссылке https://review-frontend-dev1.example.com (dev1 - ветка разработчика).
Выполнив задание, программист user3 создает запрос Pull Request на вливание изменений из своей ветки dev1 в main-ветку и докладывает тимлиду о выполнении задания.
![Запрос на слияние в личном кабинете программиста Запрос на слияние в личном кабинете программиста](https://habrastorage.org/getpro/habr/upload_files/908/5c1/3df/9085c13df8f921e19baa08c0c436c7e3.png)
Красным показан код, который разработчик удалил, а зеленым код, который добавил. Для примера мы просто сменили версию в коде сайта.
Порядок действий тимлида
В личном кабинете тимлида появится запрос на слияние от разработчика user3.
![Запрос на слияние в личном кабинете тимлида Запрос на слияние в личном кабинете тимлида](https://habrastorage.org/getpro/habr/upload_files/d12/cbf/b8e/d12cbfb8e487f3b02784702e696e3127.png)
Тимлид выбирает запрос на слияние и получает подробную информацию о нем.
![Подробная информация о запросе на слияние Подробная информация о запросе на слияние](https://habrastorage.org/getpro/habr/upload_files/80f/e59/0bc/80fe590bc707d04fdf3695bee826efe1.png)
Переходит на вкладку "Измененные файлы" и изучает внесенные программистом правки.
![Правки, внесенные программистом Правки, внесенные программистом](https://habrastorage.org/getpro/habr/upload_files/2b5/d61/7d3/2b5d617d34c9db8dfe42d49454a59a09.png)
Если все в порядке, и программист верно выполнил задание, тимлид нажимает на кнопку "Cоздать коммит на слияние" и вливает изменения из ветки разработчика dev1 в main-ветку. В случае успешного слияния появится такое сообщение.
![Сообщение об успешном слиянии веток Сообщение об успешном слиянии веток](https://habrastorage.org/getpro/habr/upload_files/1d6/12a/9f6/1d612a9f6d89b44c614e4e04b7631847.png)
Коммит на слияние инициирует 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-хуков](https://habrastorage.org/getpro/habr/upload_files/052/d6b/2e8/052d6b2e8550a1841279a5a75395b2cc.png)
Выберите Web-хук типа Gitea, задайте URL сервиса Jenkins и токен доступа.
![Параметры Web-хука Параметры Web-хука](https://habrastorage.org/getpro/habr/upload_files/ccb/61b/72a/ccb61b72a088455e1282f7c6c1515bd7.png)
Защита веток
Сделав программиста соавтором, тимлид дает ему право вносить изменения не только в свою ветку, но и в main-ветку. Если все программисты будут неконтролируемо вносить изменения в main-ветку напрямую, начнется путаница и конфликты, и мы не выполним требование в п.2 поставленной задачи. Перейдите в настройки репозитория и создайте правила защиты веток.
![Правила защиты веток в Gitea Правила защиты веток в Gitea](https://habrastorage.org/getpro/habr/upload_files/e8f/095/f25/e8f095f25059385935742903f2545ec8.png)
Для ветки main cоздайте правило, разрешающее прямое внесение правок и вливание изменений Pull Request Merge только пользователям из белого списка (тимлидам, руководителям проекта).
![Ограничение доступа к main-ветке по белому списку пользователей Ограничение доступа к main-ветке по белому списку пользователей](https://habrastorage.org/getpro/habr/upload_files/009/f21/6b7/009f216b72490d07c60da79acbcbd5f6.png)
Платформа построена в соответствии с подходом инфраструктура как код IaC. В одном Git-репозитории рядом с исходным кодом микросервиса хранятся: Dockerfile для сборки Docker-образа микросервиса, Jenkinsfile с пайплайном сборки и доставки, конфигурационные файлы микросервиса для всех 3х контуров, helm-чарт развертывания микросервиса в кластер Kubernetes.
![Типовой набор директорий и файлов в репозитории микросервиса Типовой набор директорий и файлов в репозитории микросервиса](https://habrastorage.org/getpro/habr/upload_files/110/547/e61/110547e61646379e619af66ca34d4530.png)
Чтобы программисты не "сломали" процессы сборки и доставки, мы ограничили им доступ ко всем файлам и директориям репозитория, кроме директории src/ с исходным кодом микросервиса, с которым программисты будут непосредственно работать. Создали правило для всех веток с префиксом dev** и перечислили директории и файлы, к которым доступ программистам запрещен.
![Ограничение доступа программистов к директориям и файлам в репозитории микросервиса Ограничение доступа программистов к директориям и файлам в репозитории микросервиса](https://habrastorage.org/getpro/habr/upload_files/6fa/ce3/67f/6face367f56d257484ace00762bbf7aa.png)
Заключение
В следующей статье мы рассмотрим подробнее тонкости реализации непрерывной доставки CD при помощи Jenkins, а также вспомогательные инструменты, которые потребовалось интегрировать в платформу для построения Continuous Delivery. Спасибо.
angrykirc
Не совсем понятна цель статьи. Ближе всего это к обзору конкретных решений в "платформе".
Язык сухой, мозгу не за что зацепиться. Много написано про конкретные решения в части CI/CD, но не написано, как поступить, к примеру, если я у себя на проекте захочу построить процесс разработки иначе, чем предлагается. Вроде удобно, когда всё настроено "за тебя", а с другой стороны, избыточность такой настройки может ограничивать конечного пользователя.
Я вот точно из таких же компонентов (Gitea+Jenkins+k8s) у себя развернул такую же "платформу", только вместо let's encrypt использовал step-ca+certbot, так как не хочу "светить" свой интранет в какой-нибудь crt.sh, и SSO сделал через authentik.
В gitea до сих пор, кстати, не приняли PR с возможностью полного отключения локальной аутентификации, у Вас это тоже, как вижу, не исправлено. Подумайте, что будет, если пользователь "по незнанию" попытается залогиниться используя форму в интерфейсе gitea, а не keycloak?
gitorion Автор
Цель цикла статей - осветить наш вариант решения поставленной задачи. Задача - создать замену GitLab CI из бесплатных OpenSource инструментов, принадлежащих и контролируемых сообществом. Язык сухой потому что, это архитектурные наброски, чтобы не перегружать обзоры. Платформу развертывали в Kubernetes, а он позволяет удалять и добавлять в платформу любы OpenSource инструменты на усмотрение заказчика - это на наш взгляд не ограничение, а скорее наоборот преимущество перед коробочными решениями. Про SSO и Keycloak мы расскажем в отдельной статье и под ней можно будет предметно обсудить нюансы и избыточность. А почему не стали использовать GitLab CI, если не секрет?