В CI / CD, как управлять зависимостями между внешним и внутренним интерфейсом? - PullRequest
0 голосов
/ 21 ноября 2018

Я опишу мои настройки, чтобы сделать проблемы менее абстрактными, но они не кажутся специфичными для моего случая.

Контекст

У нас есть бэкенд Python-Django и интерфейс VueJSкаждый в репозитории, с Gitlab-CI, настроенным и развернутым с использованием Portainer (с использованием стека).Коммит в производственной ветви каждого репозитория следует по этому пути:

  1. commit
  2. конвейер gitlab-ci:
    1. сборка образа сборки
    2. testimage (внешний интерфейс протестирован с развернутым бэкэндом)
    3. изображение тега как производственное: последнее
    4. отправка изображения обратно в реестр gitlab
    5. webhook соответствующая служба (frontend / backend) в Portainerобновить развернутый образ
  3. portainer:
    1. pull image
    2. deploy

Проблемы

Синхронизация развертывания

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

В нашей текущей настройке мы должны сначала развернуть бэкэнд (что сломает развернутый фронтенд), а затем развернуть новый фронтэнд, исправив производство, но с "down"period.

Зависимость ветвления для тестов

Иногда, когда мы разрабатываем ветвь Feature-1 во внешнем интерфейсе, она должна быть проверена на ветвь Feature-1 из внутреннего интерфейса.

InВ нашей текущей настройке все коммиты во внешнем интерфейсе тестируются с развернутым бэкэндом (чтобы избежать репликации бэкенда в CI, используется только адрес производственного API), что приводит к ложным результатам тестирования в таких случаях.

Интеграция с бэкендомtests

Когда коммит выполняется в бэкэнде, он может сломать внешний интерфейс.

В настоящее время бэкэнд не тестируется во внешнем интерфейсе (только другим способом).

Возможные решения

В связи с проблемой синхронизации развертывания я подумал о создании другого хранилища, которое будет иметьтолько один файл, указывающий версии для внешнего интерфейса и внутреннего интерфейса, которые должны быть развернуты.Фиксация в этом репозитории приведет к тому, что оба веб-подключения сервисов Portanier будут «свернуты» для обновления (backend и frontend).Это не гарантирует одновременное обновление (в Portainer может произойти сбой, и отката не будет), но это будет лучше, чем текущая настройка.

Я не уверен, что следует использовать для указания версийздесь: commit hash, git tag, branch, версия образа докера ... Последнее, возможно, избегает необходимости перестраивать и тестировать образы, но я думаю, что имя и версии изображений фиксированы в определении стеков Portainer, и их нелегко автоматически обновлять.

Для тестов зависимостей ветвей я думал о том, чтобы в каждом репозитории был файл (внешний и внутренний), указывающий, с какой веткой из внутреннего / внешнего интерфейса нужно тестировать.Но CI для каждого репозитория должен будет реплицировать всю среду развертывания (например, запустить новый бэкэнд и внешний интерфейс для тестирования каждого коммита внешнего интерфейса).Это также позволило бы провести интеграционные тесты.Поскольку мы используем Docker, это не очень сложно, но потребует дополнительного времени для каждого конвейера CI ... Кроме того, когда первый репозиторий (внешний или внутренний) фиксируется, он будет ссылаться на еще не существующую ветвь в другомхранилище и сбой ...

Эти решения кажутся мне неловкими, особенно если эти проблемы являются общими для CI / CD с Docker.И это может стать еще страшнее, когда мы добавим больше репозиториев в микс.

Альтернативы?

Спасибо за внимание!

( edit: дляЛюбопытно, что мои текущие настройки были основаны на этой статье )

Ответы [ 2 ]

0 голосов
/ 06 января 2019

Зависимость ветвления для тестов

Иногда, когда мы разрабатываем ветвь Feature-1 во внешнем интерфейсе, она должна быть> протестирована с ответвлением Feature-1 от внутреннего интерфейса.

В нашемпри текущей настройке все коммиты во внешнем интерфейсе проверяются на развернутый бэкэнд (во избежание репликации бэкэнда в CI используется только адрес производственного API), что приводит к ложным результатам тестирования в таких случаях.

и

Интеграционные тесты бэкэнда

Когда коммит выполняется с бэкэндом, он может сломать фронтэнд.

В настоящее время бэкэнд не тестируется с фронтэндом(только в другую сторону).

В моей нынешней компании у нас есть Django для внешнего интерфейса (FE) и внутреннего интерфейса (BE), каждый в репозитории.мы следим за развитием магистральных сетей.Мы также используем gitlab для CI / CD.Я выкатил то, что вы упомянули здесь, и совсем не чувствовал себя неловко.

Отношения между средами и этой моделью ветвления.

| Ветви | пример| окружающая среда |

| мастер | мастер |staging |

| release-v * | release-v1.1.10 | preprod |

Tag:

| Tag | пример |окружающая среда |

| v . . |v.1.1.10 | Производство |

После создания веток / тегов или фиксации в определенных ветвях gitlab запустит автоматическую сборку / развертывание.

Необходимо протестировать интерфейсбэкэндмы делаем это с помощью ветви функций.

feature /

разработчики должны обеспечить одинаковое имя ветви функции, существующее как в FE, так и в BE.

URL для каждого внешнего интерфейса / бэкэнда создается для каждого развертывания, выглядит как -fe. .com для внешнего интерфейса -be. .com для внутреннего интерфейса

например: есть функция/ mytask в обоих репозиториях FE / BE.URL-адрес FE - mytask-fe. .com, а URL-адрес BE - mytask-be. .com

Вы можете использовать docker-compose, но в моем случае наше приложение развертывается в kubernetes с помощьюшлем.Чуть дальше этой реализации My FE и BE имеют вход k8s, который управляется traefik.DNS-запись (для каждого URL-адреса) автоматически создается (с помощью контроллера DNS k8s), серверная часть использует DB и Redis, которые создаются каждый раз, когда создается или изменяется ветвь компонента.Согласно соглашению об именах ветвей функций, FE знает, как подключиться к BE, а BE знает, как использовать свою собственную БД и Redis.

Например: обновление руля --install $ {RELEASE_NAME}...

RELEASE_NAME извлекается из функции / <отраслевая сводка> (не более 63 символов)

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

*) Разработчикам удастся заполнить данные (возможно, запустить скрипт в качестве контейнера инициализации в k8s).Если разработчик выдвигает коммит в одну и ту же ветку функций, это вызовет повторное развертывание, и все данные DB / Redis будут повторно инициированы.Разработчику, возможно, потребуется заново заполнить данные, а QC, возможно, потребуется перезапустить их тестирование с начала этой функции.

*), чтобы избежать создания слишком большого количества ресурсов в k8s и ветвях в репозитории gitlab.Я установил функцию удаления в gitlab CI, чтобы удалить ветвь функций в репозитории BE / FE, которая инициирует удаление развертывания в k8s соответственно.

0 голосов
/ 21 ноября 2018

Синхронизация развертывания

Представьте, что мы вносим существенные изменения как в интерфейс, так и в интерфейс, и оба они станут несовместимыми с предыдущими версиями.Таким образом, новые версии должны быть развернуты одновременно.

В нашей текущей настройке мы должны сначала развернуть бэкэнд (что сломает развернутый фронтенд), а затем развернуть новый фронтэнд, исправив производство, но с «down»period.

Я не пользователь portainer, но, может быть, вы могли бы положиться на какой-нибудь файл docker-compose.yml или около того, собирая как версию бэкэнда, так и интерфейс?в этом случае они могут быть обновлены одновременно…

Действительно, в соответствии с portainer / portainer # 1963 и на этой странице документа , portainer, кажется, поддерживает оба docker-составлять и копить стеки.

Кроме того, Docker Swarm предоставляет некоторые функции для обновления службы без простоев, как описано в этом блоге , но я не знаю, в какой степени это можно настроитьв portainer.

Возможные решения

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

Хотя хэши фиксации являются точными идентификаторами, ониВероятно, недостаточно удобно для выявления несовместимых версий.Поэтому вы можете использовать семантическое управление версиями с использованием тегов (и / или ветвей) в своем репозитории Git backend.

Затем вы можете соответствующим образом пометить соответствующие изображения Docker, введя некоторые синонимные тегиесли нужно.Например, предполагая, что серверная часть была выпущена с версиями 1.0.0, 1.0.1, 1.1.0, 1.1.1, 1.2.0, 1.2.1, 1.2.2, стандартная практика заключается в маркировке образов Docker следующим образом:

  • project/backend:2.0.2 = project/backend:2.0 = project/backend:2
  • project/backend:2.0.1
  • project/backend:2.0.0
  • project/backend:1.1.1 = project/backend:1.1 = project/backend:1
  • project/backend:1.1.0
  • project/backend:1.0.1= project/backend:1.0
  • project/backend:1.0.0

(удаление старых изображений при необходимости)

Бэкэнд-интеграционные тесты

В настоящее времябэкэнд не тестируется на внешнем интерфейсе (только наоборот).

ОК, но я думаю, что ваш подход довольно стандартный (внешний интерфейс зависит от бэкенда, а не наоборот).

В любом случае, я напомню, что даже если тестируемая система является интерфейсной, возможно, стоит реализовать модульные тесты (которые дешевле и дешевле разработать, чем интеграционные тесты), так что на первом этапеконвейер быстро запускает эти модульные тесты, прежде чем запускать необходимые интеграционные тесты.

Зависимость ветвления для тестовts

В нашей текущей настройке все коммиты во внешнем интерфейсе проверяются на развернутый бэкэнд (во избежание репликации бэкэнда в CI используется только адрес производственного API), что приводит к ложным результатам тестирования в таких случаях.

Это может быть недостаточно гибким: в общем случае CI / CD предполагает, что интеграционные тесты выполняются с использованием выделенного серверного экземпляра (сервер "dev" или сервер "pre-prod"), и если всеИнтеграционные тесты и системные тесты проходят, образ развертывается на сервере «prod» (и отслеживается и т. д.)

Я вижу из вашего поста, что вы используете GitLab CI, который имеет некоторый собственный Dockerподдержка , так что, возможно, это можно было бы легко реализовать.

Пара подсказок:

  • Предположим, что бэкэнд был изменен в версии, не совместимой с предыдущими,и соответствующий образ Docker доступен в реестре (например, в GitLab CI).Затем вы можете просто изменить спецификацию этого образа в конфигурации внешнего интерфейса (например, заменив project/backend:1 на project/backend:2 или около того в GitLab CI conffile).

  • Ваш бэкэнд, вероятно, реализован в виде веб-службы REST, и в этом случае вы также можете добавить префикс версии в свой URL, чтобы при переключении с project/backend:1 на project/backend:2 (с несовместимыми изменениями)при необходимости обе версии могут быть развернуты одновременно по URL-адресам https://example.com/api/v1/… и https://example.com/api/v2/…

Кроме того, помимо решения иметь только два репозитория с CI / CD(бэкэнд протестирован отдельно, а веб-интерфейс протестирован с соответствующей версией бэкэнда), решение, которое вы предложили в первую очередь, также может быть рассмотрено:

Для проблемы синхронизации развертывания я подумал о создании другого репозиторияв нем будет только один файл с указанием версий для внешнего и внутреннего интерфейсов, которые должны быть развернуты.Фиксация в этом репозитории приведет к тому, что оба веб-подключения сервисов Portanier будут «свернуты» для обновления (backend и frontend).Это не гарантирует одновременное обновление (в Portainer может произойти сбой, и отката не будет), но это будет лучше, чем текущая настройка.

Вы можете немного изменить этот подход, чтобы избежать одного такогоошибка развертывания: вы можете добавить некоторые настройки CI к этому третьему репо, которые будут содержать только файл docker-compose.yml или около того, и переместить интеграционные тесты из внешнего интерфейса CI в этот «составной» CI…

(FYIэтот подход аналогичен предложенному в этом руководстве по DigitalOcean , где интеграционное тестирование выполняется благодаря некоторому файлу docker-compose.test.yml.)

...