CI/CD для архитектур микрослужб

Azure

Более быстрые циклы выпуска являются одним из основных преимуществ архитектур микрослужб. Но без хорошего процесса CI/CD вы не достигнете гибкости, которую обещают микрослужбы. В этой статье описываются проблемы и рекомендуется использовать некоторые подходы к проблеме.

Что такое CI/CD?

Когда мы говорим о CI/CD, мы действительно говорим о нескольких связанных процессах: непрерывной интеграции, непрерывной доставке и непрерывном развертывании.

  • непрерывной интеграции. Изменения кода часто объединяются в основную ветвь. Автоматизированные процессы сборки и тестирования гарантируют, что код в главной ветви всегда является рабочим качеством.

  • непрерывной доставки. Любые изменения кода, которые передают процесс CI, автоматически публикуются в рабочей среде. Развертывание в рабочей среде может потребовать ручного утверждения, но в противном случае автоматизировано. Цель заключается в том, что код всегда должен быть готов для развертывания в рабочей среде.

  • непрерывное развертывание. Изменения кода, которые передают предыдущие два шага, автоматически развертываются в рабочей.

Ниже приведены некоторые цели надежного процесса CI/CD для архитектуры микрослужб:

  • Каждая команда может создавать и развертывать службы, принадлежащие ему независимо, не затрагивая или не нарушая другие команды.

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

  • Новую версию службы можно развернуть параллельно с предыдущей версией.

  • Существуют достаточные политики управления доступом.

  • Для контейнерных рабочих нагрузок можно доверять образы контейнеров, развернутые в рабочей среде.

Почему надежный конвейер CI/CD имеет значение

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

Следуя философии микрослужб, никогда не должно быть длинного поезда выпуска, где каждая команда должна быть в очереди. Команда, которая создает службу "A", может выпускать обновление в любое время, не ожидая изменения в службе "B", чтобы быть объединены, протестированы и развернуты.

схема монолитного CI/CD

Чтобы достичь высокой скорости выпуска, конвейер выпуска должен быть автоматическим и высоконадежным, чтобы минимизировать риск. Если вы выпускаете в рабочую среду один или несколько раз ежедневно, регрессии или нарушения работы служб должны быть редкими. В то же время, если плохое обновление развертывается, необходимо иметь надежный способ быстро отката или отката к предыдущей версии службы.

Проблемы

  • множество небольших независимых баз кода. Каждая команда отвечает за создание собственной службы с собственным конвейером сборки. В некоторых организациях команды могут использовать отдельные репозитории кода. Отдельные репозитории могут привести к ситуации, когда знание о том, как создать систему распространяется между командами, и никто в организации не знает, как развернуть все приложение. Например, что происходит в сценарии аварийного восстановления, если необходимо быстро развернуть в новом кластере?

    устранение рисков: единый и автоматизированный конвейер для создания и развертывания служб, чтобы эти знания не были скрытыми в каждой команде.

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

    устранения рисков: контейнеризация процесса сборки для каждой службы. Таким образом, системе сборки необходимо просто иметь возможность запускать контейнеры.

  • интеграции и нагрузочного тестирования. При выпуске обновлений командами в собственном темпе может быть сложно разработать надежное комплексное тестирование, особенно если службы имеют зависимости от других служб. Кроме того, выполнение полного рабочего кластера может быть дорогостоящим, поэтому вряд ли каждая команда будет запускать собственный полный кластер в масштабах рабочей среды только для тестирования.

  • управления выпусками. Каждая команда должна иметь возможность развернуть обновление в рабочей среде. Это не означает, что у каждого члена команды есть разрешения на это. Но наличие централизованной роли диспетчера выпусков может снизить скорость развертывания.

    устранение рисков: чем больше процесс CI/CD автоматизирован и надежнее, тем меньше необходимо для центрального центра. Тем не более чем у вас могут быть разные политики для выпуска основных обновлений компонентов и незначительных исправлений ошибок. Децентрализованность не означает нулевое управление.

  • обновления службы. При обновлении службы до новой версии она не должна прерывать другие службы, зависящие от нее.

    устранение рисков. Используйте такие методы развертывания, как синий зеленый или канарной выпуск для некричных изменений. Для критических изменений API разверните новую версию параллельно с предыдущей версией. Таким образом, службы, использующие предыдущий API, можно обновить и протестировать для нового API. См. обновления службниже.

Monorepo vs. Multi-repo

Перед созданием рабочего процесса CI/CD необходимо знать, как будет структурирована и управляема база кода.

  • Работают ли команды в отдельных репозиториях или в monorepo (один репозиторий)?
  • Что такое ваша стратегия ветвления?
  • Кто может отправить код в рабочую среду? Существует ли роль диспетчера выпусков?

Подход monorepo получил пользу, но есть преимущества и недостатки для обоих.

  Monorepo Несколько репозиториев
Преимущества Общий доступ к коду
Упрощение стандартизации кода и инструментов
Проще рефакторинг кода
Возможность обнаружения — одно представление кода
Очистка владения для каждой команды
Потенциально меньше конфликтов слиянием
Помогает обеспечить разобщение микрослужб
вызовов Изменения общего кода могут повлиять на несколько микрослужб
Больший потенциал для конфликтов слиянием
Инструмент должен масштабироваться до большой базы кода
Управление доступом
Более сложный процесс развертывания
Труднее поделиться кодом
Труднее применять стандарты кодирования
Управление зависимостями
Диффузная база кода, низкая возможность обнаружения
Отсутствие общей инфраструктуры

Обновление служб

Существуют различные стратегии обновления службы, которая уже находится в рабочей среде. Здесь мы обсудим три распространенных варианта: последовательное обновление, сине-зеленое развертывание и канареарный выпуск.

Последовательное обновление

В последовательном обновлении развертываются новые экземпляры службы, а новые экземпляры начинают получать запросы сразу. По мере создания новых экземпляров предыдущие экземпляры удаляются.

Пример. В Kubernetes последовательное обновление — это поведение по умолчанию при обновлении спецификации pod для развертывания. Контроллер развертывания создает новый набор реплик для обновленных модулей pod. Затем он масштабирует новый набор реплик во время масштабирования старого, чтобы сохранить требуемое число реплик. Он не удаляет старые модули pod до тех пор, пока новые не будут готовы. Kubernetes сохраняет журнал обновления, поэтому при необходимости можно откатить обновление.

Пример. Azure Service Fabric использует стратегию последовательного обновления по умолчанию. Эта стратегия лучше всего подходит для развертывания версии службы с новыми функциями, не изменяя существующие API. Service Fabric запускает развертывание обновления, обновив тип приложения до подмножества узлов или домена обновления. Затем он выполняет перекат к следующему домену обновления до тех пор, пока все домены не будут обновлены. Если домен обновления не удается обновить, тип приложения откатится к предыдущей версии во всех доменах. Помните, что тип приложения с несколькими службами (и если все службы обновляются в рамках одного развертывания обновления) подвержены сбою. Если не удается обновить одну службу, все приложение откатится до предыдущей версии, а другие службы не обновляются.

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

Для критических изменений API рекомендуется поддерживать обе версии параллельно, пока не будут обновлены все клиенты предыдущей версии. См.управления версиями API .

Развертывание сине-зеленого цвета

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

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

пример. В Kubernetes не нужно подготавливать отдельный кластер для развертывания сине-зеленого цвета. Вместо этого можно воспользоваться селекторами. Создайте ресурс развертывания с новой спецификацией pod и другим набором меток. Создайте это развертывание, не удаляя предыдущее развертывание или не изменяя службу, которая указывает на нее. После запуска новых модулей pod можно обновить селектор службы, чтобы он соответствовал новому развертыванию.

Одним из недостатков развертывания сине-зеленого цвета является то, что во время обновления выполняется в два раза больше модулей pod для службы (текущей и следующей). Если для модулей pod требуется много ресурсов ЦП или памяти, возможно, потребуется временно увеличить масштаб кластера для обработки потребления ресурсов.

Канарийный выпуск

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

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

пример. В Kubernetes можно настроить service для охвата двух наборов реплик (по одному для каждой версии) и настроить счетчики реплик вручную. Однако этот подход является довольно грубым, из-за того, как Kubernetes балансировка нагрузки между модулями pod. Например, если у вас есть всего 10 реплик, можно перемещать трафик только в 10% добавок. При использовании сетки служб можно использовать правила маршрутизации сетки служб для реализации более сложной стратегии выпуска канарной версии.

Дальнейшие действия