Golang монорепозиторий

Хочу попробовать поработать с монорепозиторием в Golang. Но у меня есть несколько открытых вопросов перед тем как начать.

Структура:

- cmd
--- /services - микросервисы (auth, profile ...etc)
--- /workers - воркера
- pkg
- internal
--- /migrations
----/validators
......... etc ......

По структуре проекта пока заглядываю в репозитории Google

Микросервис - web контейнер который умеет http, и писать в RabbitMQ. Worker - слушает только RabbitMQ.

Так как и веб, и воркер будет ходить в базу данных - удобно когда все models в одном репозитории (поэтому и монорепозиторий).

Инфра

Буду запускать проект в minikube.

И так, вопросы:

  1. Prometheus, Pushgateway и другие контейры (приложение с go внутри Docker) запускают goroutine внутри контейнера. Это и есть лучшие практити Docker? Как я понимаю, goroutine это отдельный поток - worker. Если это ок, можно больше информации об этом?) Моя мысль такая: в k8s есть deployment в которого есть replicas - сколько worker/web нужно, столько и деплоим, но они должны быть отдельно.

  2. Как построить CI? Если все в одном репозитории то CI не знает какой именно сервис изменился. Нужно собирать все? А если сервисов будет 20? 20 билдов при каждому push?)

  3. Deploy. Если все в одном репозитории, то и тег у всех сервисов общий. Катим все сразу?


Ответы (1 шт):

Автор решения: Senior Pomidor

ваш вопрос обширный. возможно, не все вопросы будут полностью отвеченные.

goroutine - это как потоки, но ими не являются. Не путайте с системными потоками. Горутины более лайтовая версия, они работают в одном адресном пространстве, а все расходы — это создание стека. представьте их в виде worker-ов ))

-Это и есть лучшие практики Docker?
-нет, они никак не связаны. Docker используют для легкого запуска\деплоя приложения, которая не зависит от окружающей среды. Для той же сборки проекта нужны определенные предустановленные компоненты, например, go компилятор. Докер позволяет все шаги для компиляции исполнить почти изолированно от host-системы.

k8s deployment + replicas хорошая идея, когда делаете горизонтальное масштабирование. так как k8s работает поверх докера, то вам нужно иметь docker-image для работы

Как построить CI?
А зачем? цель CI - не допускать нерабочего кода в репозиторий, чтобы другие участники-разработчики не ломали голову, угадывая, где не работает.
Вы можете обойтись локальным запуском тестов, если работаете один.

Предположим, вам нужен CI для проверки тестами, сборкой, пушом на docker-registry. Почти все известные мне CI системы поддерживают системы запуска такие как "коммит в ветку", "выставление тэгов", "изменение файла". Вы можете настроить запуск на "изменение файла", например, если изменился /src/proj1, то запускать "Build 1", если /src/proj2, то "Build 1". Так можно сделать, если вы точно можете спрогнозировать какой проект изменился. Обычно в монорепах есть смежные каталоги\пакеты. Я вам рекомендую собирать все сразу, чтобы не усложнить жизнь. Если 20 сервисов уже собралось, то скорее всего вы делаете что-то не то. Лучше вынести core составляющую в отдельную репу и подключить как модуль к каждому проекту.

Deploy
в deployment.yaml вы указываете какую версию image нужно деплоить. Рекомендую деплоить не при каждом пуше в мастер(хотя так тоже можно). Можете использовать тэгирование как создание docker-image и push в registry. Тогда, вы можете создать новый тэг - запускается билд-сборщик, в deployment.yaml указываете новую версию вашего сервиса. K8s обновит только тот под, который изменился. Таким образом остальные сервисы не изменены. p.s. не используйте latest версию при каждом пуше в мастер.

Расскажу какая структура у меня

- .github
- cmd
--- /service1
--- /service2
- internal
- deploy
--- /production
--- /sttaging

......... etc ......

Я использую GitHun Actions. 2 вида билда
Первый - собирает docker-image, если появился тэг, пушает в registry

name: Build and push to ECS
# Only build when pushed with the version tag
on:
  push:
    tags:
    - 'v*'

jobs:
  build-publish:

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

name: Trigger deployment to EKS

on:
  push:
    paths:
      - 'deploy/**'

jobs:
  deploy:
    name: Setup, Build, Publish
→ Ссылка