Deployment jobs
Azure Pipelines
Note
To use deployment jobs, make sure the multi-stage pipelines experience is turned on.
In YAML pipelines, we recommend that you put your deployment steps in a deployment job. A deployment job is a special type of job that's a collection of steps, which are run sequentially against the environment.
Overview
Deployment jobs provide some benefits:
Deployment history: You get end-to-end deployment history across pipelines, down to a specific resource and status of the deployments for auditing.
Apply deployment strategy: You define how your application is rolled out.
Note
At the moment, we offer only the runOnce strategy and the canary strategy. Additional strategies like rolling and blueGreen are on our roadmap.
Schema
Here's the full syntax to specify a deployment job:
jobs:
- deployment: string # name of the deployment job, A-Z, a-z, 0-9, and underscore
displayName: string # friendly name to display in the UI
pool: # see pool schema
name: string
demands: string | [ string ]
dependsOn: string
condition: string
continueOnError: boolean # 'true' if future jobs should run even if this job fails; defaults to 'false'
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: { string: string } | [ variable | variableReference ]
environment: string # target environment name and optionally a resource-name to record the deployment history; format: <environment-name>.<resource-name>
strategy: [ deployment strategy ] # see deployment strategy schema
Deployment strategies
When you're deploying application updates, it's important that the technique you use to deliver the update will:
- Enable initialization.
- Deploy the update.
- Route traffic to the updated version.
- Test the updated version after routing traffic.
- In case of failure, run steps to restore to the last known good version.
We achieve this by using life cycle hooks that can run steps during deployment. Each of the life cycle hooks resolves into an agent job or a server job (or a container or validation job in the future), depending on the pool
attribute. By default, the life cycle hooks will inherit the pool
specified by the deployment
job.
Descriptions of life cycle hooks
preDeploy
: Used to run steps that initialize resources before application deployment starts.
deploy
: Used to run steps that deploy your application.
routeTraffic
: Used to run steps that serve the traffic to the updated version.
postRouteTraffic
: Used to run the steps after the traffic is routed. Typically, these tasks monitor the health of the updated version for defined interval.
on: failure
or on: success
: Used to run steps that perform rollback actions or clean-up.
RunOnce deployment strategy
runOnce
is the simplest deployment strategy wherein all the life cycle hooks, namely preDeploy
deploy
, routeTraffic
, and postRouteTraffic
, are executed once. Then, either on:
success
or on:
failure
is executed.
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:
...
Canary deployment strategy
Canary deployment strategy is an advanced deployment strategy that helps mitigate the risk involved in rolling out new versions of applications. By using this strategy, you can roll out the changes to a small subset of servers first. As you gain more confidence in the new version, you can release it to more servers in your infrastructure and route more traffic to it. Currently, this is applicable to only Kubernetes resources.
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 deployment strategy supports the preDeploy
life cycle hook (executed once) and iterates with the deploy
, routeTraffic
, and postRouteTraffic
life cycle hooks. It then exits with either the success
or failure
hook.
The following variables are available in this strategy:
strategy.name
: Name of the strategy. For example, canary.
strategy.action
: The action to be performed on the Kubernetes cluster. For example, deploy, promote, or reject.
strategy.increment
: The increment value used in the current interaction. This variable is available only in deploy
, routeTraffic
, and postRouteTraffic
life cycle hooks.
Examples
RunOnce deployment strategy
The following example YAML snippet showcases a simple use of a deploy job by using the runOnce
deployment strategy.
jobs:
# track deployments on the environment
- deployment: DeployWeb
displayName: deploy Web App
pool:
vmImage: 'Ubuntu-16.04'
# creates an environment if it doesn't exist
environment: 'smarthotel-dev'
strategy:
# default deployment strategy, more coming...
runOnce:
deploy:
steps:
- script: echo my first deployment
With each run of this job, deployment history is recorded against the smarthotel-dev
environment.
Note
- Currently, environments support only Kubernetes resources, with support for virtual machines and other resources on the roadmap.
- It's also possible to create an environment with empty resources and use that as an abstract shell to record deployment history, as shown in the previous example.
The next example demonstrates how a pipeline can refer both an environment and a resource to be used as the target for a deployment job.
jobs:
- deployment: DeployWeb
displayName: deploy Web App
pool:
vmImage: 'Ubuntu-16.04'
# 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)
This approach has the following benefits:
- Records deployment history on a specific resource within the environment, as opposed to recording the history on all resources within the environment.
- Steps in the deployment job automatically inherit the connection details of the resource (in this case, a Kubernetes namespace,
smarthotel-dev.bookings
), because the deployment job is linked to the environment. This is particularly useful in the cases where the same connection detail is set for multiple steps of the job.
Canary deployment strategy
In the next example, the canary strategy for AKS will first deploy the changes with 10-percent pods, followed by 20 percent, while monitoring the health during postRouteTraffic
. If all goes well, it will promote to 100 percent.
jobs:
- deployment:
environment: musicCarnivalProd
pool:
name: musicCarnivalProdPool
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'
postRouteTaffic:
pool: server
steps:
- script: echo monitor application health...
on:
failure:
steps:
- script: echo clean-up, rollback...
success:
steps:
- script: echo checks passed, notify...
Feedback
Loading feedback...