Azure Container Apps (서버리스 컨테이너)
Kubernetes 를 몰라도 컨테이너를 0 까지 줄였다 늘리며 돌리는 Azure Container Apps 의 구조(환경, 앱, 리비전, 작업), Consumption 과 워크로드 프로필, KEDA 기반 확장 규칙, 인그레스와 네트워크, 서버리스 GPU, 비용 요령을 정리합니다.
구조
| 개념 | 설명 |
|---|---|
| 환경 (Environment) | 앱들이 같이 사는 경계. VNet, 로그 대상, 워크로드 프로필을 여기서 정함 |
| 컨테이너 앱 | 하나 이상의 컨테이너로 된 서비스. 인그레스, 확장 규칙, 비밀을 가짐 |
| 리비전 | 앱 설정의 불변 스냅숏. 이미지나 템플릿이 바뀌면 새 리비전 |
| 작업 (Job) | 끝나면 멈추는 컨테이너. 수동, 일정, 이벤트로 실행 |
내부적으로는 Kubernetes, KEDA, Envoy, Dapr 를 쓰지만 사용자는 Kubernetes API 를 보지 않습니다. 그래서 AKS 보다 운영이 훨씬 가볍고, 대신 노드나 클러스터 수준 제어는 없습니다 (AKS와 비교).
요금 모델과 워크로드 프로필
환경은 워크로드 프로필 형식이 기본입니다. 한 환경 안에서 두 종류를 섞어 씁니다.
- Consumption 프로필: 서버리스. 요청이나 이벤트가 없으면 0 까지 줄고, vCPU 초, GiB 초, 요청 수로 과금합니다. 매달 무료 제공량이 있습니다.
- Dedicated 프로필: 범용, 메모리 최적화, GPU 같은 전용 노드 유형을 골라 노드 단위로 과금합니다. 큰 메모리, 꾸준한 부하, 격리가 필요할 때 씁니다.
az containerapp env create -g rg-shop-prod -n cae-shop-prod -l koreacentral \
--enable-workload-profiles --infrastructure-subnet-resource-id <subnet-id> --internal-only false
az containerapp create -g rg-shop-prod -n ca-api --environment cae-shop-prod \
--image crshopprod.azurecr.io/api:1.4.0 --registry-identity system \
--ingress external --target-port 8080 \
--min-replicas 0 --max-replicas 20 --cpu 0.5 --memory 1Gi확장 규칙
확장은 KEDA 규칙으로 정합니다. HTTP 동시 요청, TCP 연결, Service Bus 큐 길이, Event Hubs 지연, Kafka 등 KEDA 스케일러를 쓸 수 있습니다.
az containerapp update -g rg-shop-prod -n ca-worker \
--scale-rule-name orders-queue --scale-rule-type azure-servicebus \
--scale-rule-metadata queueName=orders namespace=sb-shop-prod messageCount=50 \
--scale-rule-identity systemmin-replicas 0이면 첫 요청에 콜드 스타트가 생깁니다. 지연에 민감한 API 는 최소 1로 둡니다.- 확장 규칙의 인증은 연결 문자열 대신 관리 ID(
--scale-rule-identity)를 씁니다.
리비전과 배포
- 단일 리비전 모드: 새 리비전이 준비되면 트래픽이 자동으로 넘어갑니다.
- 다중 리비전 모드: 리비전마다 트래픽 비율을 정해 카나리, 블루 그린 배포를 합니다. 레이블(
blue,green)로 리비전별 고정 주소도 만들 수 있습니다.
az containerapp revision set-mode -g rg-shop-prod -n ca-api --mode multiple
az containerapp ingress traffic set -g rg-shop-prod -n ca-api --revision-weight ca-api--v14=90 ca-api--v15=10네트워크
- 환경을 사용자 VNet 에 넣으면 앱이 VNet 안의 DB, Private Endpoint 에 닿습니다. 워크로드 프로필 환경의 인프라 서브넷은 최소
/27이고Microsoft.App/environments에 위임됩니다. 앱이 많아질 것을 생각해 넉넉히 잡습니다. - 내부 전용 환경(
--internal-only true)은 공용 인그레스 없이 VNet 안에서만 보입니다. 이때 환경 기본 도메인을 위한 Private DNS 영역을 직접 만들어야 합니다. - 앱 사이 호출은
http://ca-orders처럼 앱 이름으로 하면 환경 안에서 바로 이어집니다. - 아웃바운드 IP 를 고정하거나 방화벽을 거치려면 워크로드 프로필 환경에서 NAT Gateway 나 UDR 을 씁니다.
비밀과 ID
- 비밀은 앱 수준
secrets에 두고 환경 변수에서secretref:로 참조합니다. Key Vault 참조도 됩니다. - ACR 이미지 풀, Key Vault, 확장 규칙 모두 관리 ID 로 인증하면 비밀이 필요 없습니다.
작업 (Jobs)
배치, 데이터 처리, 큐 소비처럼 끝나는 일은 앱 대신 작업으로 만듭니다.
| 트리거 | 예 |
|---|---|
| Manual | 배포 뒤 DB 마이그레이션 한 번 |
| Schedule | 매일 새벽 집계 (CRON) |
| Event | 큐에 메시지가 쌓이면 실행 수를 늘려 처리 |
서버리스 GPU
Consumption 방식으로 GPU 를 쓰는 서버리스 GPU 는 2025-03 에 GA 가 되었습니다. 쓰지 않을 때 0 까지 줄어서 소규모 추론, 사내 모델 서빙에 맞습니다. GPU 종류와 제공 리전이 정해져 있고 GPU 할당량을 따로 요청해야 하므로, Korea Central 에서 쓸 수 있는지 먼저 확인합니다.
동적 세션
LLM 이 만든 코드를 안전하게 실행하는 격리된 샌드박스가 필요하면 동적 세션(dynamic sessions) 을 씁니다. 세션 풀을 만들어 두고 세션마다 Hyper-V 격리된 환경을 받습니다. 에이전트의 코드 실행 도구로 많이 쓰입니다.
자주 만나는 문제
| 증상 | 흔한 원인 |
|---|---|
| 리비전이 Provisioning failed | 이미지 풀 실패(ACR 권한), 대상 포트 불일치, 상태 프로브 실패 |
| 0 에서 안 늘어남 | 확장 규칙 인증 실패, 규칙 메타데이터 오타. 시스템 로그 확인 |
| VNet 안 DB 에 연결 안 됨 | DNS (Private DNS 영역이 환경 VNet 에 링크 안 됨) |
| 환경 만들기 실패 | 서브넷 크기나 위임, 서브넷에 다른 리소스 존재 |
로그는 az containerapp logs show --follow 와 Log Analytics 의 ContainerAppConsoleLogs_CL, ContainerAppSystemLogs_CL 테이블에서 봅니다.