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 preDeploy
deploy
, 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
, , deploy
routeTraffic
i 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.bookings
ponieważ 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.