Udostępnij za pośrednictwem


Zadania dotyczące wdrażania

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

Ważne

  • Nazwy zadań i etapów nie mogą zawierać słów kluczowych (na przykład: deployment).
  • Każde zadanie na etapie musi mieć unikatową nazwę.

W przypadku potoków YAML zaleca się umieszczenie kroków wdrożenia w specjalnym typie zadania o nazwie zadanie wdrażania. Zadanie wdrożeniowe to zbiór kroków, które są uruchamiane sekwencyjnie w stosunku do środowiska. Zadanie wdrożenia i tradycyjne zadanie mogą istnieć na tym samym etapie. Usługa Azure DevOps obsługuje strategie runOnce, stopniowe i kanaryjne.

Zadania wdrożenia zapewniają następujące korzyści:

  • Historia wdrożenia: uzyskujesz historię wdrożenia we wszystkich potokach, dla określonych zasobów i stanów wdrożeń na potrzeby inspekcji.
  • Stosowanie strategii wdrożenia: definiujesz sposób wdrażania aplikacji.

Zadanie wdrożenia nie klonuje automatycznie repozytorium źródłowego. Możesz wyewidencjonować repozytorium źródłowe w ramach zadania za pomocą polecenia checkout: self.

Uwaga

Ten artykuł koncentruje się na wdrażaniu za pomocą zadań wdrożeniowych. Aby dowiedzieć się, jak wdrażać na platformie Azure za pomocą potoków, zobacz Wdrażanie na platformie Azure — omówienie.

Schemat

Przejdź do schematu YAML, aby wyświetlić definicje jobs.deployment i jobs.deployment.environment .

W przypadku maszyn wirtualnych nie trzeba definiować puli. Wszystkie kroki zdefiniowane w zadaniu wdrożenia z zasobem maszyny wirtualnej są uruchamiane względem tej maszyny wirtualnej, a nie względem agenta w puli. W przypadku innych typów zasobów, takich jak Kubernetes, należy zdefiniować pulę, aby zadania mogły być uruchamiane na tym komputerze.

Strategie wdrażania

Podczas wdrażania aktualizacji aplikacji ważne jest, aby technika używana do dostarczania aktualizacji:

  • Włącz inicjowanie.
  • Wdróż aktualizację.
  • Przekieruj ruch do zaktualizowanej wersji.
  • Przetestuj zaktualizowaną wersję po przekierowaniu ruchu.
  • W przypadku awarii uruchom kroki przywracania do ostatniej znanej dobrej wersji.

Osiągamy to za pomocą punktów zaczepienia cyklu życia, które mogą uruchamiać kroki podczas wdrażania. Każdy z hooków cyklu życia jest rozpoznawany jako zadanie agenta lub zadanie serwera, w zależności od atrybutu pool, lub, w przyszłości, zadanie kontenera lub weryfikacyjne. Domyślnie haki cyklu życia dziedziczą pool określony przez deployment zadanie.

Zadania wdrażania używają zmiennej $(Pipeline.Workspace) systemowej.

Opisy hooków cyklu życia

preDeploy: służy do uruchamiania kroków inicjowania zasobów przed rozpoczęciem wdrażania aplikacji.

deploy: służy do uruchamiania kroków wdrażania aplikacji. Zadanie pobierania artefaktu jest automatycznie wstrzykiwane tylko w punkt wywołania deploy dla zadań związanych z wdrażaniem. Aby zatrzymać pobieranie artefaktów, użyj - download: none lub wybierz określone artefakty do pobrania, określając zadanie Pobierz artefakt potoku.

routeTraffic: służy do uruchamiania kroków kierujących ruch do zaktualizowanej wersji.

postRouteTraffic: służy do uruchamiania kroków po przekierowaniu ruchu. Zazwyczaj te zadania monitorują kondycję zaktualizowanej wersji dla zdefiniowanego interwału.

on: failure lub on: success: służy do wykonywania kroków w celu operacji wycofywania lub czyszczenia.

Strategia wdrażania RunOnce

runOnce to najprostsza strategia wdrażania, w której wszystkie haki cyklu życia, mianowicie preDeploydeploy, routeTraffic, i postRouteTraffic, są wykonywane raz. Następnie wykonywane jest on:success lub 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:
          ...

Jeśli używasz agentów hostowanych lokalnie, możesz użyć opcji czyszczenia przestrzeni roboczej, aby wyczyścić przestrzeń roboczą wdrożenia.

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

Strategia wdrażania stopniowego

Wdrożenie stopniowe zastępuje wystąpienia poprzedniej wersji aplikacji wystąpieniami nowej wersji aplikacji w stałym zestawie maszyn wirtualnych (zestaw kroczący) w każdej iteracji.

Obecnie obsługujemy tylko strategię stopniowej dla zasobów maszyny wirtualnej.

Na przykład wdrożenie stopniowe zwykle czeka na zakończenie wdrożeń na każdym zestawie maszyn wirtualnych przed przejściem do kolejnego zestawu. Możesz przeprowadzić kontrolę kondycji po każdej iteracji i jeśli wystąpi istotny problem, wdrożenie stopniowe można zatrzymać.

Wdrożenia stopniowe można skonfigurować, określając słowo kluczowe rolling: w węźle strategy: . Zmienna strategy.name jest dostępna w tym bloku strategii, który przyjmuje nazwę strategii. W tym przypadku stopniowe.

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:
        ...

Wszystkie haki cyklu życia są obsługiwane, a zadania haków cyklu życia są tworzone z przeznaczeniem do uruchamiania na każdej maszynie wirtualnej.

preDeploy, , deployrouteTraffici postRouteTraffic są wykonywane raz na rozmiar partii zdefiniowany przez maxParallel. Następnie wykonywane jest on: success lub on: failure.

Za pomocą programu maxParallel: <# or % of VMs>można kontrolować liczbę/procent miejsc docelowych maszyn wirtualnych, aby wdrożyć je równolegle. Dzięki temu aplikacja jest uruchomiona na tych maszynach i może obsługiwać żądania, gdy wdrożenie odbywa się na pozostałych maszynach, co zmniejsza całkowity przestój.

Uwaga

Istnieje kilka znanych luk w tej funkcji. Na przykład ponowne próby etapu powodują, że wdrożenie jest ponownie uruchamiane na wszystkich maszynach wirtualnych, a nie tylko na tych, na których wystąpiły błędy.

Strategia kanarkowa wdrożenia

Strategia wdrażania Kanary jest zaawansowaną strategią wdrażania, która pomaga ograniczyć ryzyko związane z wdrażaniem nowych wersji aplikacji. Korzystając z tej strategii, można najpierw wdrożyć zmiany w małym podzestawie serwerów. Gdy zyskujesz większą pewność co do nowej wersji, możesz wprowadzić ją na więcej serwerów w infrastrukturze i kierować do niej więcej ruchu.

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:
          ...

Strategia wdrażania kanaryjnego obsługuje hak cyklu życia preDeploy (wykonywany raz) i iteruje przy użyciu haków cyklu życia deploy, routeTraffic i postRouteTraffic. Następnie zostaje zakończony przy użyciu haka success lub failure.

W tej strategii są dostępne następujące zmienne:

strategy.name: nazwa strategii. Na przykład kanary.
strategy.action: Akcja, którą należy wykonać w klastrze Kubernetes. Na przykład wdróż, promuj lub odrzuć.
strategy.increment: wartość przyrostowa używana w bieżącej interakcji. Ta zmienna jest dostępna tylko w hakach cyklu życia deploy, routeTraffic i postRouteTraffic.

Przykłady

Strategia wdrażania RunOnce

Poniższy przykładowy fragment kodu YAML przedstawia proste użycie zadania wdrażania przy użyciu runOnce strategii wdrażania. Przykład zawiera krok finalizacji zakupu.


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

W przypadku każdego uruchomienia tego zadania historia wdrożenia jest rejestrowana w środowisku smarthotel-dev.

Uwaga

  • Istnieje również możliwość utworzenia środowiska z pustymi zasobami i użycia go jako abstrakcyjnej powłoki do rejestrowania historii wdrożenia, jak pokazano w poprzednim przykładzie.

W następnym przykładzie pokazano, jak potok może odwoływać się zarówno do środowiska, jak i zasobu, który ma być używany jako cel zadania wdrożenia.

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)

Ta metoda ma następujące zalety:

  • Rejestruje historię wdrażania dla określonego zasobu w środowisku, w przeciwieństwie do rejestrowania historii na wszystkich zasobach w środowisku.
  • Kroki w zadaniu wdrożeniowym dziedziczą automatycznie szczegóły połączeń zasobów (w tym przypadku przestrzeni nazw Kubernetes), smarthotel-dev.bookingsponieważ zadanie wdrożeniowe jest połączone ze środowiskiem. Jest to przydatne w przypadkach, w których ten sam szczegół połączenia jest ustawiany dla wielu kroków zadania.

Uwaga

Jeśli używasz prywatnego klastra usługi AKS, upewnij się, że masz połączenie z siecią wirtualną klastra, ponieważ punkt końcowy serwera interfejsu API nie jest uwidoczniony za pośrednictwem publicznego adresu IP.

Usługa Azure Pipelines zaleca skonfigurowanie własnego agenta w sieci wirtualnej, która ma dostęp do sieci wirtualnej klastra. Aby uzyskać szczegółowe informacje, zobacz Opcje nawiązywania połączenia z klastrem prywatnym.

Strategia wdrażania stopniowego

Strategia stopniowej aktualizacji maszyn wirtualnych aktualizuje maksymalnie pięć obiektów docelowych w każdej iteracji. maxParallel określa liczbę obiektów docelowych, które można wdrożyć równolegle. Wybór odpowiada bezwzględnej liczbie lub procentowi miejsc docelowych, które muszą pozostać dostępne w dowolnym momencie z wyłączeniem miejsc docelowych, do których są wdrażane. Służy również do określania warunków powodzenia i niepowodzenia podczas wdrażania.

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

Strategia wdrażania kanarkowego

W następnym przykładzie strategia kanarka dla usługi AKS najpierw wdroży zmiany z 10-procentowymi podami, a następnie z 20-procentowymi podami, monitorując kondycję podczas postRouteTraffic. Jeśli wszystko pójdzie dobrze, osiągnie 100 procent.

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... 

Użyj dekoratorów potoków do automatycznego wstrzykiwania kroków

Dekoratory potoków mogą być używane w zadaniach wdrażania do automatycznego dodawania dowolnego niestandardowego kroku (na przykład skanera luk w zabezpieczeniach) do każdej operacji każdego haka cyklu życia w każdym zadaniu wdrażania. Ponieważ dekoratory potoków można stosować do wszystkich potoków w organizacji, można je stosować w celu egzekwowania bezpiecznych praktyk wdrożeniowych.

Ponadto zadania wdrażania mogą być uruchamiane jako zadanie kontenera wraz z usługami side-car, jeśli zostały zdefiniowane.

Obsługa zmiennych wyjściowych

Zdefiniuj zmienne wyjściowe w hakach cyklu życia zadania wdrożenia i używaj ich w innych zadaniach i krokach podrzędnych w ramach tego samego etapu.

Aby udostępnić zmienne między etapami, wyprowadź artefakt w jednym etapie, a następnie użyj go w kolejnym etapie lub użyj składni opisanej stageDependencies w zmiennych.

Podczas wykonywania strategii wdrażania można uzyskać dostęp do zmiennych wyjściowych między zadaniami przy użyciu następującej składni.

  • W przypadku strategii runOnce : $[dependencies.<job-name>.outputs['<job-name>.<step-name>.<variable-name>']] (na przykład $[dependencies.JobA.outputs['JobA.StepA.VariableA']])
  • Dla strategii runOnce oraz typu zasobu: $[dependencies.<job-name>.outputs['Deploy_<resource-name>.<step-name>.<variable-name>']]. (na przykład $[dependencies.JobA.outputs['Deploy_VM1.StepA.VariableA']])
  • Strategia kanarowa : $[dependencies.<job-name>.outputs['<lifecycle-hookname>_<increment-value>.<step-name>.<variable-name>']]
  • W przypadku strategii stopniowej : $[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 W przypadku zadania określ nazwę zadania zamiast odnośnika do cyklu życia:

# 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

Podczas definiowania środowiska w zadaniu wdrażania składnia zmiennej wyjściowej różni się w zależności od sposobu definiowania środowiska. W tym przykładzie env1 użyto notacji skróconej i env2 zawiera pełną składnię ze zdefiniowanym typem zasobu.

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
      resourceName: vmsfortesting
      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.myOutputVarTwo'] ]
      myOutputVarTwo: $[ dependencies.A2.outputs['Deploy_vmsfortesting.setvarStepTwo.myOutputVarTwo'] ]
    
    steps:
    - script: "echo $(myOutputVarTwo)"
      name: echovartwo

W przypadku wyprowadzania zmiennej z zadania w etapie drugim, odwoływanie się do niej z zadania wdrożenia na następnym etapie używa innej składni w zależności od tego, czy chcesz ustawić zmienną lub użyć jej jako warunku dla etapu.

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)

Podczas wyprowadzania zmiennej z zadania wdrażania użyj składni stageDependencies, aby odwoływać się do niej z następnego etapu (na przykład $[stageDependencies.<stage-name>.<job-name>.outputs[Deploy_<resource-name>.<step-name>.<variable-name>]]).

stages:
- stage: StageA
  jobs:
    - deployment: A1
      environment: 
        name:  env1
        resourceName: DevEnvironmentV
        resourceType: virtualMachine
      strategy:
        runOnce:
          deploy:
            steps:
              - script: echo "##vso[task.setvariable variable=myVar;isOutput=true]true"
                name: setvarStep
              - script: |
                  echo "Value of myVar in the same Job : $(setVarStep.myVar)"
                displayName: 'Verify variable in StageA'
- stage: StageB
  dependsOn: StageA

  # Full Variables syntax for inter-stage jobs
  variables:
    myOutputVar: $[stageDependencies.StageA.A1.outputs['Deploy_DevEnvironmentV.setvarStep.myVar']]
  jobs:
  - deployment: B1
    pool:
      vmImage: 'ubuntu-latest'
    environment: envB
    strategy:                  
      runOnce:
        deploy:
          steps:
          - bash: echo $(myOutputVar)

Dowiedz się więcej na temat ustawiania zmiennej wyjściowej z wieloma zadaniami

Często zadawane pytania

Mój pipeline jest zablokowany z komunikatem "Zadanie jest oczekujące...". Jak rozwiązać ten problem?

Może się to zdarzyć, gdy występuje konflikt nazw między dwoma zadaniami. Sprawdź, czy wszystkie zadania wdrażania na tym samym etapie mają unikatową nazwę, a nazwy zadań i etapów nie zawierają słów kluczowych. Jeśli zmiana nazwy nie rozwiąże problemu, zapoznaj się z tematem Rozwiązywanie problemów z przebiegami potoku.

Czy dekoratory są obsługiwane w grupach wdrożeń?

Nr Nie można stosować dekoratorów w grupach wdrożeniowych.