Übung: Bereitstellen einer Azure Functions-App in Azure

Abgeschlossen

In Ihrem Projekt war eine Pipeline enthalten, die die Projekte in der Projektmappe erstellt und die Web-App für Azure App Service bereitstellt. Nun ist es an der Zeit, diese Pipeline zu erweitern, um auch das neue Azure Functions-Projekt bereitzustellen.

In diesem Teil führen Sie die folgenden Aktionen aus:

  • Überprüfen der Buildphase.
  • Hinzufügen einer Aufgabe zum Bereitstellen Ihrer Funktions-App.
  • Hinzufügen einer Aufgabe zum Konfigurieren des veröffentlichten App Service zum Verwenden der veröffentlichten Funktion.
  • Speichern Sie die Pipeline, um einen CI/CD-Workflow auszulösen.

Überprüfen der Buildphase

Hier überprüfen Sie die vorhandene in azure-pipelines.yml definierte CI/CD-Pipeline.

  1. Navigieren Sie aus Azure DevOps zu Pipelines.

  2. Wählen Sie die Pipeline aus.

  3. Wählen Sie Bearbeiten aus. Stellen Sie sicher, dass der Branch auf main festgelegt ist, indem Sie diesen aus der Dropdownliste auswählen. Dadurch wird die Datei azure-pipelines.yml geöffnet, in der die vorhandene CI/CD-Pipeline definiert wird.

    Aufgrund der Verwendung von Platzhaltern für die Projektpfade stellen die unten hervorgehobenen Aufgaben das neue Azure Functions-Projekt automatisch wieder her und erstellen und veröffentlichen es.

    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: Dies war unsere vorherige Buildphase. Ich habe sie gegenüber dem ursprünglichen Projekt nicht geändert, weil die Aufgaben bereits so konfiguriert waren, dass sie für alle Projekte auf der Grundlage des Platzhalterabgleichmusters ausgeführt werden.

Mara: Ja, das sollte unverändert funktionieren. Ich denke nicht, dass wir hier Änderungen vornehmen müssen. Nachdem dieser Buildtask ausgeführt wurde, werden die ZIP-Dateiartefakte für die Web- und Bestenlistenprojekte für die zu verwendende Bereitstellungsphase veröffentlicht.

Hinzufügen eines Tasks zum Bereitstellen der Azure-Funktion

Andy: Ich denke, wir können den App Service-Bereitstellungstask ebenfalls unverändert wiederverwenden. Hoffentlich gibt es etwas Ähnliches, das wir für den Einsatz einer Funktions-App verwenden können.

Mara: Ich habe gute Nachrichten. Ich habe ein wenig recherchiert, und es sieht so aus, als gäbe es einen Task, der konzeptionell dem App Service-Bereitstellungstask ähnelt, aber für Azure Functions-Bereitstellungen geeignet ist. Schauen wir uns das jetzt an.

Task „Azure Function-App“

Der Task AzureFunctionApp@1 ist für die Bereitstellung von Funktions-Apps konzipiert. Er ist konzeptionell vergleichbar mit der Aufgabe AzureWebApp@1 und umfasst alles, was für dieses Funktions-App-Szenario erforderlich ist:

  • azureSubscription bezieht sich auf den Namen der Pipelinevariablen der Azure-Dienstverbindung.
  • appType gibt an, ob die App für Linux (functionAppLinux) oder Windows (functionApp) bereitgestellt wird.
  • appName gibt den Namen der Azure Functions-App-Instanz in Ihrem Azure-Konto an.
  • package gibt den Pfad zum bereitzustellenden Paket an.
  • runtimeStack gibt an, mit welchem Image die Funktion ausgeführt werden soll, was für Linux-Bereitstellungen erforderlich ist.
  • startUpCommand gibt den Startbefehl an, der nach der Bereitstellung der Funktion ausgeführt wird, was für Linux-Bereitstellungen erforderlich ist.

Weitere Informationen zur Flexibilität dieses Tasks finden Sie in der Dokumentation zum Task „Azure Funktions-App“.

Fügen Sie den folgenden hervorgehobenen Code am Ende Ihrer Pipeline hinzu.

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

Tipp

In einer YAML-Datei ist der Einzug wichtig. Stellen Sie sicher, dass der Task,den Sie hier hinzufügen, denselben Einzug wie der vorherige Task verwendet.

Hinzufügen eines Tasks zum Aktualisieren der App-Einstellungen der App Service-Instanz

Andy: Jetzt müssen wir nur noch die Web-App so konfigurieren, dass sie die veröffentlichte Bestenlisten-API verwendet. Normalerweise konfigurieren wir Variablen im Portal, aber es wäre besser, wenn wir es hier machen könnten. Erwartet wird ein AppSettings-Parameter namens LeaderboardFunctionUrl.

Mara: Das sehe ich auch so. Das Hinzufügen eines entsprechenden Tasks zu unserer Pipeline hilft uns vermeiden, zufällig etwas zu übersehen, wenn wir einen der beiden Dienste später ändern. Wir können ihn direkt am Ende platzieren.

Fügen Sie den folgenden hervorgehobenen Code am Ende Ihrer Pipeline hinzu. Stellen Sie sicher, dass der Einzug mit dem Task oben identisch ist. Wenn Sie mehr über diese Aufgabe erfahren möchten, können Sie die Dokumentation für die Aufgabe „Azure App Service-Einstellungen“ lesen.

- 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
        }
      ]

Speichern der Pipeline zum Auslösen eines Build- und Releasevorgangs

  1. Klicken Sie in der oberen rechten Ecke der Seite auf Save (Speichern). Bestätigen Sie den Speichervorgang, um eine Ausführung auszulösen.

  2. Wechseln Sie in Azure Pipelines zum Build. Überwachen Sie die Ausführung des Builds.

  3. Wählen Sie nach erfolgreichem Build die Bereitstellungsaufgabe der Website aus, und wählen Sie die URL aus, um die bereitgestellte Website anzuzeigen.

    Screenshot von Azure Pipelines mit der Position der Website-URL

  4. Sie erhalten eine Seite mit der Website, die auf App Service ausgeführt wird. Scrollen Sie nach unten, um zu bestätigen, dass die Bestenliste echte Daten enthält. Dies erfolgt durch die Funktions-App.

    Screenshot der „Space Game“-Website.

    Hinweis

    Wenn beim Laden des Leaderboards ein Fehler auftritt, überprüfen Sie die ausgeführten Schritte in diesem Modul. Wenn die Ausnahmemeldung „An attempt was made to access a socket in a way forbidden by its access permissions“ (Es wurde versucht, auf einen Socket auf eine Weise zuzugreifen, die durch seine Zugriffsberechtigungen unzulässig ist) angezeigt wird, stellen Sie sicher, dass die Einstellung „AppSettings:LeaderboardFunctionUrl“ von App Service ordnungsgemäß festgelegt ist.

  5. Sie können die Funktions-App auch direkt testen. Navigieren Sie einfach zu Ihrer URL, indem Sie das folgende Format verwenden. Die Antwort ist JSON, wodurch nur Text in Ihrem Browser gerendert werden sollte.

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

    Beispiel

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

Andy: Das hat super geklappt! Alle sollten ziemlich beeindruckt sein von dem Potenzial, das wir hier gezeigt haben.