ARM, Bicep, Terraform (코드로 배포하기)
모든 Azure 배포가 지나가는 Azure Resource Manager 의 동작, ARM 템플릿과 Bicep 의 관계, 배포 범위와 모드, what-if 와 배포 스택, Terraform AzureRM 과 AzAPI 공급자를 언제 고르는지, 상태 파일과 파이프라인 구성까지 정리합니다.
Azure Resource Manager
포털, CLI, PowerShell, SDK, Terraform 모두 결국 Azure Resource Manager(ARM) 의 REST API 를 부릅니다. 주소는 https://management.azure.com 이고, ARM 이 인증(Entra 토큰), 권한(RBAC), 정책(Azure Policy), 잠금을 확인한 뒤 각 리소스 공급자(Microsoft.Compute, Microsoft.Storage 등)에 요청을 넘깁니다.
- 이 경로를 제어 평면(control plane) 이라고 부릅니다. VM 만들기, 스토리지 계정 설정 바꾸기가 여기에 속합니다.
- Blob 읽기, Key Vault 비밀 읽기, SQL 쿼리는 각 서비스의 엔드포인트로 가는 데이터 평면(data plane) 입니다. 권한 모델도 따로 봐야 합니다.
- 리소스 공급자는 구독마다 등록되어야 합니다. 처음 쓰는 서비스에서
MissingSubscriptionRegistration이 나오면az provider register --namespace Microsoft.App처럼 등록합니다.
ARM 템플릿과 Bicep
ARM 템플릿은 JSON 으로 쓴 선언형 배포 파일입니다. Bicep 은 같은 것을 짧고 읽기 쉬운 문법으로 쓰는 언어이고, 배포할 때 ARM JSON 으로 변환됩니다. 새로 시작한다면 Bicep 을 씁니다. 새 리소스 종류와 API 버전을 출시 첫날부터 쓸 수 있고, 상태 파일이 없습니다(Azure 자체가 상태입니다).
// main.bicep: 스토리지 계정 하나
param location string = resourceGroup().location
param name string
resource st 'Microsoft.Storage/storageAccounts@2024-01-01' = {
name: name
location: location
sku: { name: 'Standard_ZRS' }
kind: 'StorageV2'
properties: {
minimumTlsVersion: 'TLS1_2'
allowBlobPublicAccess: false
publicNetworkAccess: 'Disabled'
}
}
output id string = st.id# 바뀔 내용을 먼저 보고(what-if) 배포
az deployment group what-if -g rg-shop-prod -f main.bicep -p name=stshopprod
az deployment group create -g rg-shop-prod -f main.bicep -p name=stshopprod팁 검증된 모듈이 필요하면 Microsoft 가 관리하는 Azure Verified Modules(AVM) 를 먼저 찾아봅니다. Bicep 과 Terraform 두 가지로 같은 기능의 모듈이 제공됩니다.
배포 범위와 모드
| 범위 | 명령 | 주로 만드는 것 |
|---|---|---|
| 리소스 그룹 | az deployment group create | 대부분의 리소스 |
| 구독 | az deployment sub create | 리소스 그룹, 구독 수준 정책과 역할 할당, 예산 |
| 관리 그룹 | az deployment mg create | 정책 정의, 이니셔티브, 관리 그룹 수준 할당 |
| 테넌트 | az deployment tenant create | 관리 그룹 자체 |
리소스 그룹 배포의 모드는 두 가지입니다. Incremental(기본) 은 템플릿에 있는 것만 만들거나 바꾸고 나머지는 둡니다. Complete 는 템플릿에 없는 리소스를 지웁니다. Complete 는 실수 한 번에 운영 리소스를 지울 수 있어서, 지금은 아래의 배포 스택이 더 안전한 대안입니다.
배포 스택 (Deployment stacks)
배포 스택은 "이 템플릿이 만든 리소스 묶음" 을 하나의 Azure 리소스로 관리합니다. 2024년 5월에 GA 가 되었습니다.
- 템플릿에서 빠진 리소스를 분리(detach)할지 지울지(delete) 를
--action-on-unmanage로 정합니다. --deny-settings-mode denyDelete로 스택이 만든 리소스를 포털에서 직접 지우지 못하게 막을 수 있습니다. 이는 RBAC Owner 도 막는 거부 할당(deny assignment)으로 구현됩니다.
az stack group create --name shop-core -g rg-shop-prod -f main.bicep \
--action-on-unmanage detachAll --deny-settings-mode denyDelete
Terraform 을 쓸 때
Terraform 은 여러 클라우드를 같은 도구로 다루고 싶거나 이미 팀이 익숙할 때 좋습니다. Azure 용 공급자는 두 가지입니다.
| 공급자 | 특징 |
|---|---|
azurerm | 리소스마다 사람이 다듬은 스키마. 가장 많이 씀. 4.x 부터 subscription_id 를 명시해야 함 |
azapi | ARM REST API 를 그대로 감쌈. 새 기능, Preview API 를 출시 직후 바로 쓸 수 있음 |
terraform {
backend "azurerm" {
resource_group_name = "rg-tfstate"
storage_account_name = "sttfstateprod"
container_name = "tfstate"
key = "shop/prod.tfstate"
use_azuread_auth = true
}
}
provider "azurerm" {
features {}
subscription_id = var.subscription_id
}상태 파일에는 비밀이 들어갈 수 있으므로 Blob 컨테이너는 공용 액세스를 끄고, 키 대신 Entra 인증(use_azuread_auth)을 쓰고, 버전 관리와 소프트 삭제를 켭니다. Blob 리스(lease)로 상태 잠금이 자동으로 됩니다.
파이프라인 구성 요령
- 배포 ID 는 워크로드 ID 페더레이션으로 만든 서비스 주체나 사용자 할당 관리 ID 를 씁니다. 사람 계정은 MFA 때문에 자동화에 맞지 않습니다.
- PR 에서는
what-if또는terraform plan결과를 코멘트로 남기고, 승인 뒤 같은 커밋으로 적용합니다. - 운영 구독의 배포 ID 에는 Contributor 와 필요한 범위의 역할 할당 권한만 줍니다. Owner 는 피합니다.
- 포털에서 손으로 바꾼 설정(drift)은 다음 배포 때 덮어써집니다. 긴급 수정도 코드에 반영합니다.
자주 만나는 오류
| 오류 코드 | 뜻 | 해결 |
|---|---|---|
InvalidTemplateDeployment | 사전 검증 실패. 안쪽 메시지에 진짜 원인 | details 를 끝까지 읽음. 정책 거부, 할당량이 흔함 |
RequestDisallowedByPolicy | Azure Policy 가 거부 | 어떤 정책 할당인지 메시지에 나옴. 예외(exemption) 또는 설정 수정 |
MissingSubscriptionRegistration | 리소스 공급자 미등록 | az provider register |
DeploymentQuotaExceeded | 배포 기록 800개 초과 | 오래된 배포 기록 삭제 (보통 자동 정리됨) |
AuthorizationFailed | 배포 ID 권한 부족 | AuthorizationFailed 참고 |