Руководство. Использование стратегии развертывания канарной версии для Kubernetes

Azure DevOps Services | Azure DevOps Server | Azure DevOps Server 2022

В этом пошаговом наставлении показано, как использовать задачу манифеста Kubernetes с использованием canary стратегии. Стратегия развертывания может развертывать новые версии приложения рядом с стабильными рабочими версиями.

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

В этом руководстве используются подключения службы Docker и Службы Azure Resource Manager для подключения к ресурсам Azure. Для частного кластера Служба Azure Kubernetes (AKS) или кластера с отключенными локальными учетными записями подключение службы Azure Resource Manager лучше всего подходит для подключения.

Необходимые компоненты

Файлы репозитория GitHub

Репозиторий GitHub содержит следующие файлы:

Файл Description
./app/app.py Простой веб-сервер на основе Flask. Файл настраивает счетчик для количества хороших и плохих ответов на основе значения переменной success_rate .
./app/Dockerfile Используется для создания образа с каждым изменением app.py. Каждое изменение активирует конвейер сборки для сборки образа и отправки его в реестр контейнеров.
./manifests/deployment.yml Содержит спецификацию рабочей нагрузки sampleapp развертывания, соответствующей опубликованному образу. Этот файл манифеста используется для стабильной версии объекта развертывания и для получения базовых и канамерных вариантов рабочих нагрузок.
./manifests/service.yml sampleapp Создает службу. Эта служба направляет запросы к модулям pod, созданным на основе стабильных, базовых и канаарных развертываний.
./misc/fortio.yml Настраивает развертывание fortio. Это средство нагрузочного тестирования, которое отправляет поток запросов в развернутую sampleapp службу. Поток запросов направляется в модули pod в рамках трех развертываний: стабильный, базовый и канарной.

Создание подключений к службе

  1. В проекте Azure DevOps перейдите к параметрам проекта>подключениям службы.
  2. Нажмите кнопку "Новое подключение службы".
  3. Создайте подключение службы реестра Docker со следующими параметрами:
    • Имя подключения службы: azure-pipelines-canary-acr
    • Реестр Docker: выбор экземпляра реестра контейнеров Azure
    • Нажмите кнопку "Сохранить", чтобы создать подключение.
  4. Создайте второе подключение службы, снова нажав кнопку "Создать подключение службы ".
  5. Создайте подключение службы Azure Resource Manager со следующими параметрами:
    • Имя подключения службы: azure-pipelines-canary-k8s (или azure-pipelines-canary-sc как используется в конвейере YAML)
    • Уровень области: выбор подписки
    • Подписка Azure. Выбор подписки Azure
    • Группа ресурсов: выбор группы ресурсов
    • Нажмите кнопку "Сохранить", чтобы создать подключение.

Добавление этапа сборки

  1. В проекте Azure DevOps перейдите в раздел >"Создание конвейера" или "Создать конвейер".

  2. Выберите GitHub для своего расположения кода и выберите вилку репозитория azure-pipelines-canary-k8s .

  3. На вкладке "Настройка" выберите конвейер Starter.

  4. На вкладке "Рецензирование" замените YAML конвейера следующим кодом.

    trigger:
    - main
    
    pool:
      vmImage: ubuntu-latest
    
    variables:
      imageName: azure-pipelines-canary-k8s # Docker image name
      dockerRegistryServiceConnection: azure-pipelines-canary-acr # Service connection to ACR
      imageRepository: 'azure-pipelines-canary-k8s' # Image repository name
      containerRegistry: example.azurecr.io # Full container registry URL
      tag: '$(Build.BuildId)' # Tag image with the build ID for versioning
    
    stages:
    - stage: Build
      displayName: Build stage
      jobs:  
      - job: Build
        displayName: Build
        pool:
          vmImage: ubuntu-latest
        steps:
        # Build and push Docker image to Azure Container Registry
        - task: Docker@2
          displayName: Build and push image
          inputs:
            containerRegistry: $(dockerRegistryServiceConnection)
            repository: $(imageName)
            command: buildAndPush
            Dockerfile: app/Dockerfile
            tags: |
              $(tag)
    

    Если созданное соединение службы реестра Docker связано с именем example.azurecr.ioреестра контейнеров, то для образа задано значение example.azurecr.io/azure-pipelines-canary-k8s:$(Build.BuildId).

  5. Выберите "Сохранить и запустить " и убедитесь, что задание выполняется успешно.

Изменение файла манифеста

В вилке репозитория измените манифесты/deployment.yml , чтобы заменить <foobar> URL-адрес реестра контейнеров, например example.azurecr.io/azure-pipelines-canary-k8s.

Настройка непрерывного развертывания

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

Создать среду

Вы можете развернуть с помощью YAML или классической версии.

  1. В проекте Azure DevOps перейдите в Pipelines>Environments.
  2. Выберите "Создать среду " (или кнопку "Создать среду ").
  3. На экране "Создание среды" в поле "Имя" введите akscanary.
  4. В разделе "Ресурс" выберите Kubernetes из раскрывающегося списка.
  5. Нажмите кнопку "Далее ", чтобы перейти к конфигурации ресурсов Kubernetes.
  6. На экране конфигурации ресурсов Kubernetes введите следующие сведения:
    • Поставщик. Выберите службу Azure Kubernetes из раскрывающегося списка.
    • Подписка Azure. Выберите подписку Azure.
    • Кластер. Выберите кластер службы Azure Kubernetes.
    • Пространство имен: выберите "Создать " и введите canarydemo.
  7. Выберите Проверить и создать.

Добавление канарной стадии

  1. Перейдите к конвейерам, выберите созданный конвейер и нажмите кнопку "Изменить".

  2. Замените весь yamL конвейера следующим кодом.

    Этот код изменяет шаг, Docker@2 который вы выполнили ранее, чтобы использовать этап, и добавляет еще два шага для копирования манифестов и неправильных каталогов в качестве артефактов для последовательных этапов использования.

    Код также перемещает некоторые значения в переменные для упрощения использования позже в конвейере. В переменной замените containerRegistry<example> имя реестра контейнеров.

    trigger:
    - main
    
    pool:
      vmImage: ubuntu-latest
    
    variables:
      imageName: azure-pipelines-canary-k8s
      dockerRegistryServiceConnection: azure-pipelines-canary-acr
      imageRepository: 'azure-pipelines-canary-k8s'
      containerRegistry: <example>.azurecr.io # Replace <example> with your registry name
      tag: '$(Build.BuildId)' # Tag image with unique build ID
    
    stages:
    # Stage 1: Build the Docker image and publish manifests
    - stage: Build
      displayName: Build stage
      jobs:  
      - job: Build
        displayName: Build
        pool:
          vmImage: ubuntu-latest
        steps:
        # Build and push Docker image to Azure Container Registry
        - task: Docker@2
          displayName: Build and push image
          inputs:
            containerRegistry: $(dockerRegistryServiceConnection)
            repository: $(imageName)
            command: buildAndPush
            Dockerfile: app/Dockerfile
            tags: |
              $(tag)
    
        # Publish Kubernetes manifests as artifacts for later stages to use
        - publish: manifests
          artifact: manifests
    
        # Publish load testing tool (Fortio) configuration as artifacts
        - publish: misc
          artifact: misc
    
  3. Добавьте еще один этап в конце ФАЙЛА YAML для развертывания канарной версии. Замените значения my-resource-group и my-aks-cluster группу ресурсов и Служба Azure Kubernetes имя кластера.

    trigger:
    - main
    
    pool:
      vmImage: ubuntu-latest
    
    variables:
      imageName: azure-pipelines-canary-k8s
      dockerRegistryServiceConnection: azure-pipelines-canary-acr
      imageRepository: 'azure-pipelines-canary-k8s'
      containerRegistry: yourcontainerregistry.azurecr.io # Update with your container registry
      tag: '$(Build.BuildId)'
    
    stages:
    # Stage 1: Build the Docker image
    - stage: Build
      displayName: Build stage
      jobs:  
      - job: Build
        displayName: Build
        pool:
          vmImage: ubuntu-latest
        steps:
        # Build and push Docker image to Azure Container Registry
        - task: Docker@2
          displayName: Build and push image
          inputs:
            containerRegistry: $(dockerRegistryServiceConnection)
            repository: $(imageName)
            command: buildAndPush
            Dockerfile: app/Dockerfile
            tags: |
              $(tag)
    
        # Publish manifests for deployment stages
        - publish: manifests
          artifact: manifests
    
        # Publish Fortio load testing configuration
        - publish: misc
          artifact: misc
    
    # Stage 2: Deploy canary version alongside stable version
    - stage: DeployCanary
      displayName: Deploy canary
      dependsOn: Build # Wait for Build stage to complete
      condition: succeeded() # Only run if Build stage succeeded
    
      jobs:
      - deployment: Deploycanary
        displayName: Deploy canary
        pool:
          vmImage: ubuntu-latest
        environment: 'akscanary'
        strategy:
          runOnce: # Execute deployment strategy once
            deploy:
              steps:
              - task: KubernetesManifest@1
                displayName: Create Docker Registry Secret
                inputs:
                  action: 'createSecret'
                  connectionType: 'azureResourceManager'
                  azureSubscriptionConnection: 'azure-pipelines-canary-sc' # Service connection to Azure
                  azureResourceGroup: 'my-resource-group' # Replace with your resource group
                  kubernetesCluster: 'my-aks-cluster' # Replace with your AKS cluster name
                  secretType: 'dockerRegistry'
                  secretName: 'my-acr-secret'
                  dockerRegistryEndpoint: 'azure-pipelines-canary-acr'
    
              # Deploy canary version (25% of traffic) alongside stable deployment
              - task: KubernetesManifest@1
                displayName: Deploy to Kubernetes cluster
                inputs:
                  action: 'deploy'
                  connectionType: 'azureResourceManager'
                  azureSubscriptionConnection: 'azure-pipelines-canary-sc'
                  azureResourceGroup: 'my-resource-group'
                  kubernetesCluster: 'my-aks-cluster'
                  strategy: 'canary' # Use canary deployment strategy
                  percentage: '25' # Deploy to 25% of pods initially
                  manifests: |
                    $(Pipeline.Workspace)/manifests/deployment.yml
                    $(Pipeline.Workspace)/manifests/service.yml
                  containers: '$(containerRegistry)/$(imageRepository):$(tag)'
                  imagePullSecrets: 'my-acr-secret'
    
              # Deploy Fortio load testing tool to generate traffic for evaluation
              - task: KubernetesManifest@1
                displayName: Deploy Fortio to Kubernetes cluster
                inputs:
                  action: 'deploy'
                  connectionType: 'azureResourceManager'
                  azureSubscriptionConnection: 'azure-pipelines-canary-sc'
                  azureResourceGroup: 'my-resource-group'
                  kubernetesCluster: 'my-aks-cluster'
                  manifests: '$(Pipeline.Workspace)/misc/*' # Fortio configuration
    
  4. Выберите "Проверить и сохранить" и сохраните конвейер непосредственно в главной ветви.

Добавление утверждения вручную для продвижения или отклонения канарного развертывания

Вы можете вмешаться вручную с YAML или классической версией.

  1. Создайте новую среду Kubernetes с именем akspromote.
  2. Откройте новую среду akspromote из списка сред и выберите "Утверждения" на вкладке "Утверждения и проверки".
  3. На странице Согласования добавьте собственную учетную запись пользователя в разделе Согласующие.
  4. Разверните узел "Дополнительно" и убедитесь, что утверждающие могут утвердить собственные запуски .
  5. Нажмите кнопку создания.

Добавление этапов повышения и отклонения конвейера

  1. Перейдите к конвейерам, выберите созданный конвейер и нажмите кнопку "Изменить".

  2. Добавьте следующий PromoteRejectCanary этап в конце файла YAML, который способствует изменениям.

    # Stage 3: Promote canary deployment to full production (manual approval required)
    - stage: PromoteRejectCanary
      displayName: Promote or Reject canary
      dependsOn: DeployCanary # Wait for canary deployment to complete
      condition: succeeded() # Only run if canary deployment succeeded
    
      jobs:
      - deployment: PromoteCanary
        displayName: Promote Canary
        pool: 
          vmImage: ubuntu-latest
        environment: 'akspromote' # Use akspromote environment with approval gate
        strategy:
          runOnce: # Execute once per deployment
            deploy:
              steps:      
              # Create Docker registry secret for the promotion environment
              - task: KubernetesManifest@1
                displayName: Create Docker Registry Secret for akspromote
                inputs:
                  action: 'createSecret'
                  connectionType: 'azureResourceManager'
                  azureSubscriptionConnection: 'azure-pipelines-canary-sc'
                  azureResourceGroup: 'my-resource-group'
                  kubernetesCluster: 'my-aks-cluster'
                  secretType: 'dockerRegistry'
                  secretName: 'my-acr-secret'
                  dockerRegistryEndpoint: 'azure-pipelines-canary-acr'
    
              # Promote canary deployment to 100% of traffic (full production rollout)
              - task: KubernetesManifest@1
                displayName: promote canary
                inputs:
                  action: 'promote' # Transition from canary to stable
                  connectionType: 'azureResourceManager'
                  azureSubscriptionConnection: 'azure-pipelines-canary-sc'
                  azureResourceGroup: 'my-resource-group'
                  kubernetesCluster: 'my-aks-cluster'
                  strategy: 'canary'
                  manifests: '$(Pipeline.Workspace)/manifests/*'
                  containers: '$(containerRegistry)/$(imageRepository):$(tag)'
                  imagePullSecrets: 'my-acr-secret'
        ```
    
    
  3. Добавьте следующий RejectCanary этап в конце файла, который откатывает изменения.

    # Stage 4: Reject canary deployment and rollback to stable version
    - stage: RejectCanary
      displayName: Reject canary
      dependsOn: PromoteRejectCanary
      condition: failed() # Run this stage if the promotion stage fails or is rejected
    
      jobs:
      - deployment: RejectCanary
        displayName: Reject Canary
        pool: 
          vmImage: ubuntu-latest
        environment: 'akscanary'
        strategy:
          runOnce: # Execute once per deployment
            deploy:
              steps:        
              # Create Docker registry secret for the rejection environment
              - task: KubernetesManifest@1
                displayName: Create Docker Registry Secret for reject canary
                inputs:
                  action: 'createSecret'
                  connectionType: 'azureResourceManager'
                  azureSubscriptionConnection: 'azure-pipelines-canary-sc'
                  azureResourceGroup: 'kubernetes-testing'
                  kubernetesCluster: 'my-aks-cluster'
                  secretType: 'dockerRegistry'
                  secretName: 'my-acr-secret'
                  dockerRegistryEndpoint: 'azure-pipelines-canary-acr'    
    
              # Reject canary deployment and rollback to the stable version
              - task: KubernetesManifest@1
                displayName: Reject canary deployment
                inputs:
                  action: 'reject' # Rollback canary changes
                  connectionType: 'azureResourceManager'
                  azureSubscriptionConnection: 'azure-pipelines-canary-sc'
                  azureResourceGroup: 'my-resource-group'
                  kubernetesCluster: 'my-aks-cluster'
                  namespace: 'default'
                  strategy: 'canary'
                  manifests: '$(Pipeline.Workspace)/manifests/*'
        ```
    
  4. Выберите "Проверить и сохранить" и сохраните конвейер непосредственно в главной ветви.

Развертывание стабильной версии

Для первого запуска конвейера стабильная версия рабочих нагрузок и их базовых или канарной версий не существует в кластере. Разверните стабильную версию рабочей нагрузки sampleapp следующим образом.

Вы можете развернуть стабильную версию с помощью YAML или классической версии.

  1. В приложении/app.py перейдите success_rate = 50 на success_rate = 100. Это изменение активирует конвейер, сборку и отправку образа в реестр контейнеров, а также активирует DeployCanary этап.
  2. Так как вы настроили утверждение в akspromote среде, выпуск ожидается перед выполнением этого этапа. На странице сводки запуска сборки выберите "Проверка " и нажмите кнопку "Утвердить".

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

Инициирование канарского рабочего процесса и отклонение утверждения

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

  1. В приложении/app.py перейдите success_rate = 50 на success_rate = 100. Это изменение активирует конвейер, сборку и отправку образа в реестр контейнеров, а также активирует DeployCanary этап.
  2. Так как вы настроили утверждение в akspromote среде, выпуск ожидается перед выполнением этого этапа.
  3. На странице сводки запуска сборки выберите "Рецензирование ", а затем нажмите кнопку "Отклонить " в следующем диалоговом окне. Это действие отклоняет развертывание.

После отклонения конвейер предотвращает развертывание кода.

Очистка

Если вы не собираетесь продолжать использовать это приложение, удалите группу ресурсов на портале Azure и проект в Azure DevOps.