본문으로 건너뛰기
azure검색
기초

ARM, Bicep, Terraform (코드로 배포하기)

모든 Azure 배포가 지나가는 Azure Resource Manager 의 동작, ARM 템플릿과 Bicep 의 관계, 배포 범위와 모드, what-if 와 배포 스택, Terraform AzureRM 과 AzAPI 공급자를 언제 고르는지, 상태 파일과 파이프라인 구성까지 정리합니다.

ARMBicepTerraformIaC배포 스택what-if2026-10 기준, 약 7분상태 표시 설명

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 를 명시해야 함
azapiARM 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)로 상태 잠금이 자동으로 됩니다.

파이프라인 구성 요령

  1. 배포 ID 는 워크로드 ID 페더레이션으로 만든 서비스 주체나 사용자 할당 관리 ID 를 씁니다. 사람 계정은 MFA 때문에 자동화에 맞지 않습니다.
  2. PR 에서는 what-if 또는 terraform plan 결과를 코멘트로 남기고, 승인 뒤 같은 커밋으로 적용합니다.
  3. 운영 구독의 배포 ID 에는 Contributor 와 필요한 범위의 역할 할당 권한만 줍니다. Owner 는 피합니다.
  4. 포털에서 손으로 바꾼 설정(drift)은 다음 배포 때 덮어써집니다. 긴급 수정도 코드에 반영합니다.

자주 만나는 오류

오류 코드뜻해결
InvalidTemplateDeployment사전 검증 실패. 안쪽 메시지에 진짜 원인details 를 끝까지 읽음. 정책 거부, 할당량이 흔함
RequestDisallowedByPolicyAzure Policy 가 거부어떤 정책 할당인지 메시지에 나옴. 예외(exemption) 또는 설정 수정
MissingSubscriptionRegistration리소스 공급자 미등록az provider register
DeploymentQuotaExceeded배포 기록 800개 초과오래된 배포 기록 삭제 (보통 자동 정리됨)
AuthorizationFailed배포 ID 권한 부족AuthorizationFailed 참고

공식 문서

이 문서에서