Создание конвейера CI/CD для микрослужб в Kubernetes с помощью Azure DevOps и Helm

Служба Azure Kubernetes (AKS)
Реестр контейнеров Azure
Azure DevOps

Это может быть сложно создать надежный процесс непрерывной интеграции и непрерывной доставки (CI/CD) для архитектуры микрослужб. Отдельные команды должны иметь возможность быстро и надежно выпускать службы, не нарушая другие команды или дестабилизируя приложение в целом.

В этой статье описывается пример конвейера CI/CD для развертывания микрослужб в Служба Azure Kubernetes (AKS). Каждая команда и проект отличаются, поэтому не берите эту статью в качестве набора жестких и быстрых правил. Вместо этого он должен быть отправной точкой для разработки собственного процесса CI/CD.

Цели конвейера CI/CD для размещенных микрослужб Kubernetes можно суммировать следующим образом:

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

Дополнительные сведения см. в разделе CI/CD для архитектур микрослужб.

Предположения

В этом примере ниже приведены некоторые предположения о команде разработчиков и базе кода:

  • Репозиторий кода — это monorepo с папками, упорядоченными микрослужбами.
  • Стратегия создания ветви команды основывается на разработке на основе магистрали.
  • Команда использует ветви выпуска для управления выпусками . Для каждой микрослужбы создаются отдельные выпуски.
  • Процесс CI/CD использует Azure Pipelines для создания, тестирования и развертывания микрослужб в AKS.
  • Образы контейнеров для каждой микрослужбы хранятся в Реестр контейнеров Azure.
  • Команда использует диаграммы Helm для упаковки каждой микрослужбы.
  • Используется модель принудительного развертывания, в которой Azure Pipelines и связанные агенты выполняют развертывания путем подключения непосредственно к кластеру AKS.

Эти предположения приводят к множеству конкретных сведений о конвейере CI/CD. Однако базовый подход, описанный здесь, можно адаптировать для других процессов, инструментов и служб, таких как Jenkins или Docker Hub.

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

Ниже приведены распространенные варианты, которые клиенты могут использовать при выборе стратегии CI/CD с Служба Azure Kubernetes:

  • В качестве альтернативы использованию Helm в качестве средства управления пакетами и развертывания Kustomize — это средство управления собственной конфигурацией Kubernetes, которое предоставляет бесплатный шаблон способ настройки и параметризации конфигурации приложения.
  • В качестве альтернативы использованию Azure DevOps для репозиториев и конвейеров Git Можно использовать репозитории GitHub для частных и общедоступных репозиториев Git, а GitHub Actions можно использовать для конвейеров CI/CD.
  • В качестве альтернативы использованию модели принудительного развертывания управление конфигурацией Kubernetes в большом масштабе можно сделать с помощью GitOps (модель развертывания по запросу), где оператор Kubernetes в кластере синхронизирует состояние кластера на основе конфигурации, хранимой в репозитории Git.

Сборки проверки

Предположим, что разработчик работает над микрослужбой, называемой службой доставки. При разработке новых компонентов разработчик проверяет код в ветви компонентов. По соглашению компоненты ветвей носят имя feature/*.

CI/CD workflow

Файл определения сборки включает триггер, который фильтрует по имени ветви и исходному пути:

trigger:
  batch: true
  branches:
    include:
    # for new release to production: release flow strategy
    - release/delivery/v*
    - refs/release/delivery/v*
    - master
    - feature/delivery/*
    - topic/delivery/*
  paths:
    include:
    - /src/shipping/delivery/

Благодаря этому подходу каждая команда может иметь свой собственный конвейер сборки. Только код, который проверка в /src/shipping/delivery папку, активирует сборку службы доставки. Отправка фиксаций в ветвь, которая соответствует фильтру, активирует сборку CI. На этом этапе в рабочем процессе сборка CI выполняет некоторые минимальные проверки кода.

  1. Выполните сборку кода.
  2. Запустите модульные тесты.

Цель заключается в том, чтобы обеспечить короткие сроки сборки, чтобы разработчик смог получить быстрые отзывы. После того как функция будет готова к слиянию в master, разработчик открывает pr. Эта операция активирует другую сборку CI, которая выполняет некоторые дополнительные проверка:

  1. Выполните сборку кода.
  2. Запустите модульные тесты.
  3. Создайте образ контейнера среды выполнения.
  4. Выполните сканирование уязвимостей на изображении.

Diagram showing ci-delivery-full in the Build pipeline.

Примечание.

В Azure DevOps Repos можно определить политики для защиты ветвей. Например, для слияния в главную ветвь политика может требовать успешную сборку CI, а также утверждение от утверждающего.

Полная сборка CI/CD

На некотором этапе группа готова к развертыванию новой версии службы доставки. Диспетчер выпусков создает ветвь из основной ветви с помощью этого шаблона именования: release/<microservice name>/<semver> Например, release/delivery/v1.0.2.

Diagram showing ci-delivery-full in the Build pipeline and cd-delivery in the Release pipeline.

Создание этой ветви активирует полную сборку CI, которая выполняет все предыдущие шаги плюс:

  1. Отправьте образ контейнера в Реестр контейнеров Azure. Образ отмечен номером версии, взятым из имени ветви.
  2. Запустите helm package , чтобы упаковать диаграмму Helm для службы. Диаграмма также помечена номером версии.
  3. Отправьте пакет Helm в реестр контейнеров.

Если эта сборка выполнена успешно, она активирует процесс развертывания (CD) с помощью конвейера выпуска Azure Pipelines. В этом конвейере приведены следующие действия.

  1. Разверните диаграмму Helm в среде QA.
  2. Утверждающий утверждает, прежде чем пакет переместится в рабочую среду. Дополнительные сведения см. в статье Release deployment control using approvals (Управление развертыванием выпуска с помощью утверждений).
  3. Перетащите образ Docker для рабочего пространства имен в Реестр контейнеров Azure. Например, если текущий маркер – myrepo.azurecr.io/delivery:v1.0.2, рабочим маркером будет myrepo.azurecr.io/prod/delivery:v1.0.2.
  4. Разверните диаграмму Helm в рабочей среде.

Даже в monorepo эти задачи можно область отдельным микрослужбам, чтобы команды могли развертываться с высокой скоростью. Этот процесс выполняет некоторые действия вручную: утверждение PR, создание ветвей выпуска и утверждение развертываний в рабочем кластере. Эти действия выполняются вручную; они могут быть автоматизированы, если организация предпочитает.

Изоляция сред

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

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

Процесс сборки

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

Используя многоэтапные сборки в Docker, можно определить среду сборки и образ среды выполнения в одном Dockerfile. Например, вот Файл Dockerfile, который создает приложение .NET:

FROM mcr.microsoft.com/dotnet/core/runtime:3.1 AS base
WORKDIR /app

FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
WORKDIR /src/Fabrikam.Workflow.Service

COPY Fabrikam.Workflow.Service/Fabrikam.Workflow.Service.csproj .
RUN dotnet restore Fabrikam.Workflow.Service.csproj

COPY Fabrikam.Workflow.Service/. .
RUN dotnet build Fabrikam.Workflow.Service.csproj -c release -o /app --no-restore

FROM build AS testrunner
WORKDIR /src/tests

COPY Fabrikam.Workflow.Service.Tests/*.csproj .
RUN dotnet restore Fabrikam.Workflow.Service.Tests.csproj

COPY Fabrikam.Workflow.Service.Tests/. .
ENTRYPOINT ["dotnet", "test", "--logger:trx"]

FROM build AS publish
RUN dotnet publish Fabrikam.Workflow.Service.csproj -c Release -o /app

FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "Fabrikam.Workflow.Service.dll"]

Этот Файл Dockerfile определяет несколько этапов сборки. Обратите внимание, что на этапе с именем base используется среда выполнения .NET, а на этапе с именем build используется полный пакет SDK для .NET. Этап build используется для создания проекта .NET. Но окончательный контейнер среды выполнения создается из base, который содержит только среду выполнения и значительно меньше, чем полный образ пакета SDK.

Создание тестового средства выполнения

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

FROM build AS testrunner
WORKDIR /src/tests

COPY Fabrikam.Workflow.Service.Tests/*.csproj .
RUN dotnet restore Fabrikam.Workflow.Service.Tests.csproj

COPY Fabrikam.Workflow.Service.Tests/. .
ENTRYPOINT ["dotnet", "test", "--logger:trx"]

Разработчик может использовать этот файл Docker для локального выполнения тестов:

docker build . -t delivery-test:1 --target=testrunner
docker run delivery-test:1

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

Обратите внимание, что этот файл использует команду Docker для выполнения тестов, а не команды Docker ENTRYPOINTRUN .

  • При использовании RUN команды тесты выполняются каждый раз при сборке образа. С помощью ENTRYPOINTтестов выполняется согласие. Они выполняются только в том случае, если вы явно нацелены на testrunner этап.
  • Неудачный тест не приводит к сбою команды Docker build . Таким образом, можно отличить сбои сборки контейнера от тестов.
  • Результаты теста можно сохранить в подключенном томе.

Рекомендации по контейнерам

Ниже приведены некоторые другие рекомендации по использованию контейнеров.

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

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

  • Всегда развертывать определенные теги версии контейнера, а не latest.

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

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

Чарты Helm

С помощью Helm можно управлять созданием и развертыванием служб. Ниже приведены некоторые функции Helm, которые помогают с CI/CD:

  • Часто одна микрослужба определяется несколькими объектами Kubernetes. Helm позволяет упаковать эти объекты в одну диаграмму Helm.
  • Диаграмму можно развернуть с помощью одной команды Helm, а не ряда команд kubectl.
  • Диаграммы явно версии. Используйте Helm для выпуска версии, просмотра выпусков и отката до предыдущей версии. Отслеживание обновлений и исправлений с использованием семантических версий, а также возможность отката к предыдущей версии.
  • Диаграммы Helm используют шаблоны, чтобы избежать дублирования данных, таких как метки и селекторы, во многих файлах.
  • Helm может управлять зависимостями между диаграммами.
  • Диаграммы можно хранить в репозитории Helm, например Реестр контейнеров Azure, и интегрировать их в конвейер сборки.

Дополнительные сведения об использовании Реестра контейнеров Helm см. в статье Использование Реестра контейнеров Azure в качестве репозитория Helm для диаграмм приложения.

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

Например, вот часть ФАЙЛА YAML, который определяет развертывание:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "package.fullname" . | replace "." "" }}
  labels:
    app.kubernetes.io/name: {{ include "package.name" . }}
    app.kubernetes.io/instance: {{ .Release.Name }}
  annotations:
    kubernetes.io/change-cause: {{ .Values.reason }}

...

  spec:
      containers:
      - name: &package-container_name fabrikam-package
        image: {{ .Values.dockerregistry }}/{{ .Values.image.repository }}:{{ .Values.image.tag }}
        imagePullPolicy: {{ .Values.image.pullPolicy }}
        env:
        - name: LOG_LEVEL
          value: {{ .Values.log.level }}

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

helm install $HELM_CHARTS/package/ \
     --set image.tag=0.1.0 \
     --set image.repository=package \
     --set dockerregistry=$ACR_SERVER \
     --namespace backend \
     --name package-v0.1.0

Хотя конвейер CI/CD может установить диаграмму непосредственно в Kubernetes, рекомендуется создать архив диаграммы (Tgz-файл) и отправить диаграмму в репозиторий Helm, например Реестр контейнеров Azure. Дополнительные сведения см. в разделе "Приложения на основе Пакета Docker" в диаграммах Helm в Azure Pipelines.

Редакции

Диаграммы Helm всегда имеют номер версии, который должен использовать семантическое управление версиями. Диаграмма также может иметь appVersion. Это поле является необязательным и не должно быть связано с версией диаграммы. Некоторые команды могут потребоваться использовать версии приложений отдельно от обновлений диаграмм. Но проще использовать один номер версии, поэтому между версией диаграммы и версией приложения существует отношение 1:1. Таким образом, вы можете хранить одну диаграмму на выпуск и легко развертывать нужный выпуск:

helm install <package-chart-name> --version <desiredVersion>

Еще одна рекомендация заключается в предоставлении заметки об изменении в шаблоне развертывания:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "delivery.fullname" . | replace "." "" }}
  labels:
     ...
  annotations:
    kubernetes.io/change-cause: {{ .Values.reason }}

Это позволяет просматривать поле причины изменений для каждой редакции kubectl rollout history с помощью команды. В предыдущем примере причина изменений предоставляется в качестве параметра диаграммы Helm.

kubectl rollout history deployments/delivery-v010 -n backend
deployment.extensions/delivery-v010
REVISION  CHANGE-CAUSE
1         Initial deployment

Вы также можете использовать helm list команду для просмотра журнала редакций:

helm list
NAME            REVISION    UPDATED                     STATUS        CHART            APP VERSION     NAMESPACE
delivery-v0.1.0 1           Sun Apr  7 00:25:30 2020    DEPLOYED      delivery-v0.1.0  v0.1.0          backend

Конвейер Azure DevOps

В Azure Pipelines конвейеры делятся на конвейеры сборки и конвейеры выпуска. Конвейер сборки запускает процесс CI и создает артефакты сборки. Для архитектуры микрослужб в Kubernetes эти артефакты представляют собой образы контейнеров и диаграммы Helm, определяющие каждую микрослужбу. Конвейер выпуска запускает этот процесс CD, который развертывает микрослужбу в кластере.

На основе потока CI, описанного ранее в этой статье, конвейер сборки может состоять из следующих задач:

  1. Создайте контейнер тестового средства выполнения.

    - task: Docker@1
      inputs:
        azureSubscriptionEndpoint: $(AzureSubscription)
        azureContainerRegistry: $(AzureContainerRegistry)
        arguments: '--pull --target testrunner'
        dockerFile: $(System.DefaultWorkingDirectory)/$(dockerFileName)
        imageName: '$(imageName)-test'
    
  2. Запустите тесты, вызвав docker run в контейнере тестового средства выполнения.

    - task: Docker@1
      inputs:
        azureSubscriptionEndpoint: $(AzureSubscription)
        azureContainerRegistry: $(AzureContainerRegistry)
        command: 'run'
        containerName: testrunner
        volumes: '$(System.DefaultWorkingDirectory)/TestResults:/app/tests/TestResults'
        imageName: '$(imageName)-test'
        runInBackground: false
    
  3. Опубликуйте результаты теста. См. статью "Создание образа".

    - task: PublishTestResults@2
      inputs:
        testResultsFormat: 'VSTest'
        testResultsFiles: 'TestResults/*.trx'
        searchFolder: '$(System.DefaultWorkingDirectory)'
        publishRunAttachments: true
    
  4. Создайте контейнер среды выполнения.

    - task: Docker@1
      inputs:
        azureSubscriptionEndpoint: $(AzureSubscription)
        azureContainerRegistry: $(AzureContainerRegistry)
        dockerFile: $(System.DefaultWorkingDirectory)/$(dockerFileName)
        includeLatestTag: false
        imageName: '$(imageName)'
    
  5. Отправьте образ контейнера в Реестр контейнеров Azure (или другой реестр контейнеров).

    - task: Docker@1
      inputs:
        azureSubscriptionEndpoint: $(AzureSubscription)
        azureContainerRegistry: $(AzureContainerRegistry)
        command: 'Push an image'
        imageName: '$(imageName)'
        includeSourceTags: false
    
  6. Упаковка диаграммы Helm.

    - task: HelmDeploy@0
      inputs:
        command: package
        chartPath: $(chartPath)
        chartVersion: $(Build.SourceBranchName)
        arguments: '--app-version $(Build.SourceBranchName)'
    
  7. Отправьте пакет Helm в Реестр контейнеров Azure (или другой репозиторий Helm).

    task: AzureCLI@1
      inputs:
        azureSubscription: $(AzureSubscription)
        scriptLocation: inlineScript
        inlineScript: |
        az acr helm push $(System.ArtifactsDirectory)/$(repositoryName)-$(Build.SourceBranchName).tgz --name $(AzureContainerRegistry);
    

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

  • Разверните диаграмму Helm в средах разработки/QA/промежуточной среды. Команду Helm upgrade можно использовать с флагом --install для поддержки первой установки и последующих обновлений.
  • Дождитесь утверждения или отклонения развертывания утверждающего.
  • Повторная метка образа контейнера для выпуска
  • Отправьте тег выпуска в реестр контейнеров.
  • Разверните диаграмму Helm в рабочем кластере.

Дополнительные сведения о создании конвейера выпуска см. в разделе "Конвейеры выпуска", "Черновики выпусков" и "Варианты выпуска".

На следующей схеме показан сквозной процесс CI/CD, описанный в этой статье:

CD/CD pipeline

Соавторы

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

Автор субъекта:

  • Джон Пул | Старший архитектор облачных решений

Чтобы просмотреть недоступные профили LinkedIn, войдите в LinkedIn.

Следующие шаги