Мотив
Я хочу полностью автоматизировать развертывание многих сервисов с помощью Google Cloud Build и Google Kubernetes Engine . Эти сервисы расположены внутри monorepo , в котором есть папка с именем services
.
. Поэтому я создал cloudbuild.yaml
для каждого сервиса и создал триггер сборки. cloudbuild.yaml
выполняет:
- запуск тестов
- сборка новой версии образа Docker
- push новый образ Docker
- применение изменений к кластеру Kubernetes
Проблема
По мере увеличения количества служб увеличивается и количество триггеров сборки. Также все больше и больше сервисов создаются, даже если они не изменились.
Таким образом, я хочу механизм, который имеет только один триггер сборки и автоматически определяет, какие сервисы должны бытьrebuild.
Пример
Предположим, у меня есть монорепо с такой файловой структурой:
├── packages
│ ├── enums
│ ├── components
└── services
├── backend
├── frontend
├── admin-dashboard
Затем я внесу некоторые изменения в сервис frontend
. Поскольку службы frontend
и admin-dashboard
зависят от пакета components
, необходимо перестроить несколько служб:
Но не бэкэнд!
То, что я попробовал
(1) Несколько триггеров сборки
Настройка нескольких триггеров сборки для каждый сервис. Но 80% этих сборок являются избыточными, поскольку большинство изменений в коде относятся только к отдельным сервисам. Также становится все сложнее управлять многими триггерами сборки, которые выглядят почти одинаково. Один файл cloudbuild.yaml
выглядит следующим образом:
steps:
- name: "gcr.io/cloud-builders/docker"
args:
[
"build",
"-f",
"./services/frontend/prod.Dockerfile",
"-t",
"gcr.io/$PROJECT_ID/frontend:$REVISION_ID",
"-t",
"gcr.io/$PROJECT_ID/frontend:latest",
".",
]
- name: "gcr.io/cloud-builders/docker"
args: ["push", "gcr.io/$PROJECT_ID/frontend"]
- name: "gcr.io/cloud-builders/kubectl"
args: ["apply", "-f", "kubernetes/gcp/frontend.yaml"]
env:
- "CLOUDSDK_COMPUTE_ZONE=europe-west3-a"
- "CLOUDSDK_CONTAINER_CLUSTER=cents-ideas"
(2) Цикл по файлам облачной сборки
Этот вопрос касается очень похожей проблемы. Поэтому я попытался установить один файл "1072 *" "точки входа" в корне проекта и перебрал все службы:
steps:
- name: 'gcr.io/cloud-builders/gcloud'
entrypoint: 'bash'
args:
- '-c'
- |
for d in ./services/*/; do
config="${d}cloudbuild.yaml"
if [[ ! -f "${config}" ]]; then
continue
fi
echo "Building $d ... "
(
gcloud builds submit $d --config=${config}
) &
done
wait
Это избавило бы от необходимости иметь несколько триггеров сборки. Но я также столкнулся с проблемами при использовании этого метода:
Каждый сервис отправляется в свой собственный процесс сборки с областью файлов этого конкретного сервиса. Это означает, что я могу получить доступ только к файлам внутри /services/specific-service
во время сборки. Для меня это полный облом (мне нужен доступ к файлам в родительских каталогах, таких как packages
и файлам конфигурации в корне).
(3) Сборка только измененных сервисов
Так как я хочумеханизм для создания только измененных сервисов, я попытался определить сервисы, которые нужно перестроить. Кажется, это довольно легко сделать с помощью lerna . Запуск
lerna changed --all --parseable
вернет пути файла списка к измененным пакетам следующим образом:
/home/username/Desktop/project/packages/components
/home/username/Desktop/project/services/frontend
/home/username/Desktop/project/services/admin-dashboard
Однако список также включает packages
, и я понятия не имею, как бы я былвозможность использовать этот список в скрипте для циклического обхода уязвимых сервисов. Также: когда я запускаю сборку (например, с помощью пометки коммита), lerna не сможет распознать измененные пакеты во время процесса сборки, так как изменения уже зафиксированы.
Я знаю, что этодлинный. Но я думаю, что это важная тема, поэтому я очень ценю любую помощь!
PS: Этот выглядит так, как выглядит мой настоящий проект, если вы хотите более внимательно изучить конкретный вариант использования.