Share via


Implementatietaken

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

Belangrijk

  • Taak- en fasenamen mogen geen trefwoorden bevatten (bijvoorbeeld: deployment).
  • Elke taak in een fase moet een unieke naam hebben.

In YAML-pijplijnen kunt u uw implementatiestappen beter in een speciaal type taak plaatsen, een zogenaamde implementatietaak. Een implementatietaak is een verzameling stappen die opeenvolgend worden uitgevoerd op basis van de omgeving. Een implementatietaak en een traditionele taak kunnen zich in dezelfde fase bevinden. Azure DevOps ondersteunt de runOnce-, rolling- en canary-strategieën .

Implementatietaken bieden de volgende voordelen:

  • Implementatiegeschiedenis: u krijgt de implementatiegeschiedenis voor meerdere pijplijnen, tot een specifieke resource en status van de implementaties voor controle.
  • Implementatiestrategie toepassen: u definieert hoe uw toepassing wordt geïmplementeerd.

Met een implementatietaak wordt de bronopslagplaats niet automatisch gekloond. U kunt de bronopslagplaats in uw taak uitchecken met checkout: self.

Notitie

Dit artikel is gericht op implementatie met implementatietaken. Zie Het overzicht implementeren in Azure voor meer informatie over het implementeren in Azure met pijplijnen.

Schema

Hier volgt de volledige syntaxis om een implementatietaak op te geven:

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 ]

Er is een gedetailleerdere, alternatieve syntaxis die u ook voor de environment eigenschap kunt gebruiken.

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.

Voor virtuele machines hoeft u geen pool te definiëren. Alle stappen die u in een implementatietaak met een virtuele-machineresource definieert, worden uitgevoerd op die virtuele machine en niet op de agent in de pool. Voor andere resourcetypen, zoals Kubernetes, moet u een pool definiëren, zodat taken op die computer kunnen worden uitgevoerd.

Implementatiestrategieën

Wanneer u toepassingsupdates implementeert, is het belangrijk dat de techniek die u gebruikt om de update te leveren:

  • Initialisatie inschakelen.
  • Implementeer de update.
  • Routeer verkeer naar de bijgewerkte versie.
  • Test de bijgewerkte versie na het routeren van verkeer.
  • In het geval van een fout voert u stappen uit om te herstellen naar de laatst bekende goede versie.

We bereiken dit door levenscyclushooks te gebruiken die stappen kunnen uitvoeren tijdens de implementatie. Elk van de levenscyclushook wordt omgezet in een agenttaak of een servertaak (of een container- of validatietaak in de toekomst), afhankelijk van het pool kenmerk. De levenscyclushook neemt standaard de pool opgegeven door de deployment taak over.

Implementatietaken maken gebruik van de $(Pipeline.Workspace) systeemvariabele.

Beschrijvingen van levenscyclushook

preDeploy: Wordt gebruikt om stappen uit te voeren waarmee resources worden geïnitialiseerd voordat de implementatie van de toepassing wordt gestart.

deploy: Wordt gebruikt om stappen uit te voeren waarmee uw toepassing wordt geïmplementeerd. Downloadartefacttaak wordt alleen automatisch geïnjecteerd in de deploy hook voor implementatietaken. Als u wilt stoppen met het downloaden van artefacten, gebruikt - download: none of kiest u specifieke artefacten die u wilt downloaden door de taak Pijplijnartefact downloaden op te geven.

routeTraffic: Wordt gebruikt om stappen uit te voeren die het verkeer naar de bijgewerkte versie leveren.

postRouteTraffic: Wordt gebruikt om de stappen uit te voeren nadat het verkeer is gerouteerd. Normaal gesproken bewaken deze taken de status van de bijgewerkte versie voor een gedefinieerd interval.

on: failure of on: success: wordt gebruikt om stappen uit te voeren voor terugdraaiacties of opschonen.

Implementatiestrategie voor RunOnce

runOnce is de eenvoudigste implementatiestrategie waarbij alle levenscyclushook, namelijk preDeploy deploy, routeTrafficen postRouteTraffic, eenmaal worden uitgevoerd. Daarna wordt on: success of on: failure uitgevoerd.

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

Als u zelf-hostende agents gebruikt, kunt u de opties voor het opschonen van de werkruimte gebruiken om uw implementatiewerkruimte op te schonen.

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

Doorlopende implementatiestrategie

Een rolling implementatie vervangt exemplaren van de vorige versie van een toepassing door exemplaren van de nieuwe versie van de toepassing op een vaste set virtuele machines (rolling set) in elke iteratie.

Momenteel ondersteunen we alleen de rolling-strategie voor VM-resources.

Een rolling implementatie wacht bijvoorbeeld meestal op implementaties op elke set virtuele machines die moeten worden voltooid voordat u verdergaat met de volgende set implementaties. U kunt een statuscontrole uitvoeren na elke iteratie en als er een belangrijk probleem optreedt, kan de rolling implementatie worden gestopt.

Rolling implementaties kunnen worden geconfigureerd door het trefwoord rolling: onder het strategy: knooppunt op te geven. De strategy.name variabele is beschikbaar in dit strategieblok, waarbij de naam van de strategie wordt gebruikt. In dit geval rollend.

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

Alle levenscyclushook wordt ondersteund en er worden levenscyclushooktaken gemaakt om op elke VIRTUELE machine te worden uitgevoerd.

preDeploy, deploy, routeTrafficen postRouteTraffic worden eenmaal per batchgrootte uitgevoerd die is gedefinieerd door maxParallel. Vervolgens wordt een on: success of on: failure meer uitgevoerd.

Met maxParallel: <# or % of VMs>kunt u het aantal/het percentage virtuele-machinedoelen beheren waarop deze parallel moet worden geïmplementeerd. Dit zorgt ervoor dat de app wordt uitgevoerd op deze machines en kan aanvragen verwerken terwijl de implementatie plaatsvindt op de rest van de machines, waardoor de algehele downtime wordt verminderd.

Notitie

Er zijn enkele bekende hiaten in deze functie. Wanneer u bijvoorbeeld een fase opnieuw probeert, wordt de implementatie opnieuw uitgevoerd op alle VM's, niet alleen mislukte doelen.

Canary-implementatiestrategie

Canary-implementatiestrategie is een geavanceerde implementatiestrategie waarmee het risico wordt beperkt dat gepaard gaat met het implementeren van nieuwe versies van toepassingen. Met deze strategie kunt u de wijzigingen eerst implementeren in een kleine subset van servers. Naarmate u meer vertrouwen krijgt in de nieuwe versie, kunt u deze vrijgeven aan meer servers in uw infrastructuur en meer verkeer naar de versie routeren.

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-implementatiestrategie ondersteunt de preDeploy levenscyclushook (eenmaal uitgevoerd) en herhaalt met de deploy, routeTrafficen postRouteTraffic levenscyclushaken. Vervolgens wordt het afgesloten met de success of failure haak.

De volgende variabelen zijn beschikbaar in deze strategie:

strategy.name: Naam van de strategie. Bijvoorbeeld kanarie.
strategy.action: De actie die moet worden uitgevoerd op het Kubernetes-cluster. Bijvoorbeeld implementeren, promoveren of weigeren.
strategy.increment: De incrementele waarde die wordt gebruikt in de huidige interactie. Deze variabele is alleen beschikbaar in deploy, routeTrafficen postRouteTraffic levenscyclushook.

Voorbeelden

Implementatiestrategie voor RunOnce

In het volgende voorbeeld toont het YAML-fragment een eenvoudig gebruik van een implementatietaak met behulp van de runOnce implementatiestrategie. Het voorbeeld bevat een betaalstap.


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

Bij elke uitvoering van deze taak wordt de implementatiegeschiedenis vastgelegd op basis van de smarthotel-dev omgeving.

Notitie

  • Het is ook mogelijk om een omgeving met lege resources te maken en deze te gebruiken als een abstracte shell om de implementatiegeschiedenis vast te leggen, zoals wordt weergegeven in het vorige voorbeeld.

In het volgende voorbeeld ziet u hoe een pijplijn kan verwijzen naar zowel een omgeving als een resource die moet worden gebruikt als het doel voor een implementatietaak.

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)

Deze benadering heeft de volgende voordelen:

  • Registreert de implementatiegeschiedenis van een specifieke resource binnen de omgeving, in plaats van de geschiedenis op alle resources in de omgeving op te nemen.
  • Stappen in de implementatietaak nemen automatisch de verbindingsgegevens van de resource over (in dit geval een Kubernetes-naamruimte), smarthotel-dev.bookingsomdat de implementatietaak is gekoppeld aan de omgeving. Dit is handig in de gevallen waarin dezelfde verbindingsgegevens zijn ingesteld voor meerdere stappen van de taak.

Notitie

Als u een privé-AKS-cluster gebruikt, moet u ervoor zorgen dat u bent verbonden met het virtuele netwerk van het cluster, omdat het EINDPUNT van de API-server niet beschikbaar is via een openbaar IP-adres.

Azure Pipelines raadt u aan een zelf-hostende agent in te stellen binnen een VNET dat toegang heeft tot het virtuele netwerk van het cluster. Zie Opties voor het maken van verbinding met het privécluster voor meer informatie.

Doorlopende implementatiestrategie

De rolling-strategie voor VM's werkt in elke iteratie maximaal vijf doelen bij. maxParallel bepaalt het aantal doelen waarop de implementatie parallel kan worden uitgevoerd. Bij de selectie wordt rekening gehouden met een absoluut aantal of percentage doelen dat op elk gewenst moment beschikbaar moet blijven, met uitzondering van de doelen waarop wordt geïmplementeerd. De selectie wordt ook gebruikt om de voorwaarden voor een geslaagde of mislukte implementatie te bepalen.

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

In het volgende voorbeeld implementeert de canary-strategie voor AKS eerst de wijzigingen met 10 procent pods, gevolgd door 20 procent, tijdens het bewaken van de status tijdens postRouteTraffic. Als alles goed gaat, zal het promoveren tot 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... 

Pijplijn decorators gebruiken om stappen automatisch te injecteren

Pijplijn-decorators kunnen worden gebruikt in implementatietaken om elke aangepaste stap (bijvoorbeeld scanner voor beveiligingsproblemen) automatisch in te voeren voor elke levenscyclushookuitvoering van elke implementatietaak. Omdat pijplijn-decorators kunnen worden toegepast op alle pijplijnen in een organisatie, kan dit worden toegepast als onderdeel van het afdwingen van veilige implementatieprocedures.

Daarnaast kunnen implementatietaken worden uitgevoerd als een containertaak , samen met services side-car , indien gedefinieerd.

Ondersteuning voor uitvoervariabelen

Definieer uitvoervariabelen in de levenscyclushook van een implementatietaak en verbruik deze in andere downstreamstappen en taken binnen dezelfde fase.

Als u variabelen tussen fasen wilt delen, voert u een artefact in één fase uit en gebruikt u het in een volgende fase of gebruikt u de stageDependencies syntaxis die in variabelen wordt beschreven.

Tijdens het uitvoeren van implementatiestrategieën hebt u toegang tot uitvoervariabelen tussen taken met behulp van de volgende syntaxis.

  • Voor runOnce-strategie : $[dependencies.<job-name>.outputs['<job-name>.<step-name>.<variable-name>']] (bijvoorbeeld $[dependencies.JobA.outputs['JobA.StepA.VariableA']])
  • Voor runOnce-strategie plus een resourceType: $[dependencies.<job-name>.outputs['Deploy_<resource-name>.<step-name>.<variable-name>']]. (bijvoorbeeld, $[dependencies.JobA.outputs['Deploy_VM1.StepA.VariableA']])
  • Voor kanariestrategie : $[dependencies.<job-name>.outputs['<lifecycle-hookname>_<increment-value>.<step-name>.<variable-name>']]
  • Voor rolling strategie: $[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

Geef voor een runOnce taak de naam van de taak op in plaats van de levenscyclushook:

# 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

Wanneer u een omgeving in een implementatietaak definieert, varieert de syntaxis van de uitvoervariabele, afhankelijk van hoe de omgeving wordt gedefinieerd. In dit voorbeeld env1 wordt de korte notatie gebruikt en env2 bevat de volledige syntaxis met een gedefinieerd resourcetype.

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

Wanneer u een variabele uitvoert van een taak in fase één, gebruikt u deze vanuit een implementatietaak in de volgende fase verschillende syntaxis, afhankelijk van of u een variabele wilt instellen of als voorwaarde voor de fase wilt gebruiken.

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)

Wanneer u een variabele uitvoert vanuit een implementatietaak, gebruikt u de syntaxis van stageDependencies om ernaar te verwijzen vanuit de volgende fase (bijvoorbeeld $[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)

Meer informatie over het instellen van een uitvoervariabele voor meerdere taken

Veelgestelde vragen

Mijn pijplijn blijft hangen met het bericht 'Taak is in behandeling...'. Hoe kan ik dit oplossen?

Dit kan gebeuren wanneer er een naamconflict is tussen twee taken. Controleer of alle implementatietaken in dezelfde fase een unieke naam hebben en dat de taak- en fasenamen geen trefwoorden bevatten. Als het probleem niet wordt opgelost door de naam te wijzigen, controleert u de pijplijnuitvoeringen voor probleemoplossing.

Worden decorators ondersteund in implementatiegroepen?

Nee U kunt geen decorators gebruiken in implementatiegroepen.