개발 팀마다 요구 사항이 다르기 때문에 클라우드 서비스에 대한 효율적인 배포 파이프라인 구현에 어려움을 겪을 수 있습니다. 이 문서에서는 Azure App Service에 배포하는 데 필요한 세 가지 주요 구성 요소, 즉 배포 원본, 빌드 파이프라인, 그리고 배포 메커니즘을 소개합니다. 이 문서는 특정 언어 스택에 대한 몇 가지 권장 사례와 유용한 팁을 담고 있습니다.
배포 구성 요소
이 섹션에서는 App Service 배포를 위한 세 가지 핵심 구성 요소에 대해 설명합니다.
배포 원본
배포 원본 은 애플리케이션 코드의 소스 위치를 의미합니다. 일반적으로 프로덕션 앱은 GitHub, BitBucket, Azure Repos와 같은 버전 제어 소프트웨어에서 관리되는 리포지토리를 배포 소스로 사용합니다. 개발 및 테스트 환경에서 배포 소스는 로컬 컴퓨터에 있는 프로젝트일 수 있습니다.
빌드 파이프라인
배포 원본이 결정되면, 다음으로 빌드 파이프라인을 선택해야 합니다. 빌드 파이프라인은 배포 소스에서 소스 코드를 가져와 여러 단계를 거쳐 애플리케이션을 실행 가능한 상태로 만듭니다.
이 단계에는 코드 컴파일, HTML 및 JavaScript 압축, 테스트 실행, 구성 요소 패키징 등이 포함될 수 있습니다. 빌드 파이프라인에서 실행되는 특정 명령어는 언어 스택에 따라 달라집니다. 이러한 작업은 Azure Pipelines와 같은 빌드 서버나 로컬 환경에서 실행할 수 있습니다.
배포 메커니즘
배포 메커니즘은 빌드된 애플리케이션을 웹앱의 /home/site/wwwroot 디렉터리에 배치하는 데 사용됩니다. /wwwroot 디렉터리는 웹앱의 모든 인스턴스에서 공유되는 탑재된 스토리지 위치입니다. 배포 메커니즘이 애플리케이션을 이 디렉터리에 배치하면 인스턴스는 새 파일을 동기화하기 위한 알림을 받게 됩니다.
App Service는 다음과 같은 배포 방식을 지원합니다.
- Kudu 엔드포인트: Kudu 는 Windows App Service에서 독립적인 프로세스로 실행되는 오픈 소스 개발자 생산성 도구입니다. Linux App Service에서 두 번째 컨테이너로 실행됩니다. Kudu는 지속적 배포를 관리하며, zipdeploy/와 같은 배포 방식에 HTTP 엔드포인트를 제공합니다.
- FTP 및 WebDeploy: 사이트 또는 사용자 인증 정보를 사용하여 Web Deploy나 FTP 를 통해 파일을 업로드할 수 있습니다. 이러한 메커니즘은 Kudu를 통하지 않습니다.
이러한 배포 메커니즘은 Azure Pipelines, Jenkins, 편집기 플러그인과 같은 배포 도구에서 활용됩니다.
배포 슬롯 사용
새 프로덕션 빌드를 배포할 때는 가능한 한 배포 슬롯을 사용하는 것이 좋습니다. 표준 App Service 플랜 이상의 계층을 사용하는 경우, 스테이징 환경에 앱을 배포하여 변경 사항의 유효성을 검사하고 스모크 테스트를 수행할 수 있습니다. 준비가 되었다면 스테이징 슬롯과 프로덕션 슬롯을 교환하세요. 교환 작업을 수행하면 프로덕션 규모와 일치하도록 하는 데 필요한 작업자 인스턴스가 발생하므로 가동 중지 시간을 없앨 수 있습니다.
연속 배포 코드
프로젝트에 테스트, QA 및 스테이징을 위한 지정된 브랜치가 있는 경우, 각 브랜치를 스테이징 슬롯에 지속적으로 배포하는 것이 좋습니다. 이 방법을 사용하면 이해 관계자가 배포된 분기를 쉽게 평가하고 테스트할 수 있습니다. 분기 전략에 대한 자세한 내용은 트렁크 기반 개발 또는 Git 워크플로 비교를 참조하세요.
프로덕션 슬롯에 대해 연속 배포를 사용하도록 설정하면 안 됩니다. 대신 프로덕션 분기(주로 주 분기)를 비프로덕션 슬롯에 배포해야 합니다. 기본 분기를 릴리스할 준비가 완료되면 프로덕션 슬롯으로 교체합니다. 프로덕션에 배포하는 대신 프로덕션 슬롯으로 스왑하면 가동 중지 시간을 방지할 수 있고, 변경 사항을 롤백해야 할 때 다시 스왑하여 롤백할 수 있습니다.
지속적으로 컨테이너 배포
Docker 또는 다른 컨테이너 레지스트리의 사용자 지정 컨테이너에 대해 이미지를 스테이징 슬롯에 배포하고 프로덕션으로 교환하여 가동 중지 시간을 방지합니다. 자동화는 단순한 코드 배포 이상의 복잡성을 가지고 있습니다. 컨테이너 레지스트리에 이미지를 푸시한 다음, 웹앱에서 해당 이미지 태그를 업데이트해야 합니다.
슬롯 배포를 위한 각 분기별 자동화 설정을 통해, 분기에 커밋이 발생할 때마다 다음 작업을 실행합니다.
- 이미지 빌드 및 태그 지정. 빌드 파이프라인에서 Git 커밋 ID, 타임스탬프 또는 기타 식별 가능한 정보로 이미지에 태그를 지정합니다. 기본적으로 최신 태그를 사용하지 않는 것이 좋습니다. 그렇지 않으면 현재 배포된 코드를 추적하기 어려워 디버깅이 더 힘들어집니다.
- 태그가 지정된 이미지를 푸시합니다. 이미지가 빌드되어 태그가 지정되면 파이프라인이 컨테이너 레지스트리에 이미지를 푸시합니다. 다음 단계에서 배포 슬롯은 컨테이너 레지스트리에서 태그된 이미지를 가져오게 됩니다.
- 새로운 이미지 태그를 사용해서 배포 슬롯을 업데이트합니다. 이 속성이 업데이트되면 사이트가 자동으로 재시작되면서 새로운 컨테이너 이미지를 가져옵니다.
이 문서는 일반적인 자동화 프레임워크에 대한 예시를 담고 있습니다.
Azure DevOps 사용
App Service에는 배포 센터를 통해 컨테이너에 대한 지속적인 업데이트 기능이 기본적으로 포함되어 있습니다. Azure Portal에서 해당 앱으로 이동합니다. 배포 아래에서 배포 센터를 선택합니다. 지침에 따라 리포지토리와 분기를 선택합니다. 이 방식은 DevOps 빌드 및 릴리스 파이프라인을 설정하여 새 커밋이 특정 분기로 푸시될 때 컨테이너를 자동으로 빌드, 태깅 및 배포하도록 합니다.
GitHub Actions 사용
GitHub Actions를 사용하여 컨테이너 배포를 자동화할 수도 있습니다. 워크플로 파일은 컨테이너를 빌드하고, 커밋 ID 태그를 적용하여 컨테이너 레지스트리에 푸시한 다음, 지정된 Web App을 새로운 이미지 태그로 업데이트합니다.
on:
push:
branches:
- <your-branch-name>
name: Linux_Container_Node_Workflow
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
# checkout the repo
- name: 'Checkout GitHub Action'
uses: actions/checkout@main
- uses: azure/docker-login@v1
with:
login-server: contoso.azurecr.io
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- run: |
docker build . -t contoso.azurecr.io/nodejssampleapp:${{ github.sha }}
docker push contoso.azurecr.io/nodejssampleapp:${{ github.sha }}
- uses: azure/webapps-deploy@v2
with:
app-name: 'node-rnc'
publish-profile: ${{ secrets.azureWebAppPublishProfile }}
images: 'contoso.azurecr.io/nodejssampleapp:${{ github.sha }}'
다른 자동화 공급자 사용
앞서 나열된 단계들은 CircleCI나 Travis CI와 같은 다른 자동화 도구에도 적용할 수 있습니다. 하지만 마지막 단계에서는 새 이미지 태그를 사용하여 배포 슬롯을 업데이트해야 하므로 Azure CLI를 사용해야 합니다. 자동화 스크립트에서 Azure CLI를 사용하기 위해 다음 명령으로 서비스 주체를 생성합니다.
az ad sp create-for-rbac --name "myServicePrincipal" --role contributor \
--scopes /subscriptions/{subscription}/resourceGroups/{resource-group} \
--sdk-auth
스크립트에서 보안 주체 정보를 제공하고 az login --service-principal로 로그인을 진행합니다. 그런 다음 az webapp config container set 를 이용하여 컨테이너 이름, 태그, 레지스트리 URL, 레지스트리 비밀번호 등을 설정할 수 있습니다. 자세한 내용은 Circle CI에서 Azure CLI에 로그인하는 방법을 참조하세요.
언어별 고려 사항
Java, Node, .NET 구현 시 다음 사항에 유의하세요.
자바
Kudu zipdeploy API를 사용하여 JAR 형식의 애플리케이션을 배포합니다. WAR 앱에 wardeploy를 사용합니다. Jenkins를 사용하는 경우 배포 과정에서 해당 API를 직접 사용할 수 있습니다. 자세한 내용은 Jenkins로 Azure App Service에 앱 배포를 참조하세요.
노드
일반적으로 Kudu는 노드 애플리케이션(npm install)에 대한 빌드 단계를 수행합니다. Azure DevOps와 같은 빌드 서비스를 사용한다면 Kudu 빌드는 불필요합니다. Kudu 빌드를 사용하지 않도록 설정하려면 SCM_DO_BUILD_DURING_DEPLOYMENT의 값 false을 갖는 앱 설정을 만드세요.
닷넷
Kudu는 기본적으로 .NET 애플리케이션(dotnet build)에 대한 빌드 단계를 수행합니다. Azure DevOps와 같은 빌드 서비스를 사용한다면 Kudu 빌드는 불필요합니다. Kudu 빌드를 사용하지 않도록 설정하려면 SCM_DO_BUILD_DURING_DEPLOYMENT의 값 false을 갖는 앱 설정을 만드세요.
기타 배포 고려 사항
이 외에 로컬 캐시, CPU 사용률 또는 메모리 사용량이 높은 경우도 고려해야 합니다.
로컬 캐시
Azure App Service의 콘텐츠는 Azure Storage에 저장되며, 영구적인 방식으로 콘텐츠 공유를 제공합니다. 그러나 몇몇 앱들은 고가용성 환경에서 실행 가능한 고성능 읽기 전용 콘텐츠 스토리지를 필요로 합니다. 이러한 앱은 로컬 캐시를 활용할 수 있다는 장점이 있습니다. 자세한 내용은 Azure App Service 로컬 캐시를 참조하세요.
참고
WordPress와 같은 콘텐츠 관리 시스템에서는 로컬 캐시 사용이 권장되지 않습니다.
가동 중단 시간을 최소화하려면 배포 슬롯과 로컬 캐시를 함께 사용하는 것이 좋습니다. 이러한 기능들을 함께 사용하는 방법에 대한 자세한 내용은 모범 사례를 참조하세요.
높은 CPU 또는 메모리
App Service 요금제에서 사용 가능한 CPU나 메모리를 90% 이상 사용하면, 기본 가상 머신이 배포를 처리하는 데 어려움을 겪을 수 있습니다. 이러한 상황이 발생했을 때는 배포를 위해 인스턴스 수를 일시적으로 확장합니다. 인스턴스 수는 배포 완료 후 이전 값으로 반환할 수 있습니다.
더 자세한 정보는 App Service Diagnostics 에서 리소스와 관련된 실행 가능한 모범 사례를 확인하여 알아보세요.
Azure Portal에서 해당 웹앱으로 이동합니다.
App Service 진단은 왼쪽 탐색 창에서 진단을 선택하여 문제 해결을 시작하면 이용할 수 있습니다.
가용성, 성능 중 하나를 선택하거나, 높은 CPU 분석과 같은 다른 옵션을 탐색합니다.
이러한 모범 사례에 따라 앱의 현재 상태를 확인합니다.
이 링크를 통해 리소스에 대한 App Service 진단을 바로 열 수도 있습니다: https://portal.azure.com/?websitesextension_ext=asd.featurePath%3Ddetectors%2FParentAvailabilityAndPerformance#@microsoft.onmicrosoft.com/resource/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Web/sites/{siteName}/troubleshoot.