연습 - Azure에 Azure Functions 앱 배포

완료됨

프로젝트에는 솔루션에서 프로젝트를 빌드하고 웹앱을 Azure App Service에 배포하는 파이프라인이 함께 제공되었습니다. 이제 해당 파이프라인을 확장하여 새 Azure Functions 프로젝트도 배포해 보겠습니다.

이 부분에서는 다음을 수행합니다.

  • ‘빌드’ 단계를 검토합니다.
  • 함수 앱을 배포하는 작업을 추가합니다.
  • 게시된 함수를 사용하도록 게시된 App Service를 구성하는 작업을 추가합니다.
  • 파이프라인을 저장하여 CI/CD 워크플로를 트리거합니다.

빌드 단계 검토

여기서는 azure-pipelines.yml에 정의된 기존 CI/CD 파이프라인을 검토합니다.

  1. Azure DevOps에서 Pipelines로 이동합니다.

  2. 파이프라인을 선택합니다.

  3. 편집을 선택합니다. 드롭다운 메뉴에서 분기를 선택하여 분기가 기본으로 설정되어 있는지 확인합니다. 그러면 기존 CI/CD 파이프라인을 정의한 azure-pipelines.yml 파일이 표시됩니다.

    프로젝트 경로에 와일드카드를 사용하기 때문에 아래에 강조 표시된 작업은 새 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: 여기까지가 이전의 빌드 단계였습니다. 작업이 이미 와일드카드 일치 패턴을 기반으로 모든 프로젝트에 대해 실행되도록 구성되었기 때문에 원래 프로젝트에서 코드를 변경하지 않았어요.

Mara: 예, 이것은 있는 그대로 작동해요. 여기서 변경할 필요가 없다고 생각해요. 이 빌드 작업이 실행된 후 웹과 순위표 프로젝트 모두에 대한 zip 파일 아티팩트가 배포 단계에서 사용될 수 있도록 게시될 거예요.

Azure Functions를 배포하는 작업 추가

Andy: App Service 배포 작업을 있는 그대로 재사용할 수도 있을 것 같은데요. 함수 앱을 배포하는 데 사용할 수 있는 비슷한 것이 있으면 좋겠네요.

Mara: 좋은 소식이 있어요. 조사를 조금 해보니까 App Service 배포 작업과 개념적으로 비슷하지만 Azure Functions 배포를 위한 작업이 있는 것 같아요. 이제 이를 검토해 보겠습니다.

Azure 함수 앱 작업

AzureFunctionApp@1 작업은 함수 앱을 배포하도록 설계되었습니다. 해당 작업은 개념적으로 AzureWebApp@1 작업과 비슷하며, 다음과 같이 이 함수 앱 시나리오에 필요한 모든 것을 포함하고 있습니다.

  • azureSubscription은 Azure 서비스 연결 파이프라인 변수의 이름을 나타냅니다.
  • appType은 앱이 Linux(functionAppLinux)용으로 배포되는지 또는 Windows(functionApp)용으로 배포되는지를 나타냅니다.
  • appName은 Azure 계정에서 Azure Functions 앱 인스턴스의 이름을 지정합니다.
  • package는 배포할 패키지의 경로를 지정합니다.
  • runtimeStack은 Linux 배포에 필요한 함수가 실행되어야 하는 이미지를 나타냅니다.
  • startUpCommand는 Linux 배포에 필요한 함수가 배포된 후 실행할 시작 명령을 지정합니다.

Azure 함수 앱 작업에 관한 설명서에서 이 작업의 유연성에 대해 자세히 알아볼 수 있습니다.

아래에 강조 표시된 코드를 파이프라인 끝에 추가합니다.

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

YAML 파일에서 공백은 중요합니다. 여기서 추가하는 작업이 이전 작업과 동일한 들여쓰기를 사용하는지 확인해야 합니다.

App Service의 앱 설정을 업데이트하는 작업 추가

Andy: 이제 게시된 순위표 API를 사용하도록 웹앱을 구성하기만 하면 됩니다. 일반적으로 포털에서 변수를 구성하지만 여기서 구성할 수 있다면 더 좋겠어요. 그러려면 LeaderboardFunctionUrl라는 AppSettings 매개 변수가 필요해요.

Mara: 동의해요. 이를 위한 작업을 파이프라인에 추가하면 어느 한 서비스를 변경하더라도 장래의 우발적인 실수를 방지할 수 있을 거예요. 우리는 끝에 바로 넣을 수 있어요.

아래에 강조 표시된 코드를 파이프라인 끝에 추가합니다. 그 위에 있는 작업의 들여쓰기와 일치해야 합니다. 이 작업에 대해 자세히 알아보려면 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
        }
      ]

파이프라인을 저장하여 빌드 및 릴리스 트리거

  1. 페이지 오른쪽 상단 모서리에서 Save를 선택합니다. Save를 확인하여 실행을 트리거합니다.

  2. Azure Pipelines에서 빌드로 이동합니다. 실행되는 빌드를 추적합니다.

  3. 빌드가 성공하면 웹 사이트의 배포 작업을 선택하고 URL을 선택하여 배포된 사이트를 확인합니다.

    웹 사이트 URL의 위치를 보여 주는 Azure Pipelines의 스크린샷.

  4. 사이트가 App Service에서 실행되는 페이지가 표시됩니다. 아래로 스크롤하여 순위표에 실제 데이터가 있는지 확인합니다. 해당 데이터는 함수 앱에 의해 제공됩니다.

    Space Game 웹 사이트의 스크린샷.

    참고

    순위표를 로드하는 동안 오류가 발생하는 경우 이 모듈에서 수행한 단계를 다시 확인하세요. “해당 액세스 권한에 의해 금지된 방식으로 소켓에 액세스하려고 시도했습니다.”라는 예외 프롬프트가 표시되면 앱 서비스의 AppSettings__LeaderboardFunctionUrl 설정이 올바르게 설정되어 있는지 확인하세요.

  5. 함수 앱을 직접 테스트할 수도 있습니다. 다음 형식을 사용하여 URL로 이동하면 됩니다. 응답은 JSON으로, 브라우저에서 텍스트로 렌더링됩니다.

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

    예:

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

Andy: 아주 좋네요. 모든 사람이 여기서 우리가 보여 준 가능성에 깊은 인상을 받을 거예요.