Задания развертывания

Azure DevOps Services | Azure DevOps Server 2022 г. | Azure DevOps Server 2020 г.

Важно!

  • Имена заданий и стадий не могут содержать ключевые слова (например, deployment).
  • Каждое задание на этапе должно иметь уникальное имя.

В конвейерах YAML рекомендуется поместить шаги развертывания в особый тип задания , называемого заданием развертывания. Задание развертывания — это набор этапов, которые последовательно выполняются в среде. Задание развертывания и традиционное задание могут находиться на одной стадии. Azure DevOps поддерживает стратегии runOnce, rolling и canary .

Задания развертывания обеспечивают следующие преимущества:

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

Задание развертывания не клонирует исходный репозиторий автоматически. Вы можете извлечь исходный репозиторий в задании с помощью checkout: self.

Примечание

В этой статье основное внимание уделяется развертыванию с помощью заданий развертывания. Сведения о развертывании в Azure с помощью конвейеров см. в статье Общие сведения о развертывании в Azure.

схема

Ниже приведен полный синтаксис для указания задания развертывания.

jobs:
- deployment: string   # name of the deployment job, A-Z, a-z, 0-9, and underscore. The word "deploy" is a keyword and is unsupported as the deployment name.
  displayName: string  # friendly name to display in the UI
  pool:                # not required for virtual machine resources
    name: string       # Use only global level variables for defining a pool name. Stage/job level variables are not supported to define pool name.
    demands: string | [ string ]
  workspace:
    clean: outputs | resources | all # what to clean up before the job runs
  dependsOn: string
  condition: string
  continueOnError: boolean                # 'true' if future jobs should run even if this job fails; defaults to 'false'
  container: containerReference # container to run this job inside
  services: { string: string | container } # container resources to run as a service container
  timeoutInMinutes: nonEmptyString        # how long to run the job before automatically cancelling
  cancelTimeoutInMinutes: nonEmptyString  # how much time to give 'run always even if cancelled tasks' before killing them
  variables: # several syntaxes, see specific section
  environment: string  # target environment name and optionally a resource name to record the deployment history; format: <environment-name>.<resource-name>
  strategy:
    runOnce:    #rolling, canary are the other strategies that are supported
      deploy:
        steps: [ script | bash | pwsh | powershell | checkout | task | templateReference ]

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

environment:
    name: string # Name of environment.
    resourceName: string # Name of resource.
    resourceId: string # Id of resource.
    resourceType: string # Type of environment resource.
    tags: string # List of tag filters.

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

Стратегии развертывания

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

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

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

Задания развертывания используют системную $(Pipeline.Workspace) переменную.

Описание перехватчиков жизненного цикла

preDeploy: используется для выполнения шагов, которые инициализируют ресурсы перед началом развертывания приложения.

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

routeTraffic: используется для выполнения шагов, которые обслуживают трафик к обновленной версии.

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

on: failure или on: success: используется для выполнения шагов для действий отката или очистки.

Стратегия развертывания RunOnce

runOnce — это самая простая стратегия развертывания, в которой все обработчики жизненного цикла, а именно preDeploydeploy, routeTrafficи postRouteTraffic, выполняются один раз. После этого выполняется on:success или on:failure.

strategy: 
    runOnce:
      preDeploy:        
        pool: [ server | pool ] # See pool schema.        
        steps:
        - script: [ script | bash | pwsh | powershell | checkout | task | templateReference ]
      deploy:          
        pool: [ server | pool ] # See pool schema.        
        steps:
        ...
      routeTraffic:         
        pool: [ server | pool ]         
        steps:
        ...        
      postRouteTraffic:          
        pool: [ server | pool ]        
        steps:
        ...
      on:
        failure:         
          pool: [ server | pool ]           
          steps:
          ...
        success:          
          pool: [ server | pool ]           
          steps:
          ...

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

  jobs:
  - deployment: MyDeploy
    pool:
      vmImage: 'ubuntu-latest'
    workspace:
      clean: all
    environment: staging

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

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

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

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

Последовательное развертывание можно настроить, указав ключевое слово rolling: в strategy: узле. Переменная strategy.name доступна в этом блоке стратегии, который принимает имя стратегии. В этом случае — прокатка.

strategy:
  rolling:
    maxParallel: [ number or percentage as x% ]
    preDeploy:        
      steps:
      - script: [ script | bash | pwsh | powershell | checkout | task | templateReference ]
    deploy:          
      steps:
      ...
    routeTraffic:         
      steps:
      ...        
    postRouteTraffic:          
      steps:
      ...
    on:
      failure:         
        steps:
        ...
      success:          
        steps:
        ...

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

preDeploy, deploy, routeTrafficи postRouteTraffic выполняются один раз для каждого размера пакета, определенного параметром maxParallel. После этого выполняется on: success или on: failure.

С помощью maxParallel: <# or % of VMs>можно управлять количеством и процентом целевых объектов виртуальных машин, в которые развертываются параллельно. Это гарантирует, что приложение выполняется на этих компьютерах и может обрабатывать запросы во время развертывания на остальных компьютерах, что сокращает общее время простоя.

Примечание

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

Стратегия канареечного развертывания

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

strategy: 
    canary:
      increments: [ number ]
      preDeploy:        
        pool: [ server | pool ] # See pool schema.        
        steps:
        - script: [ script | bash | pwsh | powershell | checkout | task | templateReference ]
      deploy:          
        pool: [ server | pool ] # See pool schema.        
        steps:
        ...
      routeTraffic:         
        pool: [ server | pool ]         
        steps:
        ...        
      postRouteTraffic:          
        pool: [ server | pool ]        
        steps:
        ...
      on:
        failure:         
          pool: [ server | pool ]           
          steps:
          ...
        success:          
          pool: [ server | pool ]           
          steps:
          ...

Стратегия развертывания canary поддерживает preDeploy перехватчик жизненного цикла (выполняется один раз) и выполняет итерацию с deployобработчиками жизненного цикла , routeTrafficи postRouteTraffic . Затем он выходит с помощью крючка success или failure .

В этой стратегии доступны следующие переменные:

strategy.name: имя стратегии. Например, канаре.
strategy.action: действие, выполняемое в кластере Kubernetes. Например, развертывание, повышение уровня или отклонение.
strategy.increment: значение приращения, используемое в текущем взаимодействии. Эта переменная доступна только в deployобработчиках жизненного цикла , routeTrafficи postRouteTraffic .

Примеры

Стратегия развертывания RunOnce

В следующем примере фрагмента YAML демонстрируется простое использование задания развертывания с помощью runOnce стратегии развертывания. Пример включает шаг оформления заказа.


jobs:
  # Track deployments on the environment.
- deployment: DeployWeb
  displayName: deploy Web App
  pool:
    vmImage: 'ubuntu-latest'
  # Creates an environment if it doesn't exist.
  environment: 'smarthotel-dev'
  strategy:
    # Default deployment strategy, more coming...
    runOnce:
      deploy:
        steps:
        - checkout: self 
        - script: echo my first deployment

При каждом выполнении этого задания журнал развертывания записывается в smarthotel-dev среду.

Примечание

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

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

jobs:
- deployment: DeployWeb
  displayName: deploy Web App
  pool:
    vmImage: 'ubuntu-latest'
  # Records deployment against bookings resource - Kubernetes namespace.
  environment: 'smarthotel-dev.bookings'
  strategy: 
    runOnce:
      deploy:
        steps:
          # No need to explicitly pass the connection details.
        - task: KubernetesManifest@0
          displayName: Deploy to Kubernetes cluster
          inputs:
            action: deploy
            namespace: $(k8sNamespace)
            manifests: |
              $(System.ArtifactsDirectory)/manifests/*
            imagePullSecrets: |
              $(imagePullSecret)
            containers: |
              $(containerRegistry)/$(imageRepository):$(tag)

Этот подход имеет следующие преимущества:

  • Записывает журнал развертывания для определенного ресурса в среде, а не для всех ресурсов в среде.
  • Шаги в задании развертывания автоматически наследуют сведения о подключении ресурса (в данном случае это пространство имен Kubernetes, smarthotel-dev.bookings), так как задание развертывания связано со средой. Это полезно в случаях, когда для нескольких шагов задания заданы одинаковые сведения о подключении.

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

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

jobs: 
- deployment: VMDeploy
  displayName: web
  environment:
    name: smarthotel-dev
    resourceType: VirtualMachine
  strategy:
    rolling:
      maxParallel: 5  #for percentages, mention as x%
      preDeploy:
        steps:
        - download: current
          artifact: drop
        - script: echo initialize, cleanup, backup, install certs
      deploy:
        steps:
        - task: IISWebAppDeploymentOnMachineGroup@0
          displayName: 'Deploy application to Website'
          inputs:
            WebSiteName: 'Default Web Site'
            Package: '$(Pipeline.Workspace)/drop/**/*.zip'
      routeTraffic:
        steps:
        - script: echo routing traffic
      postRouteTraffic:
        steps:
        - script: echo health check post-route traffic
      on:
        failure:
          steps:
          - script: echo Restore from backup! This is on failure
        success:
          steps:
          - script: echo Notify! This is on success

Стратегия канареечного развертывания

В следующем примере стратегия canary для AKS сначала развертывает изменения с 10-процентными модулями pod, а затем 20 процентами, при этом отслеживая работоспособность во время postRouteTraffic. Если все пойдет хорошо, это будет способствовать 100 процентов.

jobs: 
- deployment: 
  environment: smarthotel-dev.bookings
  pool: 
    name: smarthotel-devPool
  strategy:                  
    canary:      
      increments: [10,20]  
      preDeploy:                                     
        steps:           
        - script: initialize, cleanup....   
      deploy:             
        steps: 
        - script: echo deploy updates... 
        - task: KubernetesManifest@0 
          inputs: 
            action: $(strategy.action)       
            namespace: 'default' 
            strategy: $(strategy.name) 
            percentage: $(strategy.increment) 
            manifests: 'manifest.yml' 
      postRouteTraffic: 
        pool: server 
        steps:           
        - script: echo monitor application health...   
      on: 
        failure: 
          steps: 
          - script: echo clean-up, rollback...   
        success: 
          steps: 
          - script: echo checks passed, notify... 

Автоматическое внедрение шагов с помощью декораторов конвейера

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

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

Поддержка выходных переменных

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

Чтобы совместно использовать переменные между этапами, выведите артефакт на одном этапе, а затем используйте его на следующем этапе или используйте синтаксис, описанный stageDependencies в разделе переменные.

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

  • Для стратегии runOnce : $[dependencies.<job-name>.outputs['<job-name>.<step-name>.<variable-name>']] (например, $[dependencies.JobA.outputs['Deploy.StepA.VariableA']])
  • Для стратегии runOnce плюс resourceType: $[dependencies.<job-name>.outputs['<job-name>_<resource-name>.<step-name>.<variable-name>']]. (например, $[dependencies.JobA.outputs['Deploy_VM1.StepA.VariableA']])
  • Для канареечного стратегии: $[dependencies.<job-name>.outputs['<lifecycle-hookname>_<increment-value>.<step-name>.<variable-name>']]
  • Для последовательной стратегии: $[dependencies.<job-name>.outputs['<lifecycle-hookname>_<resource-name>.<step-name>.<variable-name>']]
# Set an output variable in a lifecycle hook of a deployment job executing canary strategy.
- deployment: A
  pool:
    vmImage: 'ubuntu-latest'
  environment: staging
  strategy:                  
    canary:      
      increments: [10,20]  # Creates multiple jobs, one for each increment. Output variable can be referenced with this.
      deploy:
        steps:
        - bash: echo "##vso[task.setvariable variable=myOutputVar;isOutput=true]this is the deployment variable value"
          name: setvarStep
        - bash: echo $(setvarStep.myOutputVar)
          name: echovar

# Map the variable from the job.
- job: B
  dependsOn: A
  pool:
    vmImage: 'ubuntu-latest'
  variables:
    myVarFromDeploymentJob: $[ dependencies.A.outputs['deploy_10.setvarStep.myOutputVar'] ]
  steps:
  - script: "echo $(myVarFromDeploymentJob)"
    name: echovar

runOnce Для задания укажите имя задания вместо перехватчика жизненного цикла:

# Set an output variable in a lifecycle hook of a deployment job executing runOnce strategy.
- deployment: A
  pool:
    vmImage: 'ubuntu-latest'
  environment: staging
  strategy:                  
    runOnce:
      deploy:
        steps:
        - bash: echo "##vso[task.setvariable variable=myOutputVar;isOutput=true]this is the deployment variable value"
          name: setvarStep
        - bash: echo $(setvarStep.myOutputVar)
          name: echovar

# Map the variable from the job.
- job: B
  dependsOn: A
  pool:
    vmImage: 'ubuntu-latest'
  variables:
    myVarFromDeploymentJob: $[ dependencies.A.outputs['A.setvarStep.myOutputVar'] ]
  steps:
  - script: "echo $(myVarFromDeploymentJob)"
    name: echovar

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

stages:
- stage: StageA
  jobs:
  - deployment: A1
    pool:
      vmImage: 'ubuntu-latest'
    environment: env1
    strategy:                  
      runOnce:
        deploy:
          steps:
          - bash: echo "##vso[task.setvariable variable=myOutputVar;isOutput=true]this is the deployment variable value"
            name: setvarStep
          - bash: echo $(System.JobName)
  - deployment: A2
    pool:
      vmImage: 'ubuntu-latest'
    environment: 
      name: env2
      resourceType: virtualmachine
    strategy:                  
      runOnce:
        deploy:
          steps:
          - script: echo "##vso[task.setvariable variable=myOutputVarTwo;isOutput=true]this is the second deployment variable value"
            name: setvarStepTwo
  
  - job: B1
    dependsOn: A1
    pool:
      vmImage: 'ubuntu-latest'
    variables:
      myVarFromDeploymentJob: $[ dependencies.A1.outputs['A1.setvarStep.myOutputVar'] ]
      
    steps:
    - script: "echo $(myVarFromDeploymentJob)"
      name: echovar
 
  - job: B2
    dependsOn: A2
    pool:
      vmImage: 'ubuntu-latest'
    variables:
      myVarFromDeploymentJob: $[ dependencies.A2.outputs['A2.setvarStepTwo.myOutputVar'] ]
      myOutputVarTwo: $[ dependencies.A2.outputs['Deploy_vmsfortesting.setvarStepTwo.myOutputVarTwo'] ]
    
    steps:
    - script: "echo $(myOutputVarTwo)"
      name: echovartwo

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

stages:
- stage: StageA
  jobs:
  - job: A1
    steps:
      - pwsh: echo "##vso[task.setvariable variable=RunStageB;isOutput=true]true"
        name: setvarStep
      - bash: echo $(System.JobName)

- stage: StageB
  dependsOn: 
    - StageA
 
  # when referring to another stage, stage name is included in variable path
  condition: eq(dependencies.StageA.outputs['A1.setvarStep.RunStageB'], 'true')
  
  # Variables reference syntax differs slightly from inter-stage condition syntax
  variables:
    myOutputVar: $[stageDependencies.StageA.A1.outputs['setvarStep.RunStageB']]
  jobs:
  - deployment: B1
    pool:
      vmImage: 'ubuntu-latest'
    environment: envB
    strategy:                  
      runOnce:
        deploy:
          steps:
          - bash: echo $(myOutputVar)

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

Вопросы и ответы

Мой конвейер завис с сообщением "Задание ожидается...". Как это исправить?

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

Поддерживаются ли декораторы в группах развертывания?

Нет. Декораторы нельзя использовать в группах развертывания.