PF-04 · AWS · Terragrunt
AWS Terragrunt DRY IaC
Terraform 모듈 16개를 루트 설정 하나로 묶고, Terragrunt가 의존성 그래프를 읽어 순서대로 실행하게 한 구조입니다.
- 역할
- 설계 · 구현
- 기간
- 개인 프로젝트 · 2026.11 공개
- CSP
- AWS
- 규모
- 모듈 16개 · 유닛 16개 · 의존성 4단계
- 핵심 기술
- Terragrunt · Terraform · AWS
- 16
- Terraform 모듈 · 유닛
- 1
- 복사본 16개를 대체한 루트 설정
- - 40 %
- 배포 시간 단축 (실무 적용 결과)
한눈에 보기
문제
Terraform 루트마다 backend와 provider 블록을 반복해서 썼고, 루트 사이의 실행 순서는 사람이 기억해야 했습니다.
접근
모듈은 일반 Terraform으로 두고 Terragrunt로 감쌌습니다. backend, provider, 공통 inputs는 live/root.hcl 한 곳에서 생성합니다. _envcommon이 모듈 source와 dependency를 맡고, 각 유닛은 자기 inputs만 적습니다. dependency 블록으로 그래프를 만들고 mock_outputs로 클라우드 없이 전체를 검증합니다.
결과
이 레포는 모듈 16개와 유닛 16개를 의존성 4단계로 묶고, 클라우드 자격증명 없이 전체를 검증합니다. 배포 시간 40% 단축은 실제 운영 환경을 이 패턴으로 옮겼을 때 얻은 결과입니다.
자세히 보기
루트에서 생성하는 provider
이 코드가 하는 일: Terragrunt의 generate 블록이 각 유닛 폴더에 provider.tf 파일을 만들어 넣습니다. 리전은 region 설정에서, Environment 태그는 계정 이름에서 가져오고, 모든 리소스에 ManagedBy = terragrunt 태그를 자동으로 붙입니다. 마지막 줄은 계정 설정과 리전 설정의 locals를 합쳐 모든 유닛의 공통 inputs로 넘기므로, 유닛 파일에는 그 유닛에만 필요한 값만 남습니다.
generate "provider" {
path = "provider.tf"
if_exists = "overwrite_terragrunt"
contents = <<PROVIDER
provider "aws" {
region = "${local.aws_region}"
default_tags {
tags = {
Environment = "${local.account_name}"
ManagedBy = "terragrunt"
}
}
}
PROVIDER
}
inputs = merge(local.account_vars.locals, local.region_vars.locals)
dependency와 mock_outputs
이 코드가 하는 일: 이 유닛이 옆 폴더의 elastic_ip 유닛에 의존한다고 선언합니다. Terragrunt는 이 선언으로 elastic_ip를 먼저 실행하고, 그 출력(eip_id)을 이 유닛의 입력으로 넘깁니다. 아직 실제 출력이 없을 때는 mock_outputs의 가짜 ID를 쓰되 init, validate, plan 명령에서만 허용하므로, 클라우드 없이 전체를 검증할 수 있으면서도 가짜 값으로 실제 apply가 되는 일은 막습니다.
dependency "elastic_ip" {
config_path = "${get_terragrunt_dir()}/../elastic_ip"
mock_outputs = {
eip_id = {
"demo-eip-1" = "eipalloc-00000000000000001"
"demo-eip-2" = "eipalloc-00000000000000002"
}
}
mock_outputs_allowed_terraform_commands = ["init", "validate", "plan"]
}배운 점
Terragrunt는 Terraform을 대체하는 도구가 아니라 코드를 어디에 둘지 정리하는 도구라는 점이 핵심이었습니다. 모듈은 일반 Terraform으로 남기고 backend, provider, 공통 inputs는 루트 한 곳에서 만들게 하니, 같은 설정을 16번 복사하던 구조가 설정 하나를 고치면 전체에 반영되는 구조로 바뀌었습니다. 실행 순서도 dependency 블록으로 코드에 적어 두면 사람의 기억에서 그래프로 옮겨 가고, mock_outputs 덕분에 클라우드 자격증명 없이도 전체 연결을 검증할 수 있습니다. 데모에서는 state를 로컬에 두었지만 여러 사람이 함께 쓰는 환경이라면 state 위치부터 정해야 한다는 것도, 구조를 설계할 때 처음부터 고려할 부분으로 배웠습니다.