Trabajos de implementación
Azure Pipelines | Azure DevOps Server 2020
Importante
- Los nombres de trabajos y fases no pueden contener palabras clave (ejemplo:
deployment). - Cada trabajo de una fase debe tener un nombre único.
En las canalizaciones de YAML, se recomienda colocar los pasos de implementación en un tipo especial de trabajo denominado trabajo de implementación. Un trabajo de implementación es una colección de pasos que se ejecutan secuencialmente en el entorno. Un trabajo de implementación y un trabajo tradicional pueden existir en la misma fase.
Los trabajos de implementación proporcionan las siguientes ventajas:
Historial deimplementación: obtiene el historial de implementación entre canalizaciones, hasta un recurso específico y el estado de las implementaciones para la auditoría.
Aplicar estrategia de implementación:defina cómo se va a implementar la aplicación.
Nota
Actualmente solo se admiten las estrategias runOnce,rollingy canary.
Un trabajo de implementación no clona automáticamente el repositorio de origen. Puede extraer el repositorio de origen dentro de su trabajo con checkout: self . Los trabajos de implementación solo admiten un paso de desprotección.
Schema
Esta es la sintaxis completa para especificar un trabajo de implementación:
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 ]
Hay una sintaxis alternativa más detallada que también puede usar para la environment propiedad .
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.
En el caso de las máquinas virtuales, no es necesario definir un grupo. Los pasos que defina en un trabajo de implementación con un recurso de máquina virtual se ejecutarán en esa máquina virtual y no en el agente del grupo. Para otros tipos de recursos, como Kubernetes, es necesario definir un grupo para que las tareas se puedan ejecutar en esa máquina.
Estrategias de implementación
Al implementar actualizaciones de aplicaciones, es importante que la técnica que use para entregar la actualización:
- Habilite la inicialización.
- Implemente la actualización.
- Enruta el tráfico a la versión actualizada.
- Pruebe la versión actualizada después de enrutar el tráfico.
- En caso de error, ejecute los pasos para restaurar a la última versión correcta conocida.
Esto se consigue mediante el uso de enlaces de ciclo de vida que pueden ejecutar pasos durante la implementación. Cada uno de los enlaces de ciclo de vida se resuelve en un trabajo de agente o un trabajo de servidor (o un contenedor o trabajo de validación en el futuro), dependiendo del atributo. De forma predeterminada, los enlaces de ciclo de vida heredarán pool el especificado por el deployment trabajo.
Los trabajos de implementación usan la $(Pipeline.Workspace) variable del sistema.
Descripciones de enlaces de ciclo de vida
preDeploy: se usa para ejecutar pasos que inicializan recursos antes de que se inicie la implementación de la aplicación.
deploy: se usa para ejecutar los pasos que implementan la aplicación. La tarea Descargar artefacto solo se insertará automáticamente en el deploy enlace para los trabajos de implementación. Para detener la descarga de artefactos, use o elija artefactos específicos para descargar mediante la tarea Descargar artefacto - download: none- download: none.
routeTraffic: se usa para ejecutar pasos que atienden el tráfico a la versión actualizada.
postRouteTraffic: se usa para ejecutar los pasos después de enrutar el tráfico. Normalmente, estas tareas supervisan el estado de la versión actualizada para el intervalo definido.
on: failure o on: success : se usa para ejecutar pasos para acciones de reversión o limpieza.
Estrategia de implementación de RunOnce
runOncees la estrategia de implementación más sencilla en la que todos los enlaces de ciclo de vida, es preDeploydeployrouteTraffic decir, , y postRouteTraffic , se ejecutan una vez. A continuación, on:success se ejecuta o 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:
...
Si usa agentes auto hospedados, puede usar las opciones de limpieza del área de trabajo para limpiar el área de trabajo de implementación.
jobs:
- deployment: deploy
pool:
vmImage: 'ubuntu-latest'
workspace:
clean: all
environment: staging
Estrategia de implementación gradual
Una implementación gradual reemplaza las instancias de la versión anterior de una aplicación por instancias de la nueva versión de la aplicación en un conjunto fijo de máquinas virtuales (conjunto gradual) en cada iteración.
Actualmente solo se admite la estrategia gradual en los recursos de máquina virtual.
Por ejemplo, una implementación gradual suele esperar a que se completen las implementaciones en cada conjunto de máquinas virtuales antes de continuar con el siguiente conjunto de implementaciones. Puede realizar una comprobación de estado después de cada iteración y, si se produce un problema significativo, se puede detener la implementación gradual.
Las implementaciones graduales se pueden configurar especificando la palabra clave rolling: en el strategy: nodo .
La strategy.name variable está disponible en este bloque de estrategia, que toma el nombre de la estrategia. En este caso, gradual.
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:
...
Se admiten todos los enlaces de ciclo de vida y se crean trabajos de enlace de ciclo de vida para ejecutarse en cada máquina virtual.
preDeploy, deploy , y se ejecutan una vez por tamaño de lote definido por routeTrafficpostRouteTrafficmaxParallel .
A continuación, on: success se on: failure ejecuta o .
Con , puede controlar el número o porcentaje de destinos de máquina virtual en los maxParallel: <# or % of VMs> que se va a implementar en paralelo. Esto garantiza que la aplicación se ejecuta en estas máquinas y es capaz de controlar las solicitudes mientras se realiza la implementación en el resto de las máquinas, lo que reduce el tiempo de inactividad general.
Nota
Hay algunas lagunas conocidas en esta característica. Por ejemplo, cuando vuelva a intentar una fase, volverá a ejecutar la implementación en todas las máquinas virtuales, no solo en destinos con errores.
Estrategia de implementación de valores controlados
La estrategia de implementación de riesgo es una estrategia de implementación avanzada que ayuda a mitigar el riesgo que implica la implementación de nuevas versiones de aplicaciones. Con esta estrategia, puede realizar primero los cambios en un pequeño subconjunto de servidores. A medida que obtenga más confianza en la nueva versión, puede liberarla a más servidores de la infraestructura y enrutar más tráfico a ella.
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:
...
La estrategia de implementación de valor canario admite el enlace de ciclo de vida (se ejecuta una vez) e itera con los enlaces de ciclo de vida preDeploydeploy , y routeTrafficpostRouteTraffic . A continuación, se cierra con el success enlace failure o .
Las siguientes variables están disponibles en esta estrategia:
strategy.name: nombre de la estrategia. Por ejemplo, canary.
strategy.action: acción que se va a realizar en el clúster de Kubernetes. Por ejemplo, implemente, promueva o rechace.
strategy.increment: valor de incremento utilizado en la interacción actual. Esta variable solo está disponible en los enlaces deploy de ciclo de vida , y routeTrafficpostRouteTraffic .
Ejemplos
Estrategia de implementación de RunOnce
En el siguiente fragmento de código YAML de ejemplo se muestra un uso sencillo de un trabajo de implementación mediante la estrategia runOnce de implementación. En el ejemplo se incluye un paso de desprotección.
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
Con cada ejecución de este trabajo, el historial de implementación se registra en el smarthotel-dev entorno.
Nota
- También es posible crear un entorno con recursos vacíos y usarlo como un shell abstracto para registrar el historial de implementación, como se muestra en el ejemplo anterior.
En el ejemplo siguiente se muestra cómo una canalización puede hacer referencia tanto a un entorno como a un recurso que se usará como destino de un trabajo de implementación.
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)
Este enfoque tiene las siguientes ventajas:
- Registra el historial de implementación en un recurso específico dentro del entorno, en lugar de registrar el historial en todos los recursos dentro del entorno.
- Los pasos del trabajo de implementación heredan automáticamente los detalles de conexión del recurso (en este caso, un espacio de nombres de Kubernetes, ), porque el trabajo de implementación está vinculado al entorno. Esto resulta útil en los casos en los que se establece el mismo detalle de conexión para varios pasos del trabajo.
Estrategia de implementación gradual
La estrategia gradual para las máquinas virtuales actualiza hasta cinco destinos en cada iteración. maxParallel determinará el número de destinos que se pueden implementar en paralelo. La selección tiene en cuenta el número absoluto o el porcentaje de destinos que deben permanecer disponibles en cualquier momento excluyendo los destinos en los que se está realizando la implementación. También se usa para determinar las condiciones de acierto y error durante la implementación.
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
Estrategia de implementación de valores controlados
En el ejemplo siguiente, la estrategia de valores canarios para AKS implementará primero los cambios con pods del 10 por ciento, seguidos del 20 por ciento, mientras supervisa el estado durante postRouteTraffic . Si todo va bien, se promoverá al 100 %.
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...
Uso de decoradores de canalización para insertar pasos automáticamente
Los decoradores de canalización se pueden usar en los trabajos de implementación para insertar automáticamente cualquier paso personalizado (por ejemplo, el analizador de vulnerabilidades) en cada ejecución de enlace de ciclo de vida de cada trabajo de implementación. Dado que los decoradores de canalizaciones se pueden aplicar a todas las canalizaciones de una organización, esto se puede aprovechar como parte de la aplicación de prácticas de implementación seguras.
Además, los trabajos de implementación se pueden ejecutar como un trabajo de contenedor junto con el coche lateral de los servicios, si se definen.
Compatibilidad con variables de salida
Defina las variables de salida en los enlaces de ciclo de vida de un trabajo de implementación y conséctelas en otros pasos y trabajos de nivel inferior dentro de la misma fase.
Para compartir variables entre fases, genera un artefacto en una fase y, a continuación, lo consume en una fase posterior, o usa la sintaxis descrita en las variables.
Al ejecutar estrategias de implementación, puede acceder a variables de salida entre trabajos mediante la sintaxis siguiente.
- Para la estrategia runOnce: (por ejemplo,
$[dependencies.JobA.outputs['Deploy.StepA.VariableA']]) - Para la estrategia runOnce más un resourceType: . (por ejemplo,
$[dependencies.JobA.outputs['Deploy_VM1.StepA.VariableA']]) - Para la estrategia de los canarios:
- Para la estrategia gradual:
# 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 un trabajo, especifique el nombre del trabajo en lugar del runOnce enlace de 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
Al definir un entorno en un trabajo de implementación, la sintaxis de la variable de salida varía en función de cómo se defina el entorno. En este ejemplo, env1 usa la notación abreviada e env2 incluye la sintaxis completa con un 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
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
Cuando se genera una variable desde un trabajo de implementación, al hacer referencia a ella desde el siguiente trabajo se usa una sintaxis diferente en función de si desea establecer una variable o usarla como condición para la fase.
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)
Más información sobre cómo establecer una variable de salida de varios trabajos
Preguntas más frecuentes
Mi canalización está bloqueada con el mensaje "El trabajo está pendiente...". ¿Cómo lo puedo corregir?
Esto puede ocurrir cuando hay un conflicto de nombres entre dos trabajos. Compruebe que los trabajos de implementación de la misma fase tienen un nombre único y que los nombres de trabajo y fase no contienen palabras clave. Si el cambio de nombre no corrige el problema, revise la solución de problemas de ejecuciones de canalización.
¿Se admiten decoradores en grupos de implementación?
No. No se pueden usar elementos decorator en grupos de implementación.