다음을 통해 공유


자습서: Azure DevOps를 사용하여 다단계 파이프라인 만들기

Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019

Azure DevOps 다단계 파이프라인을 사용하여 CI/CD 프로세스를 개발 주기의 여러 부분을 나타내는 단계로 나눌 수 있습니다. 다단계 파이프라인을 사용하면 배포 프로세스에 대한 가시성을 높일 수 있으며 승인 및 검사를 보다 쉽게 통합 할 수 있습니다.

이 문서에서는 두 개의 App Service 인스턴스를 만들고 세 단계로 YAML 파이프라인을 빌드합니다.

실제 시나리오에서는 DevOps 프로세스에 따라 프로덕션에 배포하기 위한 또 다른 단계가 있을 수 있습니다.

이 연습의 예제 코드는 높은 점수를 표시하는 순위표를 포함하는 척 공간 게임의 .NET 웹 애플리케이션에 대한 것입니다. Linux용 Azure Web App의 개발 및 스테이징 인스턴스 모두에 배포합니다.

필수 조건

프로젝트 포크

GitHub에서 다음 샘플 리포지토리를 포크합니다.

https://github.com/MicrosoftDocs/mslearn-tailspin-spacegame-web-deploy

App Service 인스턴스 만들기

파이프라인을 배포하려면 먼저 배포할 App Service 인스턴스를 만들어야 합니다. Azure CLI를 사용하여 인스턴스를 만듭니다.

  1. Azure Portal에 로그인합니다.

  2. 메뉴에서 Cloud ShellBash 환경을 선택합니다.

  3. 웹앱의 도메인 이름을 고유하게 만드는 난수를 생성합니다. 고유한 값을 갖는 장점은 App Service 인스턴스가 이 자습서를 완료하는 다른 학습자와 이름이 충돌하지 않는다는 것입니다.

    webappsuffix=$RANDOM    
    
  4. 명령 프롬프트를 열고 명령을 사용하여 az group create 모든 App Service 인스턴스를 포함하는 tailspin-space-game-rg라는 리소스 그룹을 만듭니다. location 가장 가까운 지역을 사용하도록 값을 업데이트합니다.

    az group create --location eastus --name tailspin-space-game-rg
    
  5. 명령 프롬프트를 사용하여 App Service 계획을 만듭니다.

    az appservice plan create \
      --name tailspin-space-game-asp \
      --resource-group tailspin-space-game-rg \
      --sku B1 \
      --is-linux
    
  6. 명령 프롬프트에서 명령을 사용하여 각 인스턴스(Dev 및 Staging)에 대해 하나씩 두 개의 App Service 인스턴스를 az webapp create 만듭니다.

    az webapp create \
      --name tailspin-space-game-web-dev-$webappsuffix \
      --resource-group tailspin-space-game-rg \
      --plan tailspin-space-game-asp \
      --runtime "DOTNET|6.0"
    
    az webapp create \
      --name tailspin-space-game-web-staging-$webappsuffix \
      --resource-group tailspin-space-game-rg \
      --plan tailspin-space-game-asp \
      --runtime "DOTNET|6.0"
    
  7. 명령 프롬프트를 사용하여 두 App Service 인스턴스를 나열하여 명령으로 az webapp list 실행 중인지 확인합니다.

    az webapp list \
      --resource-group tailspin-space-game-rg \
      --query "[].{hostName: defaultHostName, state: state}" \
      --output table
    
  8. 다음 섹션에서 변수로 사용할 App Service 인스턴스의 이름을 복사합니다.

Azure DevOps 프로젝트 및 변수 만들기

Azure DevOps 프로젝트 및 빌드 파이프라인을 설정합니다. 또한 개발 및 스테이징 인스턴스 대한 변수를 추가합니다.

빌드 파이프라인:

  • 분기로 코드 변경이 있을 때 실행되는 트리거를 포함합니다.
  • 두 개의 변수를 정의합니다. buildConfigurationreleaseBranchName
  • 웹 애플리케이션을 빌드하는 Build라는 스테이지를 포함합니다.
  • 이후 단계에서 사용할 아티팩트를 게시합니다.

빌드 단계 추가

  1. Azure DevOps 조직에 로그인하고, 프로젝트로 이동합니다.

  2. 파이프라인으로 이동한 다음 새 파이프라인을 선택하거나 첫 번째 파이프라인을 만드는 경우 파이프라인 만들기를 선택합니다.

  3. 먼저 소스 코드의 위치로 GitHub 선택하여 마법사의 단계를 수행합니다.

  4. 로그인할 GitHub로 리디렉션될 수 있습니다. 그렇다면 GitHub 자격 증명을 입력합니다.

  5. 리포지토리 목록이 표시되면 리포지토리를 선택합니다.

  6. Azure Pipelines 앱을 설치하도록 GitHub로 리디렉션될 수 있습니다. 그렇다면 승인 및 설치를 선택합니다.

  1. 구성 탭이 나타나면 시작 파이프라인을 선택합니다.

  2. azure-pipelines.yml 내용을 이 코드로 바꿉니다.

    trigger:
    - '*'
    
    variables:
      buildConfiguration: 'Release'
      releaseBranchName: '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
    
  3. 준비가 되면 저장 및 실행을 선택합니다.

인스턴스 변수 추가

  1. Azure DevOps에서 파이프라인>라이브러리이동합니다.

  2. + 변수 그룹을 선택합니다.

  3. 속성 아래에서 변수 그룹 이름에 대한 Release를 추가합니다.

  4. 개발 및 스테이징 호스트 이름을 참조하는 두 개의 변수를 만듭니다. 값을 1234 인스턴스에 대한 올바른 값으로 바꿉습니다.

    변수 이름 예제 값
    WebAppNameDev tailspin-space-game-web-dev-1234
    WebAppNameStaging tailspin-space-game-web-staging-1234
  5. 저장을 선택하여 변수를 저장합니다.

개발 단계 추가

다음으로 빌드를 개발 단계로 승격하도록 파이프라인을 업데이트합니다.

  1. Azure Pipelines에서 Pipelines>파이프라인으로 이동합니다.

  2. 상황에 맞는 메뉴에서 편집을 선택하여 파이프라인을 편집합니다.

    편집 메뉴 항목 선택 스크린샷

  3. 개발 스테이지를 포함하도록 azure-pipelines.yml 업데이트합니다. 개발 단계에서 파이프라인은 다음을 수행합니다.

    • 조건 때문에 빌드 단계가 성공하면 실행
    • 에서 아티팩트 다운로드 drop
    • Azure Resource Manager 서비스 연결을 사용하여 Azure 앱 Service에 배포
    trigger:
    - '*'
    
    variables:
      buildConfiguration: 'Release'
      releaseBranchName: '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
      condition:  succeeded()
      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: dev website'
                inputs:
                  azureSubscription: 'your-subscription'
                  appType: 'webAppLinux'
                  appName: '$(WebAppNameDev)'
                  package: '$(Pipeline.Workspace)/drop/$(buildConfiguration)/*.zip'
    
  4. 구독을 AzureWebApp@1 사용하도록 작업을 변경합니다.

    1. 작업에 대한 설정을 선택합니다.

      YAML 편집기 작업의 설정 옵션 스크린샷

    2. 사용자 고유의 구독을 your-subscription 사용하도록 Azure 구독 의 값을 업데이트합니다. 이 프로세스의 일부로 액세스 권한을 부여해야 할 수도 있습니다. YAML 편집기 내에서 리소스에 권한을 부여하는 데 문제가 발생하는 경우 대체 방법은 서비스 연결을 만드는 것입니다.

      Azure 구독 메뉴 항목의 스크린샷.

    3. 앱 유형을 Linux의 웹앱으로 설정합니다.

    4. 추가를 선택하여 작업을 업데이트합니다.

  5. 파이프라인을 저장하고 실행합니다.

스테이징 단계 추가

마지막으로 개발 스테이지를 스테이징으로 승격합니다. 개발 환경과 달리, 수동 승인을 추가할 스테이징 환경에서 더 많은 제어를 원합니다.

스테이징 환경 만들기

  1. Azure Pipelines에서 환경을 선택합니다.

  2. 새 환경을 선택합니다.

  3. 이름 준비리소스가 없음으로 설정된 새 환경을 만듭니다.

  4. 스테이징 환경 페이지에서 승인 및 검사를 선택합니다.

    승인 및 확인 메뉴 옵션의 스크린샷

  5. 승인을 선택합니다.

  6. 승인자에서 사용자 및 그룹 추가를 선택한 다음, 계정을 선택합니다.

  7. 승인자에 대한 지침에서 준비 준비가 되면 이 변경 내용을 승인합니다.

  8. 저장을 선택합니다.

파이프라인에 새 단계 추가

수동 승인을 포함하는 파이프라인에 새 단계를 Staging 추가합니다.

  1. 파이프라인 파일을 편집하고 섹션을 추가합니다 Staging .

    trigger:
    - '*'
    
    variables:
      buildConfiguration: 'Release'
      releaseBranchName: '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
      condition:  succeeded()
      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: dev website'
                inputs:
                  azureSubscription: 'your-subscription'
                  appType: 'webAppLinux'
                  appName: '$(WebAppNameDev)'
                  package: '$(Pipeline.Workspace)/drop/$(buildConfiguration)/*.zip'
    
    - stage: 'Staging'
      displayName: 'Deploy to the staging environment'
      dependsOn: Dev
      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: staging website'
                inputs:
                  azureSubscription: 'your-subscription'
                  appType: 'webAppLinux'
                  appName: '$(WebAppNameStaging)'
                  package: '$(Pipeline.Workspace)/drop/$(buildConfiguration)/*.zip'
    
  2. 스테이 AzureWebApp@1 징 단계에서 구독을 사용하도록 작업을 변경합니다.

    1. 작업에 대한 설정을 선택합니다.

      YAML 편집기 작업의 설정 옵션 스크린샷

    2. 사용자 고유의 구독을 your-subscription 사용하도록 Azure 구독 의 값을 업데이트합니다. 이 프로세스의 일부로 액세스 권한을 부여해야 할 수도 있습니다.

      Azure 구독 메뉴 항목의 스크린샷.

    3. 앱 유형을 Linux의 웹앱으로 설정합니다.

    4. 추가를 선택하여 작업을 업데이트합니다.

  3. 파이프라인 실행으로 이동합니다. 빌드가 실행되는 것을 확인합니다. 도달 Staging하면 파이프라인은 수동 릴리스 승인을 기다립니다. 승인 보류 중인 파이프라인이 있는 전자 메일도 받게 됩니다.

    파이프라인 승인을 기다리는 스크린샷.

  4. 승인을 검토하고 파이프라인이 실행되도록 허용합니다.

    수동 유효성 검사 스크린샷

리소스 정리

이 애플리케이션을 계속 사용하지 않려면 다음 단계를 수행하여 Azure Portal의 리소스 그룹 및 Azure DevOps의 프로젝트를 삭제합니다.

리소스 그룹을 정리하려면 다음을 수행합니다.

  1. Azure Portal로 이동하고 로그인합니다.

  2. 메뉴 모음에서 Cloud Shell을 선택합니다. 프롬프트가 표시되면 Bash 환경을 선택합니다.

    Cloud Shell 메뉴 항목을 선택하는 것을 보여 주는 Azure Portal의 스크린샷

  3. 다음과 같이 az group delete 명령을 실행하여 앞서 사용한 리소스 그룹인 tailspin-space-game-rg를 삭제합니다.

    az group delete --name tailspin-space-game-rg
    

빌드 파이프라인을 포함하여 Azure DevOps 프로젝트를 삭제하려면 프로젝트 삭제를 참조하세요.