개요
이 포스팅은 "Terraform으로 시작하는 IaC"라는 책을 보고 정리한 내용입니다.
https://ebook-product.kyobobook.co.kr/dig/epd/ebook/E000008932854
테라폼으로 시작하는 IaC | 김민수
국내 유일 테라폼 집필서! 생성형 AI 활용으로 더 쉽고 강력해진 인프라 운영 『테라폼으로 시작하는 IaC』초판은 탄탄한 구성과 풍부한 예제를 갖춘 국내 유일한 테라폼 집필서로 각종 기업이나
ebook-product.kyobobook.co.kr
Terraform 모듈
테라폼으로 관리하는 인프라의 규모가 커지고 복잡해질수록 관리를 쉽게 하기 위해 모듈 기능을 활용할 수 있습니다.
모듈을 사용할 때는 다음과 같은 암묵적인 규칙이 존재합니다.
- 모듈 디렉토리는 "terraform-<프로바이더>-<모듈>" 형식을 사용합니다.
- 각 모듈은 독립적으로 관리합니다.
- 테라폼 레지스트리 모듈을 참고하여 작성하는 것이 좋습니다.

모듈은 기본적으로 입력 변수를 구성하고 결과를 출력하는 구조로 이루어져 있습니다.

자식 모듈 작성
random 프로바이더를 활용하여 랜덤으로 이름과 비밀번호를 설정해주는 자식 모듈을 만들어봅시다.
디렉토리 구조는 다음과 같습니다.
.
├── modules
│ └── terraform-module-pwgen
│ ├── main.tf
│ ├── output.tf
│ └── variable.tf
└── test
└── main.tf
terraform-modue-pwgen이라는 자식 모듈이 존재하고 test/main.tf이라는 루트 모듈에서 자식 모듈을 사용하는 구조입니다.
자식 모듈에서 사용하는 입력 변수를 정의해봅시다.
<modules/terraform-module-pwgen/variable.tf>
variable "isDB"{
type = bool
default = false
}
이 값은 terraform을 실행할 때 입력하는 값입니다.
자식 모듈에서 반환하는 output를 정의해봅시다.
<modules/terraform-module-pwgen/output.tf>
output "id"{
value = random_pet.name.id
}
output "password"{
value = nonsensitive(random_password.password.result)
}
랜덤으로 생성된 아이디와 비밀번호를 출력합니다.
모듈의 main.tf를 작성합시다.
<modules/terraform-module-pwgen/main.tf>
resource "random_pet" "name"{
keepers = {
ami_id = timestamp()
}
}
resource "random_password" "password"{
length = var.isDB ? 16 : 10
special = var.isDB ? true : false
override_special = "!#$%*?"
}
keepers는 trigger로 값이 변경될 때마다 랜덤 이름을 생성하도록 합니다.
ami_id가 시간이기 때문에 terraform apply 명령어를 입력할 때마다 바뀌게 되고 매번 다른 이름이 생성되게 됩니다.
override_special의 경우 랜덤 생성할 때 사용할 특수문자를 지정할 수 있습니다.
비밀번호를 사용할 때 다음과 같이 구분자와 혼동을 일으킬 수 있기 때문에 override_special을 사용합니다.
mysql://user:pass@word@host:3306/db
지금까지 자식 모듈의 입력 변수, 출력, main까지 모두 생성했습니다.
이제 root module에서 사용해봅시다.
<test/main.tf>
module "mypw1"{
source = "../modules/terraform-module-pwgen"
isDB=true
}
module "mypw2"{
source = "../modules/terraform-module-pwgen"
isDB=false
}
output "mypw1"{
value = module.mypw1
}
output "mypw2"{
value = module.mypw2
}
사용할 모듈을 지정하고 입력 변수를 넣어주고 자식 모듈에서 출력한 결과를 출력하고 있습니다.
위 디렉토리로 이동해서 terraform init -> terraform apply 명령어를 입력하면 결과를 확인할 수 있습니다.
module.mypw1.random_pet.name: Creating...
module.mypw2.random_pet.name: Creating...
module.mypw1.random_password.password: Creating...
module.mypw2.random_password.password: Creating...
module.mypw2.random_pet.name: Creation complete after 0s [id=guiding-baboon]
module.mypw1.random_pet.name: Creation complete after 0s [id=close-mole]
module.mypw2.random_password.password: Creation complete after 0s [id=none]
module.mypw1.random_password.password: Creation complete after 0s [id=none]
Apply complete! Resources: 4 added, 0 changed, 0 destroyed.
Outputs:
mypw1 = {
"id" = "close-mole"
"password" = "mRNyQTnNB9QaTZ3j"
}
mypw2 = {
"id" = "guiding-baboon"
"password" = "toIreb71Ou"
}
프로바이더 정의
모듈에서 사용하는 리소스는 프로바이더 정의가 필요한데 프로바이더 정의를 모듈 안에 둘 수도 있고 모듈 밖에 둘 수도 있습니다.
다음은 프로바이더 정의를 모듈 안에 둘 때입니다.
- 루트 모듈에서 프로바이더 정의가 없고 자식 모듈이 독립적인 구조일 때 사용할 수 있습니다.
- 모듈에 반복문을 사용할 수 없습니다.
- 하지만 모듈 간 버전 충돌 문제가 발생할 수 있기 때문에 자주 사용하는 방식은 아닙니다.
다음은 프로바이더 정의를 모듈 밖에 둘 때입니다.
- 자식 모듈은 루트 모듈의 프로바이더 구성에 종속됩니다.
- 모듈에 반복문을 사용할 수 있습니다.
- 프로바이더를 모듈 내 리소스와 데이터 소스에 일괄 적용할 수 있습니다.
모듈 소스
모듈 또한 코드 위치를 정의하고 terraform init을 통해 모듈을 다운로드 할 수 있습니다.
로컬 모듈을 사용할 때는 "./"나 "../"와 같이 상대 경로를 사용할 수 있습니다.
테라폼 모듈 레지스트리를 사용할 때는 "<네임 스페이스>/<이름>/<프로바이더>" 형태로 사용할 수 있습니다.
깃허브를 사용할 때는 "github.com/<owner name>/<repository name>/<module nmae>" 형태로 사용할 수 있습니다.