연습 - 웹 애플리케이션 배포
토이 회사에서 웹 사이트 개발 팀은 최신 버전의 웹 사이트를 Git 리포지토리에 커밋했습니다. 이제 파이프라인을 업데이트하여 웹 사이트를 빌드하고 Azure App Service에 배포할 준비가 되었습니다.
이 프로세스에서는 다음 작업을 수행합니다.
- 빌드 작업에 대한 새 파이프라인 템플릿을 추가합니다.
- 빌드 작업을 포함하도록 파이프라인을 업데이트합니다.
- 새 스모크 테스트를 추가합니다.
- 배포 단계를 업데이트하여 애플리케이션을 배포합니다.
- 파이프라인을 실행합니다.
빌드 작업에 대한 파이프라인 템플릿 추가
웹 사이트 애플리케이션을 빌드하는 데 필요한 단계를 포함하는 새 작업 정의를 추가합니다.
Visual Studio Code를 엽니다.
deploy/pipeline-templates 폴더에서 build.yml 새 파일을 만듭니다.
build.yml 파이프라인 템플릿 파일에 다음 콘텐츠를 추가합니다.
jobs: - job: Build displayName: Build application and database pool: vmImage: windows-latest steps: # Build, copy, and publish the website. - task: DotNetCoreCLI@2 displayName: Build publishable website inputs: command: 'publish' publishWebProjects: true - task: CopyFiles@2 displayName: Copy publishable website inputs: sourceFolder: '$(Build.SourcesDirectory)/src/ToyCompany/ToyCompany.Website/bin' contents: '**/publish.zip' targetFolder: '$(Build.ArtifactStagingDirectory)/website' flattenFolders: true - task: PublishBuildArtifacts@1 displayName: Publish website as pipeline artifact inputs: pathToPublish: '$(Build.ArtifactStagingDirectory)/website' artifactName: 'website'
작업은 빌드 단계를 실행하여 웹 사이트 애플리케이션의 소스 코드를 Azure에서 실행할 준비가 된 컴파일된 파일로 전환합니다. 그런 다음, 컴파일된 아티팩트를 임시 스테이징 폴더에 복사하고 파이프라인 아티팩트로 게시합니다.
파일의 변경 내용을 저장합니다.
첫 번째 파이프라인 단계의 이름을 바꾸고 빌드 작업 추가
배포 폴더에서 azure-pipelines.yml 파일을 엽니다.
Lint 단계를 수정합니다. 이름을 빌드로 바꾸고 만든 build.yml 파이프라인 템플릿을 사용하는 빌드 작업을 추가합니다.
trigger: batch: true branches: include: - main pool: vmImage: ubuntu-latest stages: - stage: Build jobs: # Build the Visual Studio solution. - template: pipeline-templates/build.yml # Lint the Bicep file. - template: pipeline-templates/lint.yml # Deploy to the test environment. - template: pipeline-templates/deploy.yml parameters: environmentType: Test # Deploy to the production environment. - template: pipeline-templates/deploy.yml parameters: environmentType: Production
파일의 변경 내용을 저장합니다.
스모크 테스트 파일 업데이트
웹 사이트 개발자는 웹 사이트에 모니터링용 엔드포인트를 추가했습니다. 이 엔드포인트는 웹 사이트가 온라인 상태이고 데이터베이스에 연결할 수 있는지 확인합니다. 여기서는 배포 파이프라인에서 상태 검사를 호출하는 새 스모크 테스트를 추가합니다.
‘deploy’ 폴더에서 ‘Website.Tests.ps1’ 파일을 엽니다.
상태 검사를 호출하는 새 테스트 사례를 추가합니다. 응답 코드가 200이 아니면 테스트 사례가 실패합니다. 이는 성공을 나타냅니다.
param( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string] $HostName ) Describe 'Toy Website' { It 'Serves pages over HTTPS' { $request = [System.Net.WebRequest]::Create("https://$HostName/") $request.AllowAutoRedirect = $false $request.GetResponse().StatusCode | Should -Be 200 -Because "the website requires HTTPS" } It 'Does not serves pages over HTTP' { $request = [System.Net.WebRequest]::Create("http://$HostName/") $request.AllowAutoRedirect = $false $request.GetResponse().StatusCode | Should -BeGreaterOrEqual 300 -Because "HTTP is not secure" } It 'Returns a success code from the health check endpoint' { $response = Invoke-WebRequest -Uri "https://$HostName/health" -SkipHttpErrorCheck Write-Host $response.Content $response.StatusCode | Should -Be 200 -Because "the website and configuration should be healthy" } }
파일의 변경 내용을 저장합니다.
Bicep 파일에 출력 추가
Azure App Service에 웹 사이트를 게시하는 배포 단계를 추가하려고 하지만 게시 단계에는 App Service 앱의 이름이 필요합니다. 여기서는 앱 이름을 Bicep 파일의 출력으로 노출합니다.
‘deploy’ 폴더에서 ‘main.bicep’ 파일을 엽니다.
파일 내용의 끝에 App Service 앱의 이름을 출력으로 추가합니다.
output appServiceAppName string = appServiceApp.name output appServiceAppHostName string = appServiceApp.properties.defaultHostName
파일의 변경 내용을 저장합니다.
배포 단계 업데이트
deploy/pipeline-templates 폴더에서 deploy.yml 파일을 엽니다.
배포 단계의 배포 작업 정의에서(59줄 근처) Windows 호스팅 에이전트 풀을 사용하도록 작업을 구성합니다.
- stage: Deploy_${{parameters.environmentType}} displayName: Deploy (${{parameters.environmentType}} Environment) jobs: - deployment: DeployWebsite displayName: Deploy website pool: vmImage: windows-latest variables: - group: ToyWebsite${{parameters.environmentType}} environment: ${{parameters.environmentType}} strategy:
데이터베이스 작업을 위해 나중에 추가한 파이프라인 단계 중 일부는 Windows 운영 체제를 실행해야 합니다. 파이프라인의 다른 작업에 서로 다른 에이전트 풀을 사용할 수 있으므로 다른 작업은 계속해서 Ubuntu Linux 파이프라인 에이전트 풀을 사용합니다.
배포 작업의 SaveDeploymentOutputs 단계에서 Bicep 배포 출력의 앱 이름 값을 사용하여 새 파이프라인 변수를 추가합니다.
- bash: | echo "##vso[task.setvariable variable=appServiceAppName]$(echo $DEPLOYMENT_OUTPUTS | jq -r '.appServiceAppName.value')" echo "##vso[task.setvariable variable=appServiceAppHostName;isOutput=true]$(echo $DEPLOYMENT_OUTPUTS | jq -r '.appServiceAppHostName.value')" name: SaveDeploymentOutputs displayName: Save deployment outputs into variables env: DEPLOYMENT_OUTPUTS: $(deploymentOutputs)
appServiceAppHostName
변수는 스모크 테스트 단계에서 사용되므로 해당 변수에는isOutput=true
속성이 적용되어 있음을 주의하세요. 변수는appServiceAppName
동일한 파이프라인 단계 및 작업에서 설정되고 사용됩니다. 따라서 설정이isOutput=true
필요하지 않습니다.작업 콘텐츠 배포 가 끝나면 Azure App Service에 앱을 배포하는 새 단계를 추가합니다.
steps: - checkout: self - task: AzureResourceManagerTemplateDeployment@3 name: DeployBicepFile displayName: Deploy Bicep file inputs: connectedServiceName: ToyWebsite${{parameters.environmentType}} deploymentName: $(Build.BuildNumber) location: ${{parameters.deploymentDefaultLocation}} resourceGroupName: $(ResourceGroupName) csmFile: deploy/main.bicep overrideParameters: > -environmentType $(EnvironmentType) -reviewApiUrl $(ReviewApiUrl) -reviewApiKey $(ReviewApiKey) deploymentOutputs: deploymentOutputs - bash: | echo "##vso[task.setvariable variable=appServiceAppName]$(echo $DEPLOYMENT_OUTPUTS | jq -r '.appServiceAppName.value')" echo "##vso[task.setvariable variable=appServiceAppHostName;isOutput=true]$(echo $DEPLOYMENT_OUTPUTS | jq -r '.appServiceAppHostName.value')" name: SaveDeploymentOutputs displayName: Save deployment outputs into variables env: DEPLOYMENT_OUTPUTS: $(deploymentOutputs) - task: AzureRmWebAppDeployment@4 name: DeployWebsiteApp displayName: Deploy website inputs: appType: webApp ConnectionType: AzureRM azureSubscription: ToyWebsite${{parameters.environmentType}} ResourceGroupName: $(ResourceGroupName) WebAppName: $(appServiceAppName) Package: '$(Pipeline.Workspace)/website/publish.zip'
비고
주의할 점은 YAML 파일의 들여쓰기로, 새 배포 단계의 들여쓰기가
DeployBicepFile
단계와 동일한 수준에 위치하도록 해야 합니다. 확실하지 않은 경우 다음 단계의 예제에서 전체 ‘deploy.yml’ 파일 내용을 복사합니다.파이프라인 정의에서 아티팩트를 명시적으로 다운로드하지 않았음을 주의하십시오. 배포 작업을 사용하므로 Azure Pipelines는 자동으로 아티팩트를 다운로드합니다.
deploy.yml 파일 내용을 확인하고 변경 내용을 커밋합니다.
deploy.yml 파일이 다음 예제와 같이 표시되는지 확인합니다.
parameters: - name: environmentType type: string - name: deploymentDefaultLocation type: string default: westus3 stages: - ${{ if ne(parameters.environmentType, 'Production') }}: - stage: Validate_${{parameters.environmentType}} displayName: Validate (${{parameters.environmentType}} Environment) jobs: - job: ValidateBicepCode displayName: Validate Bicep code variables: - group: ToyWebsite${{parameters.environmentType}} steps: - task: AzureResourceManagerTemplateDeployment@3 name: RunPreflightValidation displayName: Run preflight validation inputs: connectedServiceName: ToyWebsite${{parameters.environmentType}} location: ${{parameters.deploymentDefaultLocation}} deploymentMode: Validation resourceGroupName: $(ResourceGroupName) csmFile: deploy/main.bicep overrideParameters: > -environmentType $(EnvironmentType) -reviewApiUrl $(ReviewApiUrl) -reviewApiKey $(ReviewApiKey) - ${{ if eq(parameters.environmentType, 'Production') }}: - stage: Preview_${{parameters.environmentType}} displayName: Preview (${{parameters.environmentType}} Environment) jobs: - job: PreviewAzureChanges displayName: Preview Azure changes variables: - group: ToyWebsite${{parameters.environmentType}} steps: - task: AzureCLI@2 name: RunWhatIf displayName: Run what-if inputs: azureSubscription: ToyWebsite${{parameters.environmentType}} scriptType: 'bash' scriptLocation: 'inlineScript' inlineScript: | az deployment group what-if \ --resource-group $(ResourceGroupName) \ --template-file deploy/main.bicep \ --parameters environmentType=$(EnvironmentType) \ reviewApiUrl=$(ReviewApiUrl) \ reviewApiKey=$(ReviewApiKey) - stage: Deploy_${{parameters.environmentType}} displayName: Deploy (${{parameters.environmentType}} Environment) jobs: - deployment: DeployWebsite displayName: Deploy website pool: vmImage: windows-latest variables: - group: ToyWebsite${{parameters.environmentType}} environment: ${{parameters.environmentType}} strategy: runOnce: deploy: steps: - checkout: self - task: AzureResourceManagerTemplateDeployment@3 name: DeployBicepFile displayName: Deploy Bicep file inputs: connectedServiceName: ToyWebsite${{parameters.environmentType}} deploymentName: $(Build.BuildNumber) location: ${{parameters.deploymentDefaultLocation}} resourceGroupName: $(ResourceGroupName) csmFile: deploy/main.bicep overrideParameters: > -environmentType $(EnvironmentType) -reviewApiUrl $(ReviewApiUrl) -reviewApiKey $(ReviewApiKey) deploymentOutputs: deploymentOutputs - bash: | echo "##vso[task.setvariable variable=appServiceAppName]$(echo $DEPLOYMENT_OUTPUTS | jq -r '.appServiceAppName.value')" echo "##vso[task.setvariable variable=appServiceAppHostName;isOutput=true]$(echo $DEPLOYMENT_OUTPUTS | jq -r '.appServiceAppHostName.value')" name: SaveDeploymentOutputs displayName: Save deployment outputs into variables env: DEPLOYMENT_OUTPUTS: $(deploymentOutputs) - task: AzureRmWebAppDeployment@4 name: DeployWebsiteApp displayName: Deploy website inputs: appType: webApp ConnectionType: AzureRM azureSubscription: ToyWebsite${{parameters.environmentType}} ResourceGroupName: $(ResourceGroupName) WebAppName: $(appServiceAppName) Package: '$(Pipeline.Workspace)/website/publish.zip' - stage: SmokeTest_${{parameters.environmentType}} displayName: Smoke Test (${{parameters.environmentType}} Environment) jobs: - job: SmokeTest displayName: Smoke test variables: appServiceAppHostName: $[ stageDependencies.Deploy_${{parameters.environmentType}}.DeployWebsite.outputs['DeployWebsite.SaveDeploymentOutputs.appServiceAppHostName'] ] steps: - task: PowerShell@2 name: RunSmokeTests displayName: Run smoke tests inputs: targetType: inline script: | $container = New-PesterContainer ` -Path 'deploy/Website.Tests.ps1' ` -Data @{ HostName = '$(appServiceAppHostName)' } Invoke-Pester ` -Container $container ` -CI - task: PublishTestResults@2 name: PublishTestResults displayName: Publish test results condition: always() inputs: testResultsFormat: NUnit testResultsFiles: 'testResults.xml'
파일의 변경 내용을 저장합니다.
Visual Studio Code 터미널에서 다음 명령을 실행하여 변경 내용을 커밋하고 Git 리포지토리에 푸시합니다.
git add . git commit -m "Build and deploy website application" git push
파이프라인 실행
브라우저에서 Pipelines로 이동합니다.
가장 최근에 실행된 파이프라인을 선택하십시오.
빌드 단계가 성공적으로 완료될 때까지 기다립니다.
파이프라인은 유효성 검사(테스트 환경) 단계를 실행하기 전에 일시 중지됩니다. 파이프라인은 스테이지가 참조하는 변수 그룹을 사용할 수 있는 권한이 필요하기 때문입니다. 이 프로젝트에서 파이프라인을 처음으로 실행하므로 변수 그룹에 대한 파이프라인의 액세스를 승인해야 합니다. 파이프라인을 다시 실행하면 동일한 변수 그룹에 대한 액세스를 승인할 필요가 없습니다.
보기를 선택합니다.
허용을 선택합니다.
허용을 선택합니다.
유효성 검사(테스트 환경) 단계가 성공적으로 완료됩니다.
파이프라인이 계속되고 배포(테스트 환경) 단계가 성공적으로 완료됩니다. 파이프라인은 스모크 테스트(테스트 환경) 단계를 실행하지만 스모크 테스트 단계는 실패합니다.
스모크 테스트(테스트 환경) 단계를 선택하여 파이프라인 로그를 엽니다.
스모크 테스트 실행 단계를 선택하여 파이프라인 로그의 연결된 섹션을 봅니다.
파이프라인 로그에는 상태 검사 응답이 포함됩니다. 응답은 애플리케이션이 Azure SQL Database와 통신하는 데 문제가 있음을 나타냅니다. 데이터베이스가 아직 배포되거나 구성되지 않았기 때문에 웹 사이트에서 액세스할 수 없습니다. 다음 연습에서는 이 구성 문제를 해결합니다.