대규모 Terraform + 고급 개념
Source: Dev.to
🎯 Lab Goal
다음과 같은 모듈형 Terraform 프로젝트를 구축합니다:
- IAM 사용자와 EC2 생성
for_each,count,zipmap사용- 라이프사이클 규칙 시연
- 의존성 처리 표시
- 스케일 관행 시뮬레이션
- 타깃팅 및 리프레시 제어 사용
🧱 STEP 1 — 프로젝트 구조 (스케일링 모범 사례)
terraform-scale-lab/
│
├── iam/
│ └── main.tf
│
├── ec2/
│ └── main.tf
│
├── shared/
│ └── variables.tf
│
└── root/
└── main.tf
✅ 이것은 다음을 시뮬레이션합니다:
- 모듈로 분리된 대규모 인프라
- API 호출 감소
- 실제 기업에서 사용됨
🧩 STEP 2 — 공유 변수 (Object + Map + Set)
📄 shared/variables.tf
variable "users" {
type = set(string)
default = ["alice", "bob", "john"]
}
variable "amis" {
type = map(string)
default = {
dev = "ami-123456"
prod = "ami-654321"
}
}
variable "instance_config" {
type = object({
instance_type = string
count = number
})
default = {
instance_type = "t2.micro"
count = 2
}
}
✅ 포함 내용:
setmapobject
👤 STEP 3 — IAM 모듈 (for_each + zipmap)
📄 iam/main.tf
# Create IAM users using for_each
resource "aws_iam_user" "users" {
for_each = var.users
name = each.value
}
# Output names
output "user_names" {
value = [for u in aws_iam_user.users : u.name]
}
# Output ARNs
output "user_arns" {
value = [for u in aws_iam_user.users : u.arn]
}
# ✅ zipmap usage (IMPORTANT FOR EXAM)
output "user_map" {
value = zipmap(
[for u in aws_iam_user.users : u.name],
[for u in aws_iam_user.users : u.arn]
)
}
✅ 방금 구현한 내용:
for_each- 스플랫 대안 (for 루프)
zipmap()
🖥️ STEP 4 — EC2 모듈 (count + lifecycle + depends_on)
📄 ec2/main.tf
# Security group
resource "aws_security_group" "web" {
name = "web-sg"
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
# EC2 instances using count
resource "aws_instance" "web" {
count = var.instance_config.count
ami = var.amis["dev"]
instance_type = var.instance_config.instance_type
vpc_security_group_ids = [aws_security_group.web.id]
tags = {
Name = "web-${count.index}"
}
# ✅ lifecycle rules
lifecycle {
create_before_destroy = true
ignore_changes = [tags]
}
}
✅ 당신이 다룬 내용:
countlifecycle- 암시적 의존성 (SG → EC2)
🔗 STEP 5 — 루트 모듈 (모두 연결)
📄 root/main.tf
provider "aws" {
region = "us-east-1"
}
# 공유 변수 가져오기
module "iam" {
source = "../iam"
users = var.users
}
module "ec2" {
source = "../ec2"
amis = var.amis
instance_config = var.instance_config
# 명시적 의존성 예시
depends_on = [module.iam]
}
🧪 단계 6 — 초기화 및 실행
cd root
terraform init
terraform plan
terraform apply
🚨 STEP 7 — API 스로틀링 시뮬레이션
이제 대규모 인프라 동작을 시뮬레이션합니다:
terraform plan
👉 Terraform은 다음을 수행합니다:
- ALL 리소스를 새로 고침
- AWS API를 여러 번 호출합니다
⚡ STEP 8 — SOLUTION 1: TARGETING
terraform apply -target=module.ec2
✅ EC2만 실행 → API 호출 감소
⚡ STEP 9 — SOLUTION 2: DISABLE REFRESH
terraform plan -refresh=false
✅ API 호출을 건너뜁니다
⚠️ 상태가 신뢰할 수 있을 때만 사용하세요
⚡ STEP 10 — 테스트 수명 주기 (IMPORTANT)
- AWS 콘솔에서 태그를 수동으로 변경합니다:
Env = production추가. - 실행합니다:
terraform apply
👉 Terraform은 제거하지 않을 것입니다 왜냐하면:
ignore_changes = [tags]
⚡ STEP 11 — create_before_destroy 테스트
- AMI를 변경합니다:
ami = "new-ami-id"
- 실행합니다:
terraform apply
👉 Terraform:
- 새 인스턴스를 먼저 생성합니다
- 그런 다음 기존 인스턴스를 삭제합니다
✅ 다운타임 없음
⚡ STEP 12 — 의존성 테스트
ec2모듈에서depends_on을 제거하고 순서를 확인합니다.- 다시 추가합니다:
depends_on = [module.iam]
👉 IAM 생성이 먼저 이루어지도록 강제합니다.
⚡ STEP 13 — 주석 연습
모든 주석 유형을 추가하세요:
# Single line comment
// Another comment
/*
Multi-line comment
for disabling resources
*/
🧠 STEP 14 — count vs for_each TEST
IAM을 count를 사용하도록 변경 (잘못된 관행 테스트):
count = 3
name = "user-${count.index}"
👉 그런 다음 리스트 순서를 바꾸면 → 리소스가 다시 생성됩니다.
✅ 이것은 for_each가 더 나은 이유를 보여줍니다.
🎯 최종
방금 다음을 연습했습니다:
- 스케일링 및 API 고려 사항
- Terraform refresh가 스로틀링을 일으킬 수 있는 방법
- 프로젝트를 모듈로 분할하기
-target및-refresh=false를 책임감 있게 사용하기- 라이프사이클 규칙, 종속성 및 주석 스타일
행복한 Terraforming!
함수 및 타입
zipmap()map,set,object
리소스 동작
수명 주기
ignore_changescreate_before_destroyprevent_destroy(concept)
종속성
- 암시적 vs 명시적
반복
count(위험)for_each(프로덕션 안전)
Q: Terraform이 API 스로틀링을 일으키는 이유는?
A: 모든 plan은 상태 새로 고침을 수행하기 때문에, 클라우드 제공자의 API를 관리되는 모든 리소스에 대해 호출합니다. 대규모 인프라에서는 이로 인해 제공자의 속도 제한을 초과하여 스로틀링이 발생할 수 있습니다.
