이 게시물은 다음의 개념을 실제로 적용하는 데 도움이 되는 네 가지 튜토리얼 중 하나입니다. 마이크로서비스 2023년 3월: 마이크로서비스 제공 시작하기:
- 마이크로서비스를 배포하고 구성하는 방법
- 컨테이너에서 보안 비밀을 안전하게 관리하는 방법
- GitHub Actions를 사용하여 마이크로서비스 카나리 릴리스를 자동화하는 방법(이 게시물)
- OpenTelemetry 트레이싱을 사용하여 마이크로서비스를 이해하는 방법
대부분의 프로젝트가 성공하려면 배포 자동화가 매우 중요합니다. 하지만 단순히 코드를 배포하는 것만으로는 충분하지 않습니다. 다운타임을 최소화하거나 없애야 하며, 장애가 발생했을 때 신속하게 롤백할 수 있어야 합니다. 카나리 배포와 블루-그린 배포를 결합하는 것은 새 코드의 안정성을 확인하는 일반적인 접근 방식입니다. 이 전략은 다음 두 단계로 구성됩니다:
- 1단계: 카나리 배포를 통해 격리된 환경에서 테스트 – 코드를 현재 환경 외부의 격리된 노드, 서버 또는 컨테이너에 배포하고, 코드가 의도한 대로 작동하는지 테스트합니다.
- 2단계: 프로덕션 환경에서 테스트하기 위한 블루-그린 배포 – 카나리 배포에서 코드가 정상적으로 작동한다고 가정하고, 프로덕션 환경에서 현재 버전용 서버와 함께 새로 생성한 서버(또는 노드나 컨테이너)에 코드를 배포합니다. 그런 다음 프로덕션 트래픽의 일부를 새 버전으로 전환하여 부하가 더 높은 상황에서도 계속 원활하게 작동하는지 테스트합니다. 일반적으로 처음에는 소량의 트래픽(예: 10%)을 새 버전으로 보내고, 새 버전이 모든 트래픽을 처리할 때까지 점진적으로 비율을 높입니다. 증가 폭은 새 버전의 트래픽 처리 능력을 얼마나 확신하는지에 따라 달라지며, 한 번에 새 버전으로 완전히 전환할 수도 있습니다.
앱 또는 웹사이트의 서로 다른 버전 간에 트래픽을 분산하는 다양한 사용 사례(트래픽 분할)가 익숙하지 않다면, 블로그의 「고급 트래픽 관리로 Kubernetes의 복원력을 향상하는 방법」을 읽고 블루-그린 배포, 카나리 릴리스, A/B 테스트, 속도 제한, 서킷 브레이킹 등의 개념을 이해해 보세요. 이 블로그 글은 Kubernetes를 중심으로 설명하지만, 이러한 개념은 마이크로서비스 앱에도 폭넓게 적용됩니다.
튜토리얼 개요
이 튜토리얼에서는 GitHub Actions를 사용하여 카나리 블루-그린 배포의 첫 번째 단계를 자동화하는 방법을 보여 줍니다. 튜토리얼의 네 가지 과제에서는 Microsoft Azure Container Apps를 사용하여 애플리케이션의 새 버전을 배포한 다음, Azure Traffic Manager를 사용하여 기존 환경의 트래픽을 새 환경으로 전환합니다:
- NGINX 컨테이너 앱 만들기 및 배포
- Azure Container App 배포 자동화를 위한 권한 설정
- GitHub Action을 사용하여 카나리 블루-그린 배포 만들기
- GitHub Actions 워크플로 테스트
참고: 이 자습서에서는 Azure Container Apps를 사용하지만, 여기서 다루는 개념과 기법은 모든 클라우드 기반 호스트에 적용할 수 있습니다.
사전 요구 사항 및 설정
사전 요구 사항
자체 환경에서 이 튜토리얼을 진행하려면 다음이 필요합니다:
- An Azure 계정이 필요합니다. 조직 계정을 사용하면 권한 문제가 발생할 수 있으므로 조직에 연결되지 않은 계정을 사용하는 것이 좋습니다.
- The Azure CLI.
- 브라우저 기반 GitHub GUI 대신(또는 이와 함께) GitHub CLI를 사용하려는 경우.
설정
필요한 기본 리소스를 만들고 구성합니다. 튜토리얼용 리포지토리를 포크하고 복제한 다음, Azure CLI에 로그인하고 Azure Container Apps용 확장을 설치합니다.
- 홈 디렉터리에 microservices-march 디렉터리를 만듭니다. (다른 디렉터리 이름을 사용하고 그에 맞게 지침을 조정해도 됩니다.) 참고: 명령을 터미널에 더 쉽게 복사하여 붙여넣을 수 있도록 이 튜토리얼 전체에서 Linux 명령줄 프롬프트는 생략합니다.
mkdir ~/microservices-marchcd ~/microservices-march- Fork and clone the Microservices March 플랫폼 저장소를 개인 GitHub 계정으로 포크한 후, GitHub CLI 또는 GUI를 사용하여 클론합니다.
- GitHub GUI를 사용하는 경우:
- 창 오른쪽 상단에서 Fork를 클릭하고 Owner 메뉴에서 개인 GitHub 계정을 선택합니다.

- 리포지토리를 로컬에 복제합니다. 이때
<your_GitHub_account>를 본인의 계정 이름으로 바꿉니다:
- 창 오른쪽 상단에서 Fork를 클릭하고 Owner 메뉴에서 개인 GitHub 계정을 선택합니다.
- GitHub GUI를 사용하는 경우:
git clone https://github.com/<your_GitHub_account>/platform.gitcd platform- GitHub CLI를 사용하는 경우 다음을 실행합니다:
gh repo fork microservices-march/platform -–clone- Azure CLI에 로그인합니다. 안내에 따라 브라우저를 사용하여 로그인하세요:
az login
[
{
"cloudName": "AzureCloud",
"homeTenantId": "cfd11e0f-1435-450s-bdr1-ffab73b4er8e",
"id": "60efapl2-38ad-41w8-g49a-0ecc6723l97c",
"isDefault": true,
"managedByTenants": [],
"name": "Azure subscription 1",
"state": "Enabled",
"tenantId": "cfda3e0f-14g5-4e05-bfb1-ffab73b4fsde",
"user": {
"name": "user@example.com",
"type": "user"
}
}
]- Install the
containerapp확장을 설치합니다:
az extension add --name containerapp -upgradeThe installed extension 'containerapp' is in preview.과제 1: NGINX 컨테이너 앱 만들기 및 배포
이 첫 번째 과제에서는 카나리아 블루-그린 배포의 기준으로 사용할 애플리케이션의 초기 버전으로 NGINX Azure Container App을 만듭니다. Azure Container Apps는 컨테이너로 패키징된 애플리케이션 코드를 프로덕션 환경에 적합한 컨테이너 환경에서 손쉽게 실행할 수 있도록 지원하는 Microsoft Azure 서비스입니다.
- 컨테이너 앱을 위한 Azure 리소스 그룹을 만듭니다:
az group create --name my-container-app-rg --location westus{
"id": "/subscriptions/0efafl2-38ad-41w8-g49a-0ecc6723l97c/resourceGroups/my-container-app-rg",
"location: "westus",
"managedBy": null,
"name": "my-container-app-rg",
"properties": {
"provisioningState": "Succeeded"
},
"tags": null,
"type": "Microsoft.Resources/resourceGroups"
}- 컨테이너를 Azure Container Apps에 배포합니다(이 단계는 다소 시간이 걸릴 수 있습니다).
az containerapp up --resource-group my-container-app-rg --name my-container-app --source ./ingress --ingress external --target-port 80 --location westus
...
- image:
registry: cac085021b77acr.azurecr.io
repository: my-container-app
tag: "20230315212413756768"
digest: sha256:90a9fc67c409e244195ec0ea190ce3b84195ae725392e8451...
runtime-dependency:
registry: registry.hub.docker.com
repository: library/nginx
tag: "1.23"
digest: sha256:aa0afebbb3cfa473099a62c4b32e9b3fb73ed23f2a75a65ce...
git: {}
Run ID: cf1 was successful after 27s
Creating Containerapp my-container-app in resource group my-container-app-rg
Adding registry password as a secret with name "ca2ffbce7810acrazurecrio-cac085021b77acr"
Container app created. Access your app at https://my-container-app.delightfulmoss-eb6d59d5.westus.azurecontainerapps.io/
...- 2단계의 출력에서 Azure Container Registry(ACR)에 생성한 컨테이너 앱의 이름과 URL을 찾습니다. 샘플 출력에서는 주황색으로 강조 표시되어 있습니다. 이 자습서 전반의 명령에서 표시된 변수 대신 출력에 나온 값(2단계의 샘플 출력과는 다름)을 사용합니다:
- 컨테이너 앱 이름 –
image.registry키에서.azurecr.io앞에 있는 문자열입니다. 2단계의 샘플 출력에서는cac085021b77acr입니다. 이후 명령에서<ACR_name>을 이 문자열로 바꾸세요. - 컨테이너 앱의 URL –
Containerappcreated로 시작하는 줄에 있는 URL입니다. 2단계의 샘플 출력에서는https://my-container-app.delightfulmoss-eb6d59d5.westus.azurecontainerapps.io/입니다. 이후 명령에서<ACR_URL>을 이 URL로 바꾸세요.
- 컨테이너 앱 이름 –
- 블루-그린 배포에 필요한 컨테이너 앱의 리비전을 사용하도록 설정합니다:
az containerapp revision set-mode --name my-container-app --resource-group my-container-app-rg --mode multiple
"Multiple"- (선택 사항) 컨테이너의 /health 엔드포인트를 쿼리하여 배포가 정상적으로 작동하는지 테스트합니다:
curl <ACR_URL>/healthOK과제 2: Azure Container App 배포 자동화를 위한 권한 설정
이 챌린지에서는 Azure 컨테이너 앱 배포를 자동화할 수 있는 JSON 토큰을 획득합니다.
먼저 Azure Container Registry(ACR)의 ID를 가져온 다음, Azure 관리 ID의 보안 주체 ID를 가져옵니다. 그런 다음 ACR용 기본 제공 Azure 역할을 관리 ID에 할당하고, 컨테이너 앱에서 관리 ID를 사용하도록 구성합니다. 마지막으로 관리 ID의 JSON 자격 증명을 가져옵니다. 이 자격 증명은 GitHub Actions에서 Azure에 인증하는 데 사용됩니다.
이 일련의 단계가 번거롭게 느껴질 수 있지만, 새 애플리케이션을 만들 때 한 번만 수행하면 되며 전체 프로세스를 스크립트로 자동화할 수 있습니다. 이 자습서에서는 이러한 단계에 익숙해질 수 있도록 수동으로 수행합니다.
참고: 이 배포용 자격 증명 생성 절차는 Azure에만 해당합니다.
- 관리 ID의 보안 주체 ID를 확인합니다. 이 ID는 출력의
PrincipalID열에 표시됩니다(가독성을 위해 두 줄로 나뉘어 표시됨). 3단계에서 이 값을<managed_identity_principal_ID>대신 입력합니다:
az containerapp identity assign --name my-container-app --resource-group my-container-app-rg --system-assigned --output table
PrincipalId ...
------------------------------------ ...
39f8434b-12d6-4735-81d8-ba0apo14579f ...
... TenantId
... ------------------------------------
... cfda3e0f-14g5-4e05-bfb1-ffab73b4fsde- ACR에서 컨테이너 앱의 리소스 ID를 조회합니다. 이때
<ACR_name>을 챌린지 1의 3단계에서 기록한 이름으로 바꿉니다. 다음 단계에서는 이 값을<ACR_resource_ID>대신 사용합니다:
az acr show --name <ACR_name> --query id --output tsv/subscriptions/60efafl2-38ad-41w8-g49a-0ecc6723l97c/resourceGroups/my-container-app-rg/providers/Microsoft.ContainerRegistry/registries/cac085021b77acr- ACR용 기본 제공 Azure 역할을 컨테이너 앱의 관리 ID에 할당합니다. 이때
<managed_identity_principal_ID>을 1단계에서 얻은 관리 ID로 바꾸고,<ACR_resource_ID>를 2단계에서 얻은 리소스 ID로 바꿉니다:
az role assignment create --assignee <managed_identity_principal_ID> --role AcrPull --scope <ACR_resource_ID>
{
"condition": null,
"conditionVersion": null,
"createdBy": null,
"createdOn": "2023-03-15T20:28:40.831224+00:00",
"delegatedManagedIdentityResourceId": null,
"description": null,
"id": "/subscriptions/0efafl2-38ad-41w8-g49a-0ecc6723l97c/resourceGroups/my-container-app-rg/providers/Microsoft.ContainerRegistry/registries/cac085021b77acr/providers/Microsoft.Authorization/roleAssignments/f0773943-8769-44c6-a820-ed16007ff249",
"name": "f0773943-8769-44c6-a820-ed16007ff249",
"principalId": "39f8ee4b-6fd6-47b5-89d8-ba0a4314579f",
"principalType": "ServicePrincipal",
"resourceGroup": "my-container-app-rg",
"roleDefinitionId": "/subscriptions/60e32142-384b-43r8-9329-0ecc67dca94c/providers/Microsoft.Authorization/roleDefinitions/7fd21dda-4fd3-4610-a1ca-43po272d538d",
"scope": "/subscriptions/ 0efafl2-38ad-41w8-g49a-0ecc6723l97c/resourceGroups/my-container-app-rg/providers/Microsoft.ContainerRegistry/registries/cac085021b77acr",
"type": "Microsoft.Authorization/roleAssignments",
"updatedBy": "d4e122d6-5e64-4bg1-9cld-2aceeb0oi24d",
"updatedOn": "2023-03-15T20:28:41.127243+00:00"
}- ACR에서 이미지를 가져올 때 관리 ID를 사용하도록 컨테이너 앱을 구성합니다. 이때
<ACR_name>을(를) 과제 1의 3단계에서 기록한 컨테이너 앱 이름(위의 2단계에서도 사용한 이름)으로 바꿉니다:
az containerapp registry set --name my-container-app --resource-group my-container-app-rg --server <ACR_name>.azurecr.io --identity system
[
{
"identity": "system",
"passwordSecretRef": "",
"server": "cac085021b77acr.azurecr.io",
"username": ""
}
]- Look up your Azure 구독 ID를 확인합니다.
az account show --query id --output tsv0efafl2-38ad-41w8-g49a-0ecc6723l97c- GitHub Action에서 사용할 자격 증명이 포함된 JSON 토큰을 생성합니다. 이때
<subscription_ID>을 Azure 구독 ID로 바꿉니다. 출력 결과를 저장한 후AZURE_CREDENTIALS라는 비밀 값으로 GitHub 리포지토리에 비밀 추가에서 붙여넣습니다.--sdk-auth가 더 이상 사용되지 않는다는 경고는 무시해도 됩니다. 이는 알려진 문제입니다:
az ad sp create-for-rbac --name my-container-app-rbac --role contributor --scopes /subscriptions/<subscription_ID>/resourceGroups/my-container-app-rg --sdk-auth --output json
Option '--sdk-auth' has been deprecated and will be removed in a future release.
...
{
"clientId": "0732444d-23e6-47fb-8c2c-74bddfc7d2er",
"clientSecret": "qg88Q~KJaND4JTWRPOLWgCY1ZmZwN5MK3N.wwcOe",
"subscriptionId": "0efafl2-38ad-41w8-g49a-0ecc6723l97c",
"tenantId": "cfda3e0f-14g5-4e05-bfb1-ffab73b4fsde",
"activeDirectoryEndpointUrl": "https://login.microsoftonline.com",
"resourceManagerEndpointUrl": "https://management.azure.com/",
"activeDirectoryGraphResourceId": "https://graph.windows.net/",
"sqlManagementEndpointUrl": "https://management.core.windows.net:8443/",
"galleryEndpointUrl": "https://gallery.azure.com/",
"managementEndpointUrl": "https://management.core.windows.net/"
}과제 3: 카나리 블루-그린 배포 GitHub Action 만들기
이 챌린지에서는 GitHub Action 워크플로에서 민감한 데이터를 관리하는 데 사용되는 보안 비밀을 추가하고, GitHub 리포지토리에 Action 워크플로 파일을 생성한 다음, Action 워크플로를 실행합니다.
보안 비밀 관리에 대한 자세한 소개는 블로그의 Microservices March 23 두 번째 튜토리얼인 컨테이너에서 보안 비밀을 안전하게 관리하는 방법을 참조하세요.
GitHub 리포지토리에 보안 비밀 추가
애플리케이션의 새 버전을 배포하려면 설정에서 포크한 GitHub 리포지토리에 일련의 비밀을 생성해야 합니다. 이러한 비밀에는 과제 2에서 생성한 관리 ID의 JSON 자격 증명과 새 버전의 NGINX 이미지를 Azure에 배포하는 데 필요한 몇 가지 민감한 배포별 매개 변수가 포함됩니다. 다음 섹션에서는 GitHub Action에서 이러한 비밀을 사용하여 카나리 블루-그린 배포를 자동화합니다.
- GitHub GUI를 사용하는 경우:
- 포크한 GitHub 리포지토리로 이동합니다.
- Select Settings > Secrets and variables > Actions을 선택합니다.
- Click 새 리포지토리 비밀을 클릭합니다.
- 표시된 필드에 다음 값을 입력합니다:
- 이름 –
AZURE_CREDENTIALS - 비밀 – 과제 2의 6단계에서 가져온 JSON 자격 증명
- 이름 –
- Click 비밀 추가를 클릭합니다.
- 3~5단계를 세 번 반복하여 표에 나열된 비밀을 만듭니다. 비밀 이름 및 비밀 값 열의 값을 GUI의 이름 및 비밀 필드에 각각 입력합니다. 세 번째 비밀의 경우
<ACR_name>을(를) 과제 1의 3단계에서 기록한 컨테이너 앱에 할당된 이름으로 바꿉니다. 비밀 이름 비밀 값CONTAINER_APP_NAMEmy-container-appRESOURCE_GROUPmy-container-app-rgACR_NAME<ACR_name> - 다음으로 이동합니다. GitHub Actions 워크플로 파일 만들기.
- GitHub CLI를 사용하는 경우:
- 리포지토리의 루트에 임시 파일을 만듭니다.
touch ~/creds.json- 선호하는 텍스트 편집기를 사용하여 creds.json 파일을 열고 챌린지 2의 6단계에서 생성한 JSON 자격 증명을 복사해 넣습니다.
- 시크릿을 생성합니다:
gh secret set AZURE_CREDENTIALS --repo <your_GitHub_account>/platform < ~/creds.json- 삭제하세요: creds.json:
rm ~/creds.json- 이 명령을 반복하여 시크릿을 세 개 더 생성합니다:
gh secret set <secret_name> --repo <your_GitHub_account>/platform- 반복할 때마다
<secret_name>을(를) 표의 비밀 이름 열에 있는 값 중 하나로 바꿉니다. 프롬프트가 표시되면 비밀 값 열의 해당 값을 붙여넣습니다. 세 번째 비밀의 경우<ACR_name>을(를) 과제 1의 3단계에서 기록한 컨테이너 앱에 할당된 이름으로 바꿉니다. 비밀 이름 비밀 값CONTAINER_APP_NAMEmy-container-appRESOURCE_GROUPmy-container-app-rgACR_NAME<ACR_name>
GitHub Actions 워크플로 파일 만들기
관리 ID와 비밀을 설정했으면 카나리 블루-그린 배포를 자동화하는 GitHub Action 워크플로 파일을 만들 수 있습니다.
참고: 워크플로 파일은 공백이 중요한 YAML 형식으로 정의됩니다. 아래 단계에 표시된 들여쓰기를 그대로 유지해야 합니다.
- Action 워크플로용 파일을 만듭니다.
- GitHub GUI를 사용하는 경우:
- GitHub 리포지토리로 이동합니다.
- Select Actions > New workflow > Skip this and set up a workflow yourself을 선택합니다.
- GitHub CLI를 사용하는 경우 .github/workflows 디렉터리를 만들고 main.yml이라는 새 파일을 만듭니다:
- GitHub GUI를 사용하는 경우:
mkdir .github/workflowstouch .github/workflows/main.yml- 선호하는 텍스트 편집기를 사용하여 워크플로의 내용을 main.yml에 추가합니다. 가장 쉬운 방법은 전체 워크플로 파일에 표시된 내용을 복사하여 붙여 넣는 것입니다. 또는 이 단계에 설명된 코드 조각을 차례로 추가하여 파일을 직접 만들 수도 있습니다. 참고: 워크플로 파일은 공백이 중요한 YAML 형식으로 정의됩니다. 코드 조각을 복사하여 붙여 넣을 때는 들여쓰기를 그대로 유지해야 합니다. 확실히 하려면 작성한 파일을 전체 워크플로 파일과 비교하세요.
- 워크플로의 이름을 정의합니다:
name: Deploy to Azure- main 브랜치에 푸시하거나 풀 리퀘스트를 생성할 때 워크플로가 실행되도록 구성합니다:
on:
push:
branches:
- main
pull_request:
branches:
- main- In the
jobs섹션에서 코드를 체크아웃하고 Azure에 로그인한 후 애플리케이션을 Azure Container App에 배포하는build-deploy작업을 정의합니다:
jobs:
build-deploy:
runs-on: ubuntu-22.04
steps:
- name: Check out the codebase
uses: actions/checkout@v3
- name: Log in to Azure
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Build and deploy Container App
run: |
# Add the containerapp extension manually
az extension add --name containerapp --upgrade
# Use Azure CLI to deploy update
az containerapp up -n ${{ secrets.CONTAINER_APP_NAME }}
-g ${{ secrets.RESOURCE_GROUP }}
--source ${{ github.workspace }}/ingress
--registry-server ${{ secrets.ACR_NAME }}.azurecr.io- 새로 배포된 리비전의 스테이징 URL을 가져오고 GitHub Action을 사용하여 API 엔드포인트
test-deployment작업을 정의합니다. 이 작업은 /health에 요청을 보내 새 리비전이 응답하는지 확인합니다. 상태 확인에 성공하면 컨테이너 앱의 Azure Traffic Manager가 모든 트래픽을 새로 배포된 컨테이너로 보내도록 업데이트됩니다. 참고:test-deployment키는 이전 항목에서 정의한build-deploy키와 동일한 수준으로 들여쓰기해야 합니다.
test-deployment:
needs: build-deploy
runs-on: ubuntu-22.04
steps:
- name: Log in to Azure
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Get new container name
run: |
# Add the containerapp extension manually
az extension add --name containerapp --upgrade
# Get the last deployed revision name
REVISION_NAME=`az containerapp revision list -n ${{ secrets.CONTAINER_APP_NAME }} -g ${{ secrets.RESOURCE_GROUP }} --query "[].name" -o tsv | tail -1`
# Get the last deployed revision's fqdn
REVISION_FQDN=`az containerapp revision show -n ${{ secrets.CONTAINER_APP_NAME }} -g ${{ secrets.RESOURCE_GROUP }} --revision "$REVISION_NAME" --query properties.fqdn -o tsv`
# Store values in env vars
echo "REVISION_NAME=$REVISION_NAME" >> $GITHUB_ENV
echo "REVISION_FQDN=$REVISION_FQDN" >> $GITHUB_ENV
- name: Test deployment
id: test-deployment
uses: jtalk/url-health-check-action@v3 # Marketplace action to touch the endpoint
with:
url: "https://${{ env.REVISION_FQDN }}/health" # Staging endpoint
- name: Deploy succeeded
run: |
echo "Deployment succeeded! Enabling new revision"
az containerapp ingress traffic set -n ${{ secrets.CONTAINER_APP_NAME }} -g ${{ secrets.RESOURCE_GROUP }} --revision-weight "${{ env.REVISION_NAME }}=100"전체 워크플로 파일
다음은 Action 워크플로 파일의 전체 내용입니다.
name: Deploy to Azure
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
build-deploy:
runs-on: ubuntu-22.04
steps:
- name: Check out the codebase
uses: actions/checkout@v3
- name: Log in to Azure
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Build and deploy Container
run: |
# Add the containerapp extension manually
az extension add --name containerapp -upgrade
# Use Azure CLI to deploy update
az containerapp up -n ${{ secrets.CONTAINER_APP_NAME }}
-g ${{ secrets.RESOURCE_GROUP }}
--source ${{ github.workspace }}/ingress
--registry-server ${{ secrets.ACR_NAME }}.azurecr.io
test-deployment:
needs: build-deploy
runs-on: ubuntu-22.04
steps:
- name: Log in to Azure
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Get new container name
run: |
# Install the containerapp extension for the Azure CLI
az extension add --name containerapp --upgrade
# Get the last deployed revision name
REVISION_NAME=`az containerapp revision list -n ${{ secrets.CONTAINER_APP_NAME }} -g ${{ secrets.RESOURCE_GROUP }} --query "[].name" -o tsv | tail -1`
# Get the last deployed revision's fqdn
REVISION_FQDN=`az containerapp revision show -n ${{ secrets.CONTAINER_APP_NAME }} -g ${{ secrets.RESOURCE_GROUP }} --revision "$REVISION_NAME" --query properties.fqdn -o tsv`
# Store values in env vars
echo "REVISION_NAME=$REVISION_NAME" >> $GITHUB_ENV
echo "REVISION_FQDN=$REVISION_FQDN" >> $GITHUB_ENV
- name: Test deployment
id: test-deployment
uses: jtalk/url-health-check-action@v3 # Marketplace action to touch the endpoint
with:
url: "https://${{ env.REVISION_FQDN }}/health" # Staging endpoint
- name: Deploy succeeded
run: |
echo "Deployment succeeded! Enabling new revision"
az containerapp ingress traffic set -n ${{ secrets.CONTAINER_APP_NAME }} -g ${{ secrets.RESOURCE_GROUP }} --revision-weight "${{ env.REVISION_NAME }}=100"액션 워크플로 실행
- GitHub GUI를 사용하는 경우:
- Click 커밋 시작을 클릭하고 원하는 경우 커밋 메시지를 추가한 다음, 대화 상자에서 새 파일 커밋을 선택합니다. 새 워크플로 파일이 기본 브랜치에 병합되고 실행되기 시작합니다.
- 워크플로의 진행 상황을 모니터링하려면 Actions를 클릭합니다.
- GitHub CLI를 사용하는 경우:
- Add main.yml을 Git 스테이징 영역에 추가합니다:
git add .github/workflows/main.yml- 파일을 커밋합니다:
git commit -m "feat: create GitHub Actions workflow"- 변경 사항을 GitHub에 푸시합니다:
git push- 워크플로의 진행 상황을 모니터링합니다:
gh workflow view main.yml --repo <your_GitHub_account>/platform과제 4: GitHub Actions 워크플로 테스트
이 챌린지에서는 워크플로를 테스트합니다. 먼저 Ingress 부하 분산 장치가 성공적으로 업데이트되는 상황을 시뮬레이션하고 애플리케이션이 업데이트되었는지 확인합니다. 그런 다음 업데이트가 실패하여 내부 서버 오류가 발생하는 상황을 시뮬레이션하고 게시된 애플리케이션이 변경되지 않았는지 확인합니다.
업데이트를 성공적으로 수행하기
업데이트를 성공적으로 수행하고 워크플로가 성공하는지 확인하세요.
- GitHub GUI를 사용하는 경우:
- Select Code > ingress > default.conf.template을 선택합니다.
- 도구 설명이 default.conf.template인 연필 아이콘을 선택하여 이 파일 편집을 엽니다.
- 파일 끝부분에 있는
location/health블록에서 다음과 같이return지시문을 변경합니다:
location /health {
access_log off;
return 200 "Successful Update!n";
}- 대화 상자에서 이 커밋에 대한 새 브랜치를 만들고 풀 리퀘스트 시작을 선택한 다음 변경 사항 제안을 선택합니다.
- 풀 리퀘스트 템플릿에 액세스하려면 Create pull request를 클릭합니다.
- Click Create pull request을 다시 클릭하여 풀 리퀘스트를 생성합니다.
- Click Actions를 클릭하여 워크플로의 진행 상황을 모니터링합니다.
- 워크플로가 완료되면 다음 주소에서 컨테이너 앱으로 이동합니다. <ACR_URL>/health 여기서 <ACR_URL>은 챌린지 1의 3단계에서 기록해 둔 URL입니다.
SuccessfulUpdate!메시지가 표시되는지 확인합니다. - 터미널 세션을 시작하고 앱에 상태 확인 요청을 보내 메시지를 확인할 수 있습니다. 이때
<ACR_URL>을(를) 과제 1의 3단계에서 기록한 값으로 다시 바꾸세요:
curl <ACR_URL>/healthSuccessful Update!- 다음으로 이동합니다: 실패하는 업데이트 수행하기.
- GitHub CLI를 사용하는 경우:
- 다음 이름의 새 브랜치를 만듭니다. patch-1:
git checkout -b patch-1- 선호하는 텍스트 편집기에서 ingress/default.conf.template 파일을 열고, 파일 끝부분에 있는
location/health블록에서 다음과 같이return지시문을 변경합니다:
location /health {
access_log off;
return 200 "Successful Update!n";
}- Git 스테이징 영역에 default.conf.template을 추가합니다:
git add ingress/default.conf.template- 파일을 커밋합니다:
git commit -m "feat: update NGINX ingress"- 변경 사항을 GitHub에 푸시합니다:
git push --set-upstream origin patch-1- 풀 리퀘스트(PR)를 생성합니다:
gh pr create --head patch-1 --fill --repo <your_GitHub_account>/platform- 워크플로의 진행 상황을 모니터링합니다:
gh workflow view main.yml --repo <your_GitHub_account>/platform- 워크플로가 완료되면 앱에 상태 확인 요청을 보냅니다. 이때
<ACR_URL>을(를) 챌린지 1의 3단계에서 기록한 값으로 바꿉니다:
curl <ACR_URL>/health
Successful Update!실패하는 업데이트 수행
이제 실패하는 업데이트를 생성하고 워크플로가 실패하는 과정을 확인합니다. 기본적으로 업데이트 성공시키기의 단계를 반복하되, return 지시문의 값을 다르게 설정하면 됩니다.
- GitHub GUI를 사용하는 경우:
location /health {
access_log off;
return 500 "Unsuccessful Update!n";
}- Select -patch-1 브랜치에 직접 커밋을 선택한 다음 변경 사항 커밋을 선택합니다.
- 워크플로의 진행 상황을 모니터링하려면 Actions를 선택합니다. PR의 파일이 업데이트되면 워크플로가 다시 실행됩니다.
- 워크플로가 완료되면 컨테이너 앱의 <ACR_URL>/health 엔드포인트로 이동합니다. 여기서 <ACR_URL>은(는) 과제 1의 3단계에서 기록한 URL입니다. 메시지가
SuccessfulUpdate!(이전 업데이트가 성공한 후와 동일함)로 표시되는지 확인합니다. 모순처럼 보일 수 있지만, 이는 실제로 이번 업데이트가 실패했음을 나타냅니다. 업데이트 시도 결과 상태 코드가500(즉,InternalServerError)이었으므로 업데이트가 적용되지 않았습니다. - 터미널 세션을 시작하고 앱에 상태 확인 요청을 보내 메시지를 확인할 수 있습니다. 이때도
<ACR_URL>을(를) 과제 1의 3단계에서 기록한 값으로 바꾸세요:
curl <ACR_URL>/healthSuccessful Update!- GitHub CLI를 사용하는 경우:
- 다음 브랜치를 체크아웃합니다: patch-1. 이 브랜치는 이전 섹션에서 생성했습니다.
git checkout patch-1- 선호하는 텍스트 편집기에서 ingress/default.conf.template 파일을 열고, 다음과 같이
return지시문을 다시 변경합니다:
location /health {
access_log off;
return 500 "Unsuccessful Update!n";
}- Git 스테이징 영역에 default.conf.template을 추가합니다:
git add ingress/default.conf.template- 파일을 커밋합니다:
git commit -m "feat: update NGINX ingress again"- 변경 사항을 GitHub에 푸시합니다:
git push- 워크플로의 진행 상황을 모니터링합니다:
gh workflow view main.yml --repo <your_GitHub_account>/platform- 워크플로가 완료되면 앱에 상태 확인 요청을 보내고,
<ACR_URL>을 챌린지 1의 3단계에서 기록한 값으로 바꿉니다:
curl <ACR_URL>/healthSuccessful Update!- 메시지가
SuccessfulUpdate!(성공했던 이전 업데이트 후와 동일)로 표시되는 것이 모순처럼 보일 수 있습니다. 하지만 이는 실제로 이번 업데이트가 실패했음을 보여 줍니다. 업데이트 시도 결과 상태 코드가500(InternalServerError를 의미)으로 반환되어 적용되지 않았습니다.
리소스 정리
향후 요금이 발생할 가능성을 방지하려면 튜토리얼에서 배포한 Azure 리소스를 삭제하는 것이 좋습니다:
az group delete -n my-container-app-rg -y원하는 경우 생성한 포크도 삭제할 수 있습니다.
- GitHub GUI를 사용하는 경우:
- Click 설정을 클릭합니다.
- 페이지 맨 아래까지 스크롤합니다.
- Click 이 리포지토리 삭제를 클릭합니다.
- 입력: <your_GitHub_account>/platform을 입력하고 결과를 이해했으며 이 리포지토리를 삭제합니다를 선택합니다.
- GitHub CLI를 사용하는 경우:
gh repo delete <your_GitHub_account>/platform -yes다음 단계
축하합니다! GitHub Actions를 사용하여 마이크로서비스 앱을 카나리아 방식으로 블루-그린 배포하는 방법을 배웠습니다. DevOps에 대해 계속 알아보고 지식을 넓히려면 GitHub 문서의 다음 글을 확인해 보세요:
카나리 배포의 두 번째 단계(프로덕션 환경에서 테스트)를 시도할 준비가 되었다면 Microservices March 2022의 튜토리얼인 카나리 배포로 가동 시간과 복원력 향상을 블로그에서 확인해 보세요. 이 튜토리얼에서는 NGINX Service Mesh를 사용하여 새 앱 버전으로 점진적으로 전환합니다. 아직 서비스 메시가 필요할 만큼 배포가 복잡하지 않거나 Kubernetes를 사용하지 않더라도, 이러한 원칙은 Ingress 컨트롤러나 로드 밸런서만 사용하는 더 간단한 배포에도 적용됩니다.
마이크로서비스에 대해 계속 학습하려면 Microservices March 2023을 확인해 보세요. 유닛 3: 자동화로 마이크로서비스 배포 가속화에서는 배포 자동화에 대해 자세히 알아볼 수 있습니다.

관련 블로그 게시물
시청하기: KubeCon North America 2023에서의 NGINX Gateway Fabric
이 영상에서는 KubeCon의 NGINX 부스를 찾아가, 저희가 공개한 Kubernetes Gateway API 구현을 살펴봅니다.
F5 NGINX로 대규모 WAF 플릿을 확인하고 관리하는 2가지 방법
앱 보안을 강화하는 두 가지 방법을 소개합니다. NGINX Management Suite를 통해 WAF 운영에 대한 가시성을 높이고, NGINX App Protect WAF를 활용해 코드형 보안을 구현하는 것입니다.
Ingress 컨트롤러 선택 가이드, 4부: NGINX Ingress Controller 옵션
개발 주체, 개발 철학, 프로덕션 환경 준비도, 보안 및 지원을 기준으로 어떤 NGINX Ingress 컨트롤러가 가장 적합한지 알아보세요.
진화하는 공격 환경에 NGINX App Protect Denial of Service가 적응하는 방법
NGINX App Protect Denial of Service(DoS)가 계층 7 DoS 공격을 방어하기 위해 완화 방법을 실시간으로 조정하는 방식을 설명합니다. 정상적인 사용자 행동과 서버 상태에 대한 모델을 생성하여 공격을 나타내는 이상 징후를 감지하고 맞춤형 완화 시그니처를 적용할 수 있습니다.
NGINX Instance Manager를 활용한 대규모 구성 업데이트 및 인증서 관리
NGINX Instance Manager 버전 1.0에는 두 가지 새로운 기능이 도입되었습니다. NGINX 인스턴스에 태그와 사용자 역할을 지정하면 전체 그룹에 구성을 한 번에 적용할 수 있습니다. 인증서 검사는 만료 예정인 인증서를 감지하여 서비스 중단을 방지할 수 있도록 인증서를 교체할 수 있게 해줍니다.
Netflix가 자사 CDN의 핵심으로 NGINX를 선택한 이유
Netflix가 글로벌 콘텐츠 전송 네트워크인 Open Connect의 스트리밍 미디어 기술로 NGINX를 선택한 이유를 NGINX 개발자 Gleb Smirnoff에게서 알아보세요.