Trabalhos de implementação
Serviços de DevOps do Azure | Azure DevOps Server 2022 | Azure DevOps Server 2020
Importante
- Os nomes de cargos e estágios não podem conter palavras-chave (exemplo:
deployment
). - Cada trabalho em um estágio deve ter um nome exclusivo.
Nos pipelines do YAML, recomendamos que coloque os passos de implementação num tipo especial de trabalho chamado trabalho de implementação. Um trabalho de implementação é uma coleção de passos executados sequencialmente no ambiente. Um trabalho de implantação e um trabalho tradicional podem existir no mesmo estágio. O Azure DevOps dá suporte às estratégias runOnce, rolling e canary.
Os trabalhos de implementação apresentam os seguintes benefícios:
- Histórico de implementações: obtém o histórico de implementações através dos pipelines, até um recurso específico e o estado das implementações para auditoria.
- Aplicar estratégia de implementação: define como a aplicação é desenvolvida.
Um trabalho de implementação não clona automaticamente o repositório de origem. Você pode fazer checkout do repositório de origem em seu trabalho com checkout: self
o .
Nota
Este artigo se concentra na implantação com trabalhos de implantação. Para saber como implantar no Azure com pipelines, consulte Visão geral de Implantar no Azure.
Esquema
Aqui está a sintaxe completa para especificar um trabalho de implantação:
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 ]
Há uma sintaxe alternativa mais detalhada que você também pode usar para a environment
propriedade.
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.
Para máquinas virtuais, não é necessário definir um pool. Todas as etapas definidas em um trabalho de implantação com um recurso de máquina virtual serão executadas nessa máquina virtual e não no agente no pool. Para outros tipos de recursos, como o Kubernetes, você precisa definir um pool para que as tarefas possam ser executadas nessa máquina.
Estratégias de implementação
Ao implantar atualizações de aplicativos, é importante que a técnica usada para entregar a atualização seja:
- Habilite a inicialização.
- Implante a atualização.
- Encaminhe o tráfego para a versão atualizada.
- Teste a versão atualizada após rotear o tráfego.
- Em caso de falha, execute as etapas para restaurar para a última versão válida.
Conseguimos isso usando ganchos de ciclo de vida que podem executar etapas durante a implantação. Cada um dos ganchos do ciclo de vida é resolvido em um trabalho de agente ou um trabalho de servidor (ou um contêiner ou trabalho de validação no futuro), dependendo do pool
atributo. Por padrão, os ganchos de ciclo de vida herdarão o pool
deployment
especificado pelo trabalho.
Os trabalhos de implantação usam a $(Pipeline.Workspace)
variável de sistema.
Descrições de ganchos de ciclo de vida
preDeploy
: Usado para executar etapas que inicializam recursos antes do início da implantação do aplicativo.
deploy
: Usado para executar etapas que implantam seu aplicativo. A tarefa de download do artefato será injetada automaticamente somente no gancho para trabalhos de deploy
implantação. Para interromper o download de artefatos, use - download: none
ou escolha artefatos específicos para download especificando a tarefa Baixar Artefato de Pipeline.
routeTraffic
: Usado para executar etapas que servem o tráfego para a versão atualizada.
postRouteTraffic
: Usado para executar as etapas depois que o tráfego é roteado. Normalmente, essas tarefas monitoram a integridade da versão atualizada para um intervalo definido.
on: failure
ou on: success
: Usado para executar etapas para ações de reversão ou limpeza.
Estratégia de implantação do RunOnce
runOnce
é a estratégia de implantação mais simples em que todos os ganchos do ciclo de vida, ou seja preDeploy
deploy
, , routeTraffic
e postRouteTraffic
, são executados uma vez. Em seguida, ou on:
success
on:
failure
é executado.
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:
...
Se você estiver usando agentes auto-hospedados, poderá usar as opções de limpeza do espaço de trabalho para limpar o espaço de trabalho de implantação.
jobs:
- deployment: MyDeploy
pool:
vmImage: 'ubuntu-latest'
workspace:
clean: all
environment: staging
Estratégia de implementação contínua
Uma implantação sem interrupção substitui instâncias da versão anterior de um aplicativo por instâncias da nova versão do aplicativo em um conjunto fixo de máquinas virtuais (conjunto contínuo) em cada iteração.
Atualmente, oferecemos suporte apenas à estratégia contínua para recursos de VM.
Por exemplo, uma implantação sem interrupção normalmente aguarda a conclusão das implantações em cada conjunto de máquinas virtuais antes de prosseguir para o próximo conjunto de implantações. Você pode fazer uma verificação de integridade após cada iteração e, se ocorrer um problema significativo, a implantação contínua pode ser interrompida.
As implantações contínuas podem ser configuradas especificando a palavra-chave rolling:
sob o strategy:
nó.
A strategy.name
variável está disponível neste bloco de estratégia, que leva o nome da estratégia. Neste caso, rolando.
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:
...
Todos os ganchos de ciclo de vida são suportados e os trabalhos de gancho de ciclo de vida são criados para serem executados em cada VM.
preDeploy
, deploy
, routeTraffic
, e são executados uma vez por tamanho de lote postRouteTraffic
definido por maxParallel
.
Em seguida, ou on: success
on: failure
é executado.
Com maxParallel: <# or % of VMs>
o , você pode controlar o número/porcentagem de destinos de máquina virtual para implantar em paralelo. Isso garante que o aplicativo esteja sendo executado nessas máquinas e seja capaz de lidar com solicitações enquanto a implantação está ocorrendo no restante das máquinas, o que reduz o tempo de inatividade geral.
Nota
Existem algumas lacunas conhecidas neste recurso. Por exemplo, quando você tenta novamente um estágio, ele executa novamente a implantação em todas as VMs, não apenas em destinos com falha.
Estratégia de implementação canário
A estratégia de implantação Canary é uma estratégia de implantação avançada que ajuda a reduzir o risco envolvido na implantação de novas versões de aplicativos. Usando essa estratégia, você pode distribuir as alterações para um pequeno subconjunto de servidores primeiro. À medida que você ganha mais confiança na nova versão, pode liberá-la para mais servidores em sua infraestrutura e rotear mais tráfego para ela.
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:
...
A estratégia de implantação Canary suporta o gancho de preDeploy
ciclo de vida (executado uma vez) e itera com os ganchos , deploy
routeTraffic
e postRouteTraffic
ciclo de vida. Em seguida, ele sai com o success
gancho ou failure
gancho.
As seguintes variáveis estão disponíveis nesta estratégia:
strategy.name
: Nome da estratégia. Por exemplo, canário.
strategy.action
: A ação a ser executada no cluster Kubernetes. Por exemplo, implantar, promover ou rejeitar.
strategy.increment
: O valor de incremento usado na interação atual. Esta variável está disponível apenas em deploy
, routeTraffic
e postRouteTraffic
ganchos de ciclo de vida.
Exemplos
Estratégia de implantação do RunOnce
O trecho YAML de exemplo a seguir mostra um uso simples de um trabalho de implantação usando a runOnce
estratégia de implantação. O exemplo inclui uma etapa de checkout.
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
Com cada execução desse trabalho, o smarthotel-dev
histórico de implantação é registrado no ambiente.
Nota
- Também é possível criar um ambiente com recursos vazios e usá-lo como um shell abstrato para registrar o histórico de implantação, como mostrado no exemplo anterior.
O próximo exemplo demonstra como um pipeline pode referir um ambiente e um recurso a serem usados como destino para um trabalho de implantação.
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)
Esta abordagem tem os seguintes benefícios:
- Registra o histórico de implantação em um recurso específico dentro do ambiente, em vez de registrar o histórico em todos os recursos dentro do ambiente.
- As etapas no trabalho de implantação herdam automaticamente os detalhes de conexão do recurso (neste caso, um namespace Kubernetes,
smarthotel-dev.bookings
), porque o trabalho de implantação está vinculado ao ambiente. Isso é útil nos casos em que o mesmo detalhe de conexão é definido para várias etapas do trabalho.
Nota
Se estiver a utilizar um cluster AKS privado, certifique-se de que está ligado à rede virtual do cluster, uma vez que o ponto de extremidade do servidor API não está exposto através de um endereço IP público.
O Azure Pipelines recomenda configurar um agente auto-hospedado em uma VNET que tenha acesso à rede virtual do cluster. Consulte Opções para conexão com o cluster privado para obter detalhes.
Estratégia de implementação contínua
A estratégia contínua para VMs atualiza até cinco destinos em cada iteração. maxParallel
determinará o número de alvos que podem ser implantados em paralelo. A seleção leva em conta o número absoluto ou a porcentagem de metas que devem permanecer disponíveis a qualquer momento, excluindo as metas para as quais estão sendo implantadas. Ele também é usado para determinar as condições de sucesso e falha durante a implantação.
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
Estratégia de implementação canário
No próximo exemplo, a estratégia canária para AKS implantará primeiro as mudanças com 10% de pods, seguido por 20%, enquanto monitora a saúde durante postRouteTraffic
o . Se tudo correr bem, vai subir a 100 por cento.
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...
Use decoradores de tubulação para injetar etapas automaticamente
Os decoradores de pipeline podem ser usados em trabalhos de implantação para injetar automaticamente qualquer etapa personalizada (por exemplo, scanner de vulnerabilidade) em cada execução de gancho de ciclo de vida de cada trabalho de implantação. Como os decoradores de pipeline podem ser aplicados a todos os pipelines em uma organização, isso pode ser aplicado como parte da aplicação de práticas de implantação seguras.
Além disso, os trabalhos de implantação podem ser executados como um trabalho de contêiner junto com o side-car de serviços, se definido.
Suporte para variáveis de saída
Defina variáveis de saída nos ganchos de ciclo de vida de um trabalho de implantação e consuma-as em outras etapas e trabalhos downstream dentro do mesmo estágio.
Para compartilhar variáveis entre estágios, produza um artefato em um estágio e consuma-o em um estágio subsequente ou use a stageDependencies
sintaxe descrita em variáveis.
Ao executar estratégias de implantação, você pode acessar variáveis de saída entre trabalhos usando a sintaxe a seguir.
- Para a estratégia runOnce :
$[dependencies.<job-name>.outputs['<job-name>.<step-name>.<variable-name>']]
(por exemplo,$[dependencies.JobA.outputs['JobA.StepA.VariableA']]
) - Para a estratégia runOnce mais um resourceType:
$[dependencies.<job-name>.outputs['Deploy_<resource-name>.<step-name>.<variable-name>']]
. (por exemplo,$[dependencies.JobA.outputs['Deploy_VM1.StepA.VariableA']]
) - Para a estratégia canária :
$[dependencies.<job-name>.outputs['<lifecycle-hookname>_<increment-value>.<step-name>.<variable-name>']]
- Para a estratégia evolutiva :
$[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
Para um runOnce
trabalho, especifique o nome do trabalho em vez do gancho do ciclo de vida:
# 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
Quando você define um ambiente em um trabalho de implantação, a sintaxe da variável de saída varia dependendo de como o ambiente é definido. Neste exemplo, env1
usa notação abreviada e env2
inclui a sintaxe completa com um tipo de recurso definido.
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
Quando você produz uma variável de um trabalho no estágio um, fazer referência a ela a partir de um trabalho de implantação no próximo estágio usa sintaxe diferente, dependendo se você deseja definir uma variável ou usá-la como condição para o estágio.
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)
Quando você produz uma variável de um trabalho de implantação, use a sintaxe stageDependencies para fazer referência a ela a partir do próximo estágio (por exemplo, $[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)
Saiba mais sobre como definir uma variável de saída multitarefa
FAQ
Meu pipeline está preso com a mensagem "Job is pending...". Como posso corrigir isso?
Isso pode acontecer quando há um conflito de nome entre dois trabalhos. Verifique se todos os trabalhos de implantação no mesmo estágio têm um nome exclusivo e se os nomes de trabalho e estágio não contêm palavras-chave. Se a renomeação não corrigir o problema, revise as execuções de pipeline de solução de problemas.
Os decoradores são apoiados em grupos de implantação?
N.º Não é possível usar decoradores em grupos de implantação.