Ejercicio: Implementación de una aplicación de Azure Functions en Azure

Completado

En el proyecto se incluía una canalización que compila los proyectos de la solución e implementa la aplicación web en Azure App Service. Ahora es el momento de ampliar esa canalización para implementar también el nuevo proyecto de Azure Functions.

En esta parte, hará lo siguiente:

  • Revisar la fase de compilación.
  • Agregar una tarea para implementar la aplicación de funciones.
  • Agregar una tarea de configuración a la instancia publicada de App Service para usar la función publicada.
  • Guardar la canalización para desencadenar un flujo de trabajo de CI/CD.

Revisión de la fase de compilación

Aquí revisará la canalización de CI/CD existente definida en azure-pipelines.yml.

  1. En Azure DevOps, vaya a Canalizaciones.

  2. Seleccione la canalización.

  3. Seleccione Editar. Asegúrese de que la rama está establecida como principal; para ello, selecciónela en el menú desplegable. Se abrirá el archivo azure-pipelines.yml en el que se define la canalización de CI/CD existente.

    Debido al uso de caracteres comodín en las rutas de acceso del proyecto, las tareas resaltadas a continuación restaurarán, compilarán y publicarán automáticamente el nuevo proyecto de Azure Functions.

    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.0.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
    

Andy: Esta era la fase de compilación anterior. No lo ha cambiado con respecto al proyecto original porque las tareas ya estaban configuradas para ejecutarse en todos los proyectos en función del patrón de coincidencia de caracteres comodín.

Mara: Sí, debería funcionar tal cual. No creo que aquí sea necesario realizar ningún cambio. Después de que se ejecute esta tarea de compilación, los artefactos del archivo ZIP para los proyectos web y de tabla de clasificación se publicarán para su uso en la fase de implementación.

Adición de una tarea para implementar la función de Azure

Andy: Creo que también podemos reutilizar la tarea de implementación de App Service tal cual. Esperamos que haya algo similar que podamos usar para implementar una aplicación de funciones.

Mara: Tengo buenas noticias. Después de una pequeña investigación, parece que hay una tarea conceptualmente similar a la de implementación de App Service, pero para implementaciones de Azure Functions. Vamos a revisarla ahora.

Tarea de aplicación de funciones de Azure

La tarea AzureFunctionApp@1 está diseñada para implementar aplicaciones de funciones. Conceptualmente es similar a la tarea AzureWebApp@1 e incluye todo lo necesario para este escenario de aplicación de funciones:

  • azureSubscription hace referencia al nombre de la variable de canalización de conexión del servicio de Azure.
  • appType indica si la aplicación se va a implementar para Linux (functionAppLinux) o Windows (functionApp).
  • appName especifica el nombre de la instancia de la aplicación de Azure Functions en la cuenta de Azure.
  • package especifica la ruta de acceso del paquete que se va a implementar.
  • runtimeStack indica la imagen en la que se debe ejecutar la función, que es necesaria para las implementaciones de Linux.
  • startUpCommand especifica el comando de inicio que se debe ejecutar una vez que se haya implementado la función, necesario para las implementaciones de Linux.

Puede obtener más información sobre la flexibilidad de esta tarea en la documentación de la tarea Azure Function App.

Agregue el código resaltado siguiente al final de la canalización.

- stage: 'Deploy'
  displayName: 'Deploy the web application'
  dependsOn: Build
  jobs:
  - deployment: Deploy
    pool:
      vmImage: 'ubuntu-20.04'
    environment: spike
    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: '$(WebAppName)'
              appType: webAppLinux
              package: '$(Pipeline.Workspace)/drop/$(buildConfiguration)/Tailspin.SpaceGame.Web.zip'

          - task: AzureFunctionApp@1
            displayName: 'Azure Function Deploy: leaderboard'
            inputs:
              azureSubscription: 'Resource Manager - Tailspin - Space Game'
              appType: functionAppLinux
              appName: '$(LeaderboardAppName)'
              package: '$(Pipeline.Workspace)/drop/$(buildConfiguration)/Tailspin.SpaceGame.LeaderboardFunction.zip'
              runtimeStack: DOCKER|microsoft/azure-functions-dotnet:4
              startUpCommand: 'func azure functionapp publish $(functionAppName) --no-bundler'

Sugerencia

En un archivo YAML, el espacio en blanco es importante. Asegúrese de que en la tarea que agrega aquí se usa la misma sangría que en la anterior.

Adición de una tarea para actualizar la configuración de la aplicación de App Service

Andy: Ahora todo lo que debemos hacer es configurar la aplicación web para que use la API de tabla de clasificación publicada. Normalmente configuramos las variables en el portal, pero sería mejor poder hacerlo aquí. Espera un parámetro AppSettings denominado LeaderboardFunctionUrl.

Mara: De acuerdo. Agregar una tarea para eso a nuestra canalización nos ayudará a evitar descuidos accidentales durante el proceso si cambiamos alguno de los servicios. Podemos colocarla justo al final.

Agregue el código resaltado siguiente al final de la canalización. Asegúrese de que coincide con la sangría de la tarea anterior. Si quiere obtener más información sobre esta tarea, puede revisar la documentación de la tarea Configuración de Azure App Service .

- task: AzureFunctionApp@1
  displayName: 'Azure Function Deploy: leaderboard'
  inputs:
    azureSubscription: 'Resource Manager - Tailspin - Space Game'
    appType: functionAppLinux
    appName: '$(LeaderboardAppName)'
    package: '$(Pipeline.Workspace)/drop/$(buildConfiguration)/Tailspin.SpaceGame.LeaderboardFunction.zip'
    runtimeStack: DOCKER|microsoft/azure-functions-dotnet:4
    startUpCommand: 'func azure functionapp publish $(functionAppName) --no-bundler'

- task: AzureAppServiceSettings@1
  displayName: 'Update web app settings'
  inputs:
    azureSubscription: 'Resource Manager - Tailspin - Space Game'
    appName: $(WebAppName)
    resourceGroupName: $(ResourceGroupName)
    appSettings: |
      [
        {
          "name": "AppSettings__LeaderboardFunctionUrl",
          "value": "http://$(LeaderboardAppName).azurewebsites.net/api/LeaderboardFunction",
          "slotSetting": false
        }
      ]

Guardado de la canalización para desencadenar una compilación y una versión

  1. Seleccione Guardar en la esquina superior derecha de la página. Confirme Guardar para desencadenar una ejecución.

  2. En Azure Pipelines, vaya a la compilación. Realice el seguimiento de la compilación a medida que se ejecuta.

  3. Una vez que la compilación se haya realizado correctamente, seleccione la tarea de implementación del sitio web y seleccione la dirección URL para ver el sitio implementado.

    Captura de pantalla de Azure Pipelines en la que se muestra el URL del sitio web.

  4. Obtendrá una página con el sitio que se ejecuta en App Service. Desplácese hacia abajo para confirmar que la tabla de clasificación contenga datos. La aplicación de funciones proporciona esta tecnología.

    Captura de pantalla del sitio web de Space Game.

    Nota:

    Si se produce un error al cargar la tabla de clasificación, vuelva a comprobar los pasos que ha seguido en este módulo. Si ve el mensaje de excepción "An attempt was made to access a socket in a way forbidden by its access permissions" (Se ha realizado un intento de acceso a un socket de una manera prohibida por sus permisos de acceso), asegúrese de que el valor AppSettings__LeaderboardFunctionUrl de App Service se ha establecido correctamente.

  5. También puede probar directamente la aplicación de funciones. Solo tiene que ir a la dirección URL con el siguiente formato. La respuesta es JSON, que debería representarse como texto en el explorador.

    http://<leaderboard function name>.azurewebsites.net/api/LeaderboardFunction?pageSize=10
    

    Por ejemplo,

    http://tailspin-space-game-leaderboard-4692.azurewebsites.net/api/LeaderboardFunction?pageSize=10
    

Andy: ¡Ha salido muy bien! Todos deberían estar impresionados con el potencial que hemos demostrado.