Ejercicio: Implementación del patrón de implementación azul-verde

Completado

En Creación de una canalización de varias fases con Azure Pipelines, ha creado una canalización de implementación básica que implementa una aplicación web en Azure App Service en estas fases: Desarrollo, Pruebas y Ensayo.

Aquí, ampliará ese flujo de trabajo mediante la aplicación del patrón de implementación azul-verde durante la fase de Ensayo.

Para ello, haremos lo siguiente:

  • Agregar una ranura de implementación a la instancia de App Service que se corresponda con Ensayo.
  • Agregar una tarea a la canalización para intercambiar las ranuras de implementación.

Incorporación de una ranura de implementación

Ahora agregará una ranura de implementación a la instancia de App Service que se corresponda con Ensayo.

De forma predeterminada, cada instancia de App Service proporciona una ranura predeterminada, denominada production (Producción). Ha realizado la implementación en la ranura production al configurar la canalización en la sección anterior.

Una instancia de App Service puede tener varias ranuras. Aquí se agrega una segunda ranura de implementación a la instancia de App Service que se corresponde con Ensayo. La ranura de implementación se denomina swap.

Para agregar la ranura:

  1. Abra Azure Portal e inicie sesión.

  2. En el menú, seleccione Cloud Shell. Cuando se le solicite, seleccione la experiencia de Bash.

  3. Ejecute el comando siguiente para obtener el nombre de la instancia de App Service que se corresponde a Ensayo y almacene el resultado en una variable de Bash denominada staging.

    staging=$(az webapp list \
      --resource-group tailspin-space-game-rg \
      --query "[?contains(@.name, 'tailspin-space-game-web-staging')].{name: name}" \
      --output tsv)
    

    El argumento --query usa JMESPath, que es un lenguaje de consulta para JSON. El argumento selecciona la instancia de App Service cuyo campo name contiene "tailspin-space-game-web-staging".

  4. Imprima la variable staging para comprobar que obtiene el nombre correcto.

    echo $staging
    

    A continuación, presentamos un ejemplo de la salida:

    tailspin-space-game-web-staging-1234
    
  5. Ejecute el comando siguiente para agregar una ranura denominada swap al entorno Ensayo.

    az webapp deployment slot create \
      --name $staging \
      --resource-group tailspin-space-game-rg \
      --slot swap
    
  6. Ejecute el comando siguiente para mostrar el nombre de host de la ranura de implementación.

    az webapp deployment slot list \
        --name $staging \
        --resource-group tailspin-space-game-rg \
        --query [].hostNames \
        --output tsv
    

    El resultado es similar a esta salida:

    tailspin-space-game-web-staging-25391-swap.azurewebsites.net
    

    Anote este nombre para usarlo más adelante.

  7. Como paso opcional, vaya al sitio en un explorador. Verá la página principal predeterminada porque todavía no ha implementado el código en esta ranura.

    Screenshot of the default home page in Azure App Service.

De forma predeterminada, una ranura de implementación es accesible desde Internet. En la práctica, podría configurar una red virtual de Azure que coloque la ranura swap en una red que no sea enrutable a Internet y a la que solo pueda acceder el equipo. La ranura production seguirá siendo accesible desde Internet.

Intercambio de ranuras de implementación en Ensayo

Aquí puede usar la tarea AzureAppServiceManage@0 para intercambiar ranuras de implementación en el entorno de ensayo.

También puede usar esta tarea para iniciar, detener o eliminar una ranura. O bien para instalar extensiones de sitio o habilitar la supervisión continua en App Service.

  1. En Visual Studio Code, modifique azure-pipelines.yml con este código:

    Sugerencia

    Puede reemplazar todo el archivo o simplemente actualizar el elemento que está resaltado.

    trigger:
    - '*'
    
    variables:
      buildConfiguration: 'Release'
    
    stages:
    - stage: 'Build'
      displayName: 'Build the web application'
      jobs: 
      - job: 'Build'
        displayName: 'Build job'
        pool:
          vmImage: 'ubuntu-20.04'
          demands:
          - npm
    
        variables:
          wwwrootDir: 'Tailspin.SpaceGame.Web/wwwroot'
          dotnetSdkVersion: '6.x'
    
        steps:
        - task: UseDotNet@2
          displayName: 'Use .NET SDK $(dotnetSdkVersion)'
          inputs:
            version: '$(dotnetSdkVersion)'
    
        - task: Npm@1
          displayName: 'Run npm install'
          inputs:
            verbose: false
    
        - script: './node_modules/.bin/node-sass $(wwwrootDir) --output $(wwwrootDir)'
          displayName: 'Compile Sass assets'
    
        - task: gulp@1
          displayName: 'Run gulp tasks'
    
        - script: 'echo "$(Build.DefinitionName), $(Build.BuildId), $(Build.BuildNumber)" > buildinfo.txt'
          displayName: 'Write build info'
          workingDirectory: $(wwwrootDir)
    
        - task: DotNetCoreCLI@2
          displayName: 'Restore project dependencies'
          inputs:
            command: 'restore'
            projects: '**/*.csproj'
    
        - task: DotNetCoreCLI@2
          displayName: 'Build the project - $(buildConfiguration)'
          inputs:
            command: 'build'
            arguments: '--no-restore --configuration $(buildConfiguration)'
            projects: '**/*.csproj'
    
        - task: DotNetCoreCLI@2
          displayName: 'Publish the project - $(buildConfiguration)'
          inputs:
            command: 'publish'
            projects: '**/*.csproj'
            publishWebProjects: false
            arguments: '--no-build --configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)/$(buildConfiguration)'
            zipAfterPublish: true
    
        - publish: '$(Build.ArtifactStagingDirectory)'
          artifact: drop
    
    - stage: 'Dev'
      displayName: 'Deploy to the dev environment'
      dependsOn: Build
      jobs:
      - deployment: Deploy
        pool:
          vmImage: 'ubuntu-20.04'
        environment: dev
        variables:
        - group: Release
        strategy:
          runOnce:
            deploy:
              steps:
              - download: current
                artifact: drop
              - task: AzureWebApp@1
                displayName: 'Azure App Service Deploy: website'
                inputs:
                  azureSubscription: 'Resource Manager - Tailspin - Space Game'
                  appName: '$(WebAppNameDev)'
                  package: '$(Pipeline.Workspace)/drop/$(buildConfiguration)/*.zip'
    
    - stage: 'Test'
      displayName: 'Deploy to the test environment'
      dependsOn: Dev
      jobs:
      - deployment: Deploy
        pool:
          vmImage: 'ubuntu-20.04'
        environment: test
        variables:
        - group: 'Release'
        strategy:
          runOnce:
            deploy:
              steps:
              - download: current
                artifact: drop
              - task: AzureWebApp@1
                displayName: 'Azure App Service Deploy: website'
                inputs:
                  azureSubscription: 'Resource Manager - Tailspin - Space Game'
                  appName: '$(WebAppNameTest)'
                  package: '$(Pipeline.Workspace)/drop/$(buildConfiguration)/*.zip'
    
    - stage: 'Staging'
      displayName: 'Deploy to the staging environment'
      dependsOn: Test
      jobs:
      - deployment: Deploy
        pool:
          vmImage: 'ubuntu-20.04'
        environment: staging
        variables:
        - group: 'Release'
        strategy:
          runOnce:
            deploy:
              steps:
              - download: current
                artifact: drop
              - task: AzureWebApp@1
                displayName: 'Azure App Service Deploy: website'
                inputs:
                  azureSubscription: 'Resource Manager - Tailspin - Space Game'
                  deployToSlotOrASE: 'true'
                  resourceGroupName: 'tailspin-space-game-rg'
                  slotName: 'swap'
                  appName: '$(WebAppNameStaging)'
                  package: '$(Pipeline.Workspace)/drop/$(buildConfiguration)/*.zip'
              - task: AzureAppServiceManage@0
                displayName: 'Swap deployment slots'
                inputs:
                  azureSubscription: 'Resource Manager - Tailspin - Space Game'
                  resourceGroupName: 'tailspin-space-game-rg'
                  webAppName: '$(WebAppNameStaging)'
                  sourceSlot: 'swap'
                  targetSlot: 'production'
                  action: 'Swap Slots'
    

    Anote estos cambios:

    • Ahora la tarea AzureWebApp@1 especifica estos valores:
      • deployToSlotOrASE, cuando se establece en true, se implementa en una ranura de implementación existente.
      • resourceGroupName especifica el nombre del grupo de recursos. Este valor es obligatorio cuando deployToSlotOrASE es true.
      • slotName especifica el nombre de la ranura de implementación. Aquí la implementación se realiza en la ranura denominada swap.
    • La nueva tarea, AzureAppServiceManage@0, intercambia las ranuras de implementación.
      • sourceSlot y targetSlot especifican las ranuras que se van a intercambiar.
      • action especifica la acción que se va a realizar. Recuerde que puede usar esta tarea para iniciar, detener o eliminar una ranura. Aquí, "Intercambiar espacios" especifica el intercambio de las ranuras de origen y de destino.

    Esta configuración siempre realiza la implementación en la ranura swap. Después, intercambia las ranuras production y swap. El proceso de intercambio garantiza que production señale a la implementación más reciente.

  2. En el terminal integrado, agregue azure-pipelines.yml al índice. Confirme los cambios y, después, inserte la rama en GitHub.

    Sugerencia

    Guarde azure-pipelines.yml antes de ejecutar estos comandos de Git.

    git add azure-pipelines.yml
    git commit -m "Swap deployment slots"
    git push origin blue-green
    
  3. En Azure Pipelines, realice el seguimiento de la compilación a lo largo de cada uno de los pasos.

Nota

Si se produce el siguiente error ...'staging' slot did not respond to http ping. (CODE: 417), intente reiniciar el servicio de aplicaciones. Si el problema persiste, restablezca el intercambio automático de la ranura.

  1. Como paso opcional, en un explorador, vaya a la dirección URL correspondiente a cada fase.

    Aunque todavía no ha realizado cambios en el sitio web Space Game, verá que se ha implementado correctamente en cada entorno de App Service.

    Screenshot of a browser that shows the Space Game website in the Dev environment.