Exercice – Déployer une application Azure Functions dans Azure

Effectué

Votre projet comprend un pipeline qui génère les projets dans la solution et déploie l’application web sur Azure App Service. Le moment est venu à présent d’étendre ce pipeline pour déployer également le nouveau projet Azure Functions.

Dans cette partie, vous allez :

  • Passer en revue la phase de génération.
  • Ajouter une tâche pour déployer votre application de fonction.
  • Ajouter une tâche pour configurer l’instance App Service publiée de sorte qu’elle utilise la fonction publiée.
  • Enregistrer le pipeline pour déclencher un flux de travail CI/CD.

Passer en revue la phase de génération

Ici, vous allez examiner le pipeline CI/CD existant défini dans azure-pipelines.yml.

  1. Dans Azure DevOps, accédez à Pipelines.

  2. Sélectionnez le pipeline.

  3. Sélectionnez Modifier. Vérifiez que la branche est définie sur principal en la sélectionnant dans le menu déroulant. Cela fait apparaître le fichier azure-pipelines.yml qui définit le pipeline CI/CD existant.

    Du fait de l’utilisation de caractères génériques dans les chemins du projet, les tâches mises en évidence ci-dessous restaurent, génèrent et publient automatiquement le nouveau projet 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 : Voici notre phase de génération précédente. Je ne l’ai pas modifiée par rapport au projet d’origine, car les tâches étaient déjà configurées pour s’exécuter sur tous les projets basés sur le modèle de mise en correspondance de caractères génériques.

Mara : Oui, cela devrait fonctionner en l’état. Je ne pense pas que nous ayons besoin d’apporter de modifications ici. Une fois cette tâche de génération exécutée, les artefacts de fichier zip des projets web et leaderboard sont publiés pour être utilisés à la phase de déploiement.

Ajouter une tâche pour déployer la fonction Azure

Andy : Je pense que nous pouvons aussi réutiliser la tâche de déploiement App Service telle quelle. J’espère que nous avons quelque chose de similaire pour déployer une application de fonction.

Mara : J’ai une bonne nouvelle. Après quelques recherches, il semble qu’il existe une tâche similaire d’un point de vue conceptuel à la tâche de déploiement App Service, mais pour les déploiements Azure Functions. Voyons cela.

Tâche d’application de fonction Azure

La tâche AzureFunctionApp@1 est destinée à déployer des applications de fonction. D’un point de vue conceptuel, elle est similaire à la tâche AzureWebApp@1 et elle offre tout ce qui est nécessaire à ce scénario d’application de fonction :

  • azureSubscription fait référence au nom de la variable du pipeline de connexion à vos services Azure.
  • appType indique si l’application est déployée pour Linux (functionAppLinux) ou Windows (functionApp).
  • appName spécifie le nom de l’instance d’application Azure Functions dans votre compte Azure.
  • package spécifie le chemin du package à déployer.
  • runtimeStack indique sur quelle image la fonction doit s’exécuter, ce qui est nécessaire pour les déploiements Linux.
  • startUpCommand spécifie la commande de démarrage à exécuter après que la fonction a été déployée, ce qui est nécessaire pour les déploiements Linux.

Pour plus d’informations sur la flexibilité de cette tâche, consultez la documentation relative à la tâche d’application de fonction Azure.

Ajoutez le code mis en évidence suivant à la suite de votre pipeline.

- 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'

Conseil

Dans un fichier YAML, l’espace blanc est important. Vérifiez que la tâche que vous ajoutez ici utilise la même mise en retrait que la tâche précédente.

Ajouter une tâche pour mettre à jour les paramètres d’application d’App Service

Andy : À présent, il ne nous reste plus qu’à configurer l’application web pour qu’elle utilise l’API Leaderboard publiée. Nous configurons habituellement les variables sur le portail, mais il serait préférable de le faire ici. Elle attend un paramètre AppSettings nommé LeaderboardFunctionUrl.

Mara : Je suis d’accord. L’ajout d’une tâche prévue à cet effet à notre pipeline nous évitera par la suite des oublis accidentels si nous modifions l’un ou l’autre des services. Nous pouvons la placer juste à la fin.

Ajoutez le code mis en évidence suivant à la suite de votre pipeline. Veillez à ce qu’elle présente la même mise en retrait que la tâche qui le précède. Si vous souhaitez en savoir plus sur cette tâche, vous pouvez consulter la documentation relative à la tâche Paramètres 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
        }
      ]

Enregistrer le pipeline pour déclencher une génération et une mise en production

  1. Sélectionnez Enregistrer en haut à droite de la page. Confirmez l’enregistrement pour déclencher une exécution.

  2. Dans Azure Pipelines, accédez à la build. Suivez la build pendant son exécution.

  3. Une fois la build réussie, sélectionnez la tâche de déploiement du site web, puis sélectionnez l’URL pour voir le site déployé.

    Capture d’écran d’Azure Pipelines montrant l’emplacement de l’URL du site web.

  4. Vous obtiendrez une page avec le site exécuté sur App Service. Faites défiler l’écran vers le bas pour vérifier que le leaderboard contient des données réelles. Il est alimenté par l’application de fonction.

    Capture d'écran du site web de Space Game.

    Notes

    Si une erreur se produit pendant le chargement du leaderboard, revérifiez les étapes que vous avez suivies dans ce module. Si vous obtenez le message d’exception « Tentative d’accès à un socket de manière interdite par ses autorisations d’accès », vérifiez que le paramètre AppSettings__LeaderboardFunctionUrl du service d’application est correctement défini.

  5. Vous pouvez aussi tester directement l’application de fonction. Accédez simplement à votre URL en utilisant le format suivant. La réponse est un fichier JSON, qui doit simplement s’afficher sous forme de texte dans votre navigateur.

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

    Par exemple :

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

Andy : C’est parfait ! Tout le monde devrait être assez impressionné par le résultat.