Distributionsjobb

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

Viktigt!

  • Jobb- och stegnamn får inte innehålla nyckelord (exempel: deployment).
  • Varje jobb i en fas måste ha ett unikt namn.

I YAML-pipelines rekommenderar vi att du anger distributionsstegen i en särskild typ av jobb som kallas för ett distributionsjobb. Ett distributionsjobb är en samling steg som körs sekventiellt mot miljön. Ett distributionsjobb och ett traditionellt jobb kan finnas i samma fas. Azure DevOps stöder runOnce, rullande och kanariestrategier .

Distributionsjobb ger följande fördelar:

  • Distributionshistorik: Du får distributionshistoriken över pipelines, ned till en specifik resurs och status för distributionerna för granskning.
  • Tillämpa distributionsstrategi: Du definierar hur programmet distribueras.

Ett distributionsjobb klonar inte källdatabasen automatiskt. Du kan checka ut källdatabasen i jobbet med checkout: self.

Kommentar

Den här artikeln fokuserar på distribution med distributionsjobb. Information om hur du distribuerar till Azure med pipelines finns i Distribuera till Azure-översikt.

Schema

Här är den fullständiga syntaxen för att ange ett distributionsjobb:

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 ]

Det finns en mer detaljerad, alternativ syntax som du också kan använda för egenskapen 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.

För virtuella datorer behöver du inte definiera en pool. Alla steg som du definierar i ett distributionsjobb med en virtuell datorresurs körs mot den virtuella datorn och inte mot agenten i poolen. För andra resurstyper, till exempel Kubernetes, måste du definiera en pool så att aktiviteter kan köras på den datorn.

Distributionsstrategier

När du distribuerar programuppdateringar är det viktigt att den teknik du använder för att leverera uppdateringen kommer att:

  • Aktivera initiering.
  • Distribuera uppdateringen.
  • Dirigera trafik till den uppdaterade versionen.
  • Testa den uppdaterade versionen efter routning av trafik.
  • I händelse av fel kör du steg för att återställa till den senast kända versionen.

Vi uppnår detta genom att använda livscykelkrokar som kan köra steg under distributionen. Var och en av livscykeln kopplas till ett agentjobb eller ett serverjobb (eller en container eller ett valideringsjobb i framtiden), beroende på pool attributet. Som standard ärver livscykelkrokerna den pool som angetts av deployment jobbet.

Distributionsjobb använder $(Pipeline.Workspace) systemvariabeln.

Beskrivningar av livscykelkrokar

preDeploy: Används för att köra steg som initierar resurser innan programdistributionen startar.

deploy: Används för att köra steg som distribuerar ditt program. Ladda ned artefaktaktivitet matas bara in automatiskt i kroken deploy för distributionsjobb. Om du vill sluta ladda ned artefakter använder - download: none eller väljer du specifika artefakter att ladda ned genom att ange ladda ned pipelineartefaktaktivitet.

routeTraffic: Används för att köra steg som hanterar trafiken till den uppdaterade versionen.

postRouteTraffic: Används för att köra stegen när trafiken dirigeras. Normalt övervakar dessa uppgifter hälsotillståndet för den uppdaterade versionen för definierat intervall.

on: failure eller on: success: Används för att köra steg för återställningsåtgärder eller rensning.

RunOnce-distributionsstrategi

runOnce är den enklaste distributionsstrategin där alla livscykelkrokar, nämligen preDeploydeploy, routeTrafficoch postRouteTraffic, körs en gång. Sedan körs antingen on:success eller 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:
          ...

Om du använder lokalt installerade agenter kan du använda alternativen för att rensa arbetsytan på arbetsytan för att rensa distributionsarbetsytan.

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

Strategi för rullande distribution

En löpande distribution ersätter instanser av den tidigare versionen av ett program med instanser av den nya versionen av programmet på en fast uppsättning virtuella datorer (rullande uppsättning) i varje iteration.

För närvarande stöder vi bara den löpande strategin för VM-resurser.

En rullande distribution väntar till exempel vanligtvis på att distributionerna på varje uppsättning virtuella datorer ska slutföras innan du fortsätter till nästa uppsättning distributioner. Du kan göra en hälsokontroll efter varje iteration och om ett betydande problem uppstår kan den löpande distributionen stoppas.

Rullande distributioner kan konfigureras genom att ange nyckelordet rolling: under strategy: noden. Variabeln strategy.name är tillgänglig i det här strategiblocket, som tar namnet på strategin. I det här fallet rullande.

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

Alla livscykelkrokar stöds och livscykelkrokjobb skapas för att köras på varje virtuell dator.

preDeploy, deploy, routeTraffic, och postRouteTraffic körs en gång per batchstorlek som definieras av maxParallel. Sedan körs antingen on: success eller on: failure .

Med maxParallel: <# or % of VMs>kan du styra antalet/procentandelen virtuella datormål som ska distribueras parallellt. Detta säkerställer att appen körs på dessa datorer och kan hantera begäranden medan distributionen sker på resten av datorerna, vilket minskar den totala stilleståndstiden.

Kommentar

Det finns några kända luckor i den här funktionen. När du till exempel försöker utföra en fas igen körs distributionen på alla virtuella datorer, inte bara misslyckade mål.

Strategi för canary-distribution

Strategi för canary-distribution är en avancerad distributionsstrategi som hjälper till att minska risken med att lansera nya versioner av program. Med den här strategin kan du distribuera ändringarna till en liten delmängd av servrarna först. När du får mer förtroende för den nya versionen kan du släppa den till fler servrar i infrastrukturen och dirigera mer trafik till den.

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

Strategin för canary-distribution stöder preDeploy livscykelkroken (körs en gång) och itererar med deployrouteTraffic, och postRouteTraffic livscykelkrokar. Den avslutas sedan med antingen eller failure krokensuccess.

Följande variabler är tillgängliga i den här strategin:

strategy.name: Namnet på strategin. Till exempel kanariefågel.
strategy.action: Den åtgärd som ska utföras på Kubernetes-klustret. Du kan till exempel distribuera, höja upp eller avvisa.
strategy.increment: Det inkrementsvärde som används i den aktuella interaktionen. Den här variabeln är endast tillgänglig i deploy, routeTrafficoch postRouteTraffic livscykelkrokar.

Exempel

RunOnce-distributionsstrategi

I följande exempel visar YAML-kodavsnittet en enkel användning av ett distributionsjobb med hjälp av distributionsstrategin runOnce . Exemplet innehåller ett utcheckningssteg.


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

För varje körning av det här jobbet registreras distributionshistoriken smarthotel-dev mot miljön.

Kommentar

  • Det går också att skapa en miljö med tomma resurser och använda den som ett abstrakt gränssnitt för att registrera distributionshistorik, som du ser i föregående exempel.

Nästa exempel visar hur en pipeline kan referera till både en miljö och en resurs som ska användas som mål för ett distributionsjobb.

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)

Den här metoden har följande fördelar:

  • Registrerar distributionshistorik för en specifik resurs i miljön, i stället för att registrera historiken för alla resurser i miljön.
  • Steg i distributionsjobbet ärver automatiskt anslutningsinformationen för resursen (i det här fallet ett Kubernetes-namnområde, smarthotel-dev.bookings), eftersom distributionsjobbet är länkat till miljön. Detta är användbart i de fall där samma anslutningsinformation har angetts för flera steg i jobbet.

Strategi för rullande distribution

Den löpande strategin för virtuella datorer uppdaterar upp till fem mål i varje iteration. maxParallel avgör antalet mål som kan distribueras till, parallellt. Valet står för absolut antal eller procentandel av mål som måste vara tillgängliga när som helst, exklusive de mål som distribueras till. Den används också för att fastställa villkoren för lyckade och misslyckade distributioner.

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

Strategi för canary-distribution

I nästa exempel distribuerar kanariestrategin för AKS först ändringarna med 10 procent poddar, följt av 20 procent, samtidigt som hälsotillståndet övervakas under postRouteTraffic. Om allt går bra kommer det att höjas till 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... 

Använd pipelinedekoratörer för att mata in steg automatiskt

Pipelinedekoratörer kan användas i distributionsjobb för att automatiskt mata in alla anpassade steg (till exempel sårbarhetsskanner) till varje livscykelkrokkörning för varje distributionsjobb. Eftersom pipelinedekoratörer kan tillämpas på alla pipelines i en organisation kan detta användas som en del av att tillämpa säkra distributionsmetoder.

Dessutom kan distributionsjobb köras som ett containerjobb tillsammans med tjänster på sidovagnen om det definieras.

Stöd för utdatavariabler

Definiera utdatavariabler i ett distributionsjobbs livscykelkrokar och använd dem i andra underordnade steg och jobb inom samma fas.

Om du vill dela variabler mellan faser matar du ut en artefakt i ett steg och använder den sedan i en efterföljande fas, eller använder syntaxen stageDependencies som beskrivs i variabler.

När du kör distributionsstrategier kan du komma åt utdatavariabler mellan jobb med hjälp av följande syntax.

  • För runOnce-strategi : $[dependencies.<job-name>.outputs['<job-name>.<step-name>.<variable-name>']] (till exempel $[dependencies.JobA.outputs['JobA.StepA.VariableA']])
  • För runOnce-strategi plus en resourceType: $[dependencies.<job-name>.outputs['<job-name>_<resource-name>.<step-name>.<variable-name>']]. (till exempel $[dependencies.JobA.outputs['Deploy_VM1.StepA.VariableA']])
  • För kanariestrategi : $[dependencies.<job-name>.outputs['<lifecycle-hookname>_<increment-value>.<step-name>.<variable-name>']]
  • För löpande strategi: $[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

För ett runOnce jobb anger du namnet på jobbet i stället för livscykelkroken:

# 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

När du definierar en miljö i ett distributionsjobb varierar syntaxen för utdatavariabeln beroende på hur miljön definieras. I det här exemplet env1 använder du kortfattad notation och env2 innehåller den fullständiga syntaxen med en definierad resurstyp.

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

När du matar ut en variabel från ett distributionsjobb använder refererande från nästa jobb olika syntax beroende på om du vill ange en variabel eller använda den som ett villkor för fasen.

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)

Läs mer om hur du anger en utdatavariabel för flera jobb

Vanliga frågor

Min pipeline har fastnat med meddelandet "Jobbet väntar...". Hur kan jag åtgärda detta?

Detta kan inträffa när det finns en namnkonflikt mellan två jobb. Kontrollera att alla distributionsjobb i samma fas har ett unikt namn och att jobb- och stegnamnen inte innehåller nyckelord. Om du inte löser problemet genom att byta namn läser du felsökning av pipelinekörningar.

Stöds dekoratörer i distributionsgrupper?

Nej. Du kan inte använda dekoratörer i distributionsgrupper.