티스토리 뷰
Terraform

테라폼(Terraform)은 하시코프(HashiCorp)에서 공개한 IaC 도구다. 테라폼을 통해 리소스를 코드로 손쉽게 배포 및 삭제하며, 다수의 리소스를 일괄적으로 관리하는 구조로 특정 클라우드나 인프라에 종속적이지 않고 AWS, Azure, Google Cloud와 같은 클라우드 서비스나 온프레미스 시스템과 연동될 수 있도록 지원하는 프로바이더 기반 아키텍처이다.
테라폼은 HCL를 사용하여 간결하고 읽기 쉬운 문법을 통해 인프라를 정의할 수 있다. 각 인프라와 서비스는 고유의 API를 가지고 있고 프로바이더는 각 API 명세를 테라폼 코드로 호출해 동작한다. 즉, terraform apply와 같은 명령으로 만들어진 코드를 실행하고 배포할 수 있다.
테라폼 장점
테라폼을 사용하면 다음과 같은 장점이 있다.
- 자동화 및 일관성 있는 인프라 관리 환경 구축
- 인프라와 서비스 구성 및 변경 작업인 프로비저닝을 위해 워크플로우를 제공하여 코드로 자동화된 환경을 구축할 수 있다.
- 여러 환경(개발, 테스트, 프로덕션)에 동일한 인프라를 배포하고, 코드로 모든 구성을 관리하여 높은 일관성을 확보할 수 있다.
- 변경 추적 및 버전 관리
- 코드 형태로 되어 있어 Git 같은 VCS(Version Control System)들을 통해 프로비저닝 작업 일관성을 보장할 수 있다.
- 작업 수행 전에 실행 계획을 작성하여 변경 사항을 미리 확인하므로 안전하고 빠른 프로비저닝을 수행한다.
- VPC나 로드 밸런서와 같은 리소스를 모듈로 작성하여 다양한 프로젝트와 환경에서 동일한 환경을 제공한다.
테라폼 워크플로우

Terraform 워크플로우는 Write -> Init -> Plan -> Apply -> Destroy 순으로 진행되고, 각 단계에 대한 자세한 설명은 다음과 같다.
- write: 프로비저닝하려는 목적에 따라 인프라를 작성하는 단계로 리소스, 모듈, 변수 등을 정의한다.
- init: 프로바이더 플러그인 설치, 모듈 다운로드, .terraform.lock.hcl 생성 등을 수행하여 작업 디렉터리를 초기화한다.
- plan: 현재 상태와 코드의 차이를 계산해 실행 계획을 보여준다.
- apply: 계획을 실행해 인프라를 생성/수정/삭제한다.
- destroy: 모든 관리 리소스를 제거한다.
프로바이더(Provider)

테라폼은 terraform 바이너리 파일을 시작으로 원격 환경에서 원하는 대상을 호출하는 방식으로 실행된다. '원하는 대상'은 호출하는 방식이 서로 다르지만 대상의 공급자, 즉 프로바이더가 제공하는 API를 호출해 상호작용을 한다. 여기서 테라폼이 대상과의 상호작용을 할 수 있도록 하는 것이 '프로바이더'다.
프로바이더 구성에 대한 요구사항은 위 사진처럼 공식 레지스트리 사이트인 테라폼 레지스트리에 공개되어 있는 각 프로바이더의 구성 방식을 참고하는 것이 올바른 방법이다. AWS와 같은 클라우드 프로바이더의 경우는 AWS 자격증명 정보와 리전 이름 등을 정의하기도 한다.
프로바이더 종류
Terraform에는 다음과 같은 다양한 프로바이더들을 제공하여 각각의 플랫폼에서 리소르를 관리할 수 있다.
- aws: Amazon Web Service(AWS)의 리소스(예: EC2, S3 등)를 관리하기 위한 Terrafor의 주요 프로바이더
- azurerm: Microsoft Azure 리소스를 관리하는 프로바이더로, VM, 네트워크, 데이터베이스 등의 Azure 서비스에 접근 가능
- google: Google Cloud Platform(GCP) 리소스를 관리하며, Compute Engine, GKE 등 GCP 서비스와 통합됨
- kubernetes: Kubernetes 클러스터 및 리소스(Pod, Service, Deployment 등)를 관리하는 프로바이더
- helm: Helm 패키지 관리자를 통해 Kubernetes 애플리케이션을 설치하고 관리하는 Terraform 프로바이더
- kubectl: kubectl 명령을 사용하여 Kubernetes 리소스를 직접 조작하거나 관리할 수 있도록 지원하는 프로바이더
- docker: Docker 컨테이너와 네트워크를 관리하며, 로컬 또는 원격 Docker 엔진과 통합할 수 있음
HCL(HashiCorp Configuration Language)
HCL은 하시코프에서 IaC와 구성 정보를 명시하기 위해 개발된 오픈소스 도구로 간결하고 직관적인 문법을 제공한다. 그리고 다양한 클라우드 프로바이더와 서비스에서 사용 가능한 리소스들을 간편하게 정의하고, 각 리소스 간의 의존 관계를 자동으로 관리해주기 때문에 복잡한 인프라도 쉽게 구성할 수 있다.
테라폼은 인프라를 구성하기 위한 다음과 같은 선언 블록이 존재한다.
- terraform 블록
- resource 블록
- data 블록
- variable 블록
- local 블록
- output 블록
terraform 블록
terraform {
required_version = "~> 1.12.2" # 테라폼 버전
required_providers {
# 각 프로바이더의 이름에 소스 경로와 버전을 명시
aws = {
source = "hashicorp/aws"
version = "~> 6.7.0" # 지정한 버전에서 가장 자릿수가 낮은 구성 요소만 증가하는 것 허용
}
}
backend "local" { # state를 보관하는 위치를 지정
path = "relative/path/to/terraform.tfstate"
}
}
테라폼 버전이나 프로바이더 버전과 같은 값들은 자동으로 설정되지만 다른 사람과 함께 작업할 때는 버전을 명시적으로 선언하고 필요한 조건을 입력하여 실행 오류를 최소화하는 것이 좋다. 테라폼 내에서 버전이 명시되는 terraform, module에서 사용 가능하며 버전에 대한 제약을 둠으로써 테라폼, 프로바이더, 모듈이 항상 의도한 정의대로 실행되는 것을 목적으로 한다.
terraform 블록의 required_providers 블록 내에 <로컬 이름> = { }으로 여러 개의 프로바이더를 정의할 수 있다.
resource 블록
resource "<리소스 유형>" "<이름>" {
<인수> = <값>
}
resource "aws_instance" "web" {
ami = "ami-0897f20d7e803af8f"
instance_type = "t3.micro"
}

리소스(resource)는 테라폼이 프로비저닝 도구라는 측면에서 가장 중요한 요소다. 리소스 블록은 선언된 항목을 생성하는 동작을 수행한다. 리소스에서 사용되는 유형들은 프로바이더에 종속성을 갖는다. aws_instance 유형처럼 특정 프로바이더의 유형만 추가해도 terraform init을 수행하면 해당 프로바이더를 설치한다.
리소스 블록을 정의할 때 사용 가능한 메타인수를 다음과 같다.
- depends_on: 종속성을 선언하며, 선언된 구성 요소와의 생성 시점에 대해 정의
- count: 선언된 개수에 따라 여러 데이터 소스를 선언
- for_each: map 또는 set 타입의 데이터 배열의 값을 기준으로 여러 리소스를 생성
- provider: 동일한 프로바이더가 다수 정의되어 있는 경우 지정
- lifecycle: 데이터 소스의 수명주기 관리
- provisioner: 리소스 생성 후 추가 작업 정의
- timeouts: 프로바이더에서 정의한 일부 리소스 유형에서는 create, update, delete에 대한 허용 시간을 정의 가능
resource "local_file" "abc" {
content = "123!"
filename = "${path.module}/abc.txt"
}
resource "local_file" "edf" {
content = local_file.abc.content # <-- local_file.abc의 속성 값을 대신 넣어줌
filename = "${path.module}/abc.txt"
}

테라폼의 종속성은 resource, module 선언으로 프로비저닝되는 각 요소의 생성 순서를 구분짓는다. 위 코드처럼 다른 리소스에서 값을 참조해 불러올 경우 자동으로 연관 관계가 정의되는 암시적 종속성을 갖게 되고, 강제로 리소스 간 명시적 종속성을 부여할 경우에는 메타인수인 depends_on을 활용할 수 있다.
리소스 속성 참조
resource "kubernetes_namespace" "example" {
metadata {
annotations = {
name = "example-annotation"
}
name = "terraform-example-namespace"
}
}
resource "kubernetes_secret" "example" {
metadata {
namespace = kubernetes_namespace.example.metadata.0.name # namespace 리소스 인수 참조
name = "terraform-example"
}
data = {
password = "P4ssw0rd"
}
}
리소스 구성에서 참조 가능한 값은 인수와 속성으로 <리소스 유형>.<이름>.<인수> 또는 <리소스 유형>.<이름>.<속성>으로 참조 가능하다.
- 인수: 리소스 생성 시 사용자가 선언하는 값
- 속성: 사용자가 설정하는 것은 불가능하지만 리소스 생성 이후 획득 가능한 리소스 고유 값
위 코드처럼 쿠버네티스 프로바이더의 Namespace 리소스를 생성하고 그 이후 Secret을 해당 Namespace에 생성하는 종속성을 리소스 인수 값으로 생성하면 Namesapce의 이름이 변경되어도 해당 Namespace를 참조하는 모든 리소스도 같이 업데이트할 수 있다.
data 블록
# Declare the data source
data "aws_availability_zones" "available" {
state = "available"
}
resource "aws_subnet" "primary" {
availability_zone = data.aws_availability_zones.available.names[0]
# e.g. ap-northeast-2a
}
resource "aws_subnet" "secondary" {
availability_zone = data.aws_availability_zones.available.names[1]
# e.g. ap-northeast-2b
}
데이터 소스는 테라폼으로 정의되지 않은 외부 리소스 또는 저장된 정보를 테라폼 내에서 참조할 때 사용한다. 그리고 데이터 소스로 읽은 대상을 참조하는 방식은 리소스와 구별되게 data가 앞에 붙는다. Data Source : aws_availability_zones 블로그의 예시 코드처럼 AWS 프로바이더의 가용영역을 작업자가 수동으로 입력하지 않고 프로바이더로 접근한 환경에서 제공되는 데이터 소스를 활용해 subnet의 가용영역 인수를 정의할 수 있다.
데이터 소스를 정의할 때 사용 가능한 메타인수는 다음과 같다.
- depends_on: 종속성을 선언하며, 선언된 구성 요소와의 생성 시점에 대해 정의
- count: 선언된 개수에 따라 여러 데이터 소스를 선언
- for_each: map 또는 set 타입의 데이터 배열의 값을 기준으로 여러 리소스를 생성
- provider: 동일한 프로바이더가 다수 정의되어 있는 경우 지정
- lifecycle: 데이터 소스의 수명주기 관리
variable 블록
variable "my_password" {}
resource "local_file" "abc" {
content = var.my_password
filename = "${path.module}/abc.txt"
}
입력 변수(variable)는 인프라를 구성하는 데 필요한 속성 값을 정의해 코드의 변경 없이 여러 인프라를 생성하는 데 목적이 있다. 테라폼에서는 이것을 입력 변수(Input Variables)로 정의하고, variable로 시작되는 블록으로 구성된다. 변수 참조가 필요한 경우에는 var.<이름>으로 참조할 수 있다.
변수 정의 시 사용 가능한 메타인수는 다음과 같다.
- default: 변수에 할당되는 기본값 정의
- type: 변수에 허용되는 값 유형 정의
- description: 입력 변수의 설명
- vaildation: 변수 선언의 제약조건을 추가해 유효성 검사 규칙을 정의
- condition에 지정된 규칙이 true 또는 false를 반환해야 하며, error_message로 false인 경우 출력되는 메시지 정의 가능
- sensitive: 민감한 변수 값임을 알리고 테라폼의 출력문에서 값 노출을 제한
- nullable: 변수에 값이 없어도 됨을 지정
변수 유형
지원되는 변수의 범주와 형태는 다음과 같다.
- 기본 유형
- string: 글자 유형
- number: 숫자 유형
- bool: true 또는 false
- any: 명시적으로 모든 유형이 허용됨을 표시
- 집합 유형
- list(<유형>): 인덱스 기반 집합
- map(<유형>): 값 = 속성 기반 집합이며 키값 기준 정렬
- set(<유형>): 값 기반 집합이며 정렬 키값 기준 정렬
- object({<인수 이름> = <유형>, ... })
- tuple([<유형>, ...])
변수 입력 우선순위
variable은 선언되는 방식에 따라 변수의 우선순위가 있으므로, 이를 적절히 사용해 로컬 환경과 빌드 서버 환경에서의 정의를 다르게 하거나, 프로비저닝 파이프라인을 구성하는 경우 외부 값을 변수에 지정할 수 있다. 입력 변수의 우선순위는 다음과 같고, 우선순위 숫자가 작을수록 우선순위도 낮다.
- 실행 후 입력(변수에 값이 선언되지 않아 CLI에서 입력)
- variable 블록의 default 값
- 환경 변수(TF_VAR_변수 이름)
- terraform.tfvars에 정의된 변수 선언
- *.auto.tfvars에 정의된 변수 선언
- *.auto.tfvars.json에 정의된 변수 선언
- CLI 실행 시 -var 인수에 지정 또는 -var-file로 파일 지정
local 블록
variable "prefix" {
default = "hello"
}
locals {
name = "terraform"
content = "${var.prefix} ${local.name}"
my_info = {
age = 20
region = "KR"
}
my_nums = [1, 2, 3, 4, 5]
}
locals {
content = "centent2" # 중복 선언되었으므로 오류가 발생한다.
}
코드 내에서 사용자가 지정한 값 또는 속성 값을 가공해 참조 가능한 local(지역 값)은 외부에서 입력되지 않고, 코드 내에서만 가공되어 동작하는 값을 선언한다. local은 입력 변수와 달리 선언된 모듈 내에서만 접근 가능하고, 변수처럼 실행 시에 입력받을 수 없다.
로컬이 선언되는 블록은 locals로 시작하고, 선언된 local 값은 local.<이름>으로 참조할 수 있다. 테라폼 구성 파일을 여러 개 생성해 작업하는 경우 서로 다른 파일에 선언되어 있더라고 다른 파일에서 참조할 수 있다.
output 블록
모듈 내에서 생성되는 속성 값들은 output 블록에 정의된다. 출력되는 값은 value의 값이며 테라폼이 제공하는 조합과 프로그래밍적인 기능들에 의해 원하는 값을 출력할 수 있다. output 정의 시 사용 가능한 메타인수는 다음과 같다.
- description: 출력 값 설명
- sensitive: 민감한 출력 값임을 알리고 테라폼의 출력문에서 값 노출을 제한
- depends_on: value에 담길 값이 특정 구성에 종속성이 있는 경우 생성되는 순서를 임의로 조정
- precondition: 출력 전에 지정된 조건을 검증
테라폼 반복문
인프라를 코드로 정의할 때, 동일한 유형의 리소스를 여러 개 생성/설정하는 경우가 많다. 이럴 때는 반복문을 사용해 코드를 더 간결하고 효율적으로 작성할 수 있다. 테라폼은 count, for_each, for, dynamic이라는 다양한 반복문 구조를 지원한다.
count
resource "aws_instance" "example1" {
count = 3 # 3개의 인스턴스를 생성
ami = "ami-0897f20d7e803af8f" # 사용할 AMI ID
instance_type = "t2.micro" # EC2 인스턴스 유형 설정
tags = {
Name = "Example-Instance-${count.index}" # 각 인스턴스에 고유한 이름 태그 지정
# (예: "Example-Instance-0", "Example-Instance-1")
}
}
리소스 또는 모듈 블록에 count값이 정수인 인수가 포함된 경우 선언된 정수값만큼 리소스나 모듈을 생성하게 된다. count로 생성되는 리소스의 경우 <리소스 타입>.<이름>[<인덱스 번호>], 모듈의 경우 module.<모듈 이름>[<인덱스 번호>]로 해당 리소스의 값을 참조한다. 위 코드처럼 테라폼으로 AWS EC2 인스턴스를 한 번에 3개 생성할 수 있고, count.index를 이용해 이름 태그를 고유하게 만들 수 있다.
for_each
resource "aws_instance" "example2" {
for_each = toset(["dev", "staging", "prod"]) # 환경별(dev, staging, prod)로 인스턴스를 생성
ami = "ami-0897f20d7e803af8f" # 사용할 AMI ID
instance_type = "t2.micro" # EC2 인스턴스 유형 설정
tags = {
Name = "Example-Instance-${each.key}" # 각 환경에 맞는 고유 이름 태그 지정
# (예: "Example-Instance-dev")
}
}
리소스 또는 모듈 블록에서 for_each에 입력된 데이터 형태가 map 또는 set 이면, 선언된 key 값 개수만큼 리소스를 생성한다. for_each가 설정된 블록에서는 each 속성을 사용해 구성을 수정할 수 있다.
- each.key: 인스턴스에 해당하는 map 또는 set 타입의 key값
- each.value: 인스턴스에 해당하는 map의 value 값
for
locals {
name_tags = [for name in var.instance_names : "Name-${name}"]
# instance_names 목록의 각 항목에 "Name-" 접두사를 추가해 태그 이름을 생성
# (예: ["Name-web1", "Name-web2", "Name-db1"])
}
for 문은 복합 형식 값의 형태를 변환하는 데 사용된다. 예를 들어, list 값의 포맷을 변경하거나 특정 접두사(prefix)를 추가할 수도 있고, output에 원하는 형태로 반복적인 결과를 표현할 수 있다.
- list 타입의 경우 값 또는 인덱스와 값을 반환
- map 타입의 경우 키 또는 키와 값에 대해 반환
- set 타입의 경우 키 값에 대해 반환
dynamic
variable "ingress_rules" {
description = "보안 그룹을 위한 인그레스 규칙 목록"
type = list(object({
from_port = number
to_port = number
protocol = string
cidr_blocks = list(string)
}))
default = [
{
from_port = 80
to_port = 80
protocol = "TCP"
cidr_blocks = ["0.0.0.0/0"]
},
{
from_port = 443
to_port = 443
protocol = "TCP"
cidr_blocks = ["0.0.0.0/0"]
}
]
}
resource "aws_security_group" "example" {
name = "example-sg" # 보안 그룹 이름 설정
dynamic "ingress" {
for_each = var.ingress_rules # ingress_rules 변수의 각 항목을 순회하며 인그레스 규칙 생성
content {
from_port = ingress.value.from_port # 시작 포트 번호 설정
to_port = ingress.value.to_port # 종료 포트 번호 설정
protocol = ingress.value.protocol # 프로토콜 설정 (예: TCP, UDP)
cidr_blocks = ingress.value.cidr_blocks # CIDR 형식의 허용 IP 블록 설정
}
}
}
count나 for_each 구문을 사용한 리소스 전체를 여러 개 생성하는 것 외에도 리소스 내에 선언되는 구성 블록을 다중으로 작성해야 하는 경우가 있다. 위 코드처럼 AWS의 Security Group 리소스 구성에 ingress 요소가 리소스 선언 내부에서 블록 형태로 여러 번 정의되는 경우 dynamic을 사용하여 동적인 블록을 생성할 수 있다.
테라폼 조건식
locals {
instance_type = var.environment == "prod" ? "m5.large" : "t2.micro"
}
locals {
ami_map = {
"us-east-1" = "ami-063d43db0594b521b" # us-east-1에서 찾은 amazon linux 2023 ami
"us-west-2" = "ami-066a7fbea5161f451" # us-west-2에서 찾은 amazon linux 2023 ami
}
selected_ami = local.ami_map[var.region != "" ? var.region : "us-east-1"] # 리전에 따라 ami 선택
}
resource "aws_instance" "example" {
ami = local.selected_ami
instance_type = local.instance_type
}
테라폼에서의 조건식은 3항 연산자 형태를 갖는다. 조건은 true 또는 false로 확인되는 모든 표현식을 사용할 수 있다. 위 코드처럼 locals 블록에서 조건문과 맵을 사용해 설정값을 미리 정의하고, 리소스 생성 시 이를 참조하면 환경과 리전에 따라 EC2 인스턴스의 유형과 AMI를 동적으로 선택하도록 구성할 수 있다.
함수
# 컬렉션 함수 예제
variable "fruit_list" {
default = ["apple", "banana", "cherry"]
}
output "joined_fruit" {
value = join(", ", var.fruit_list) # 리스트를 콤마로 구분하여 문자열로 결합
}
테라폼은 프로그래밍 언어적인 특성을 갖추고 있는데, 값의 유형을 변경하거나 조합할 수 있는 내장 함수들이 그 예다. 단, 내장된 함수 외에 사용자가 구현하는 별도의 사용자 정의 함수를 지원하지는 않는다. 함수 종류에는 숫자, 문자열, 컬렉션, 인코딩, 파일 시스템, 날짜/시간, 해시/암호화, IP 네트워크, 유형 변환이 있다.
- 숫자 함수: abs, ceil, floor, max, min 등 숫자 관련 함수
- 문자열 함수: join, split, replace, trimspace, length 등 문자열 처리 함수
- 컬렉션 함수: merge, contains, lookup, flatten, keys 등 리스트와 맵을 처리하는 함수
- 변환 함수: toset, tolist, tostring 등 타입 변환 함수
- 네트워크 함수: cidrsubnet, cidrhost, cidrnetmask 등 네트워크 관련 함수
- 파일 및 디렉터리 함수: file, filebase64, templatefile 등 파일 처리를 위한 함수
모듈
테라폼으로 인프라와 서비스를 관리하면 시간이 지날수록 구성이 복잡해지고 관리하는 리소스가 늘어나게 된다. 테라폼의 구성 파일과 디렉터리 구성에는 제약이 없기 때문에 단일 파일 구조상에서 지속적으로 업데이트할 수 있지만, 다음과 같은 문제가 발생한다.
- 테라폼 구성에서 원하는 항목을 찾고 수정하는 것이 점점 어려워짐
- 리소스들 간의 연관 관계가 복잡해질수록 변경 작업의 영향도를 분석하기 위한 노력이 늘어남
- 개발/스테이징/프로덕션 환경으로 구분된 경우 비슷한 형태의 구성이 반복되어 업무 호율이 줄어듦
- 새로운 프로젝트를 구성하는 경우 기존 구성에서 취해야 할 리소스 구성과 종속성 파악이 어려움
위와 같은 문제처럼 테라폼으로 관리하는 대상의 규모가 커지고 복잡해져 생긴 문제를 보완하고 관리 작업을 수월하게 하기 위한 방안으로 테라폼 구성의 집합인 모듈을 사용할 수 있다. 모듈은 대부분의 프로그래밍 언어에서 쓰이는 라이브러리나 패키지와 역할이 비슷하다고 할 수 있고, 다음과 같은 기본 작성 원칙을 제안한다.
- 모듈 디렉터리 형식은 terraform-<프로바이더 이름>-<모듈 이름> 형식으로 제안한다. 이 형식은 HCP Terraform, Terraform Enterprise에서도 사용되는 방식으로 디렉터리 또는 레지스트리 이름이 테라폼을 위한 것인지, 어떤 프로바이더의 리소스를 포함하고 있는지, 부여된 이름이 무엇인지 판별할 수 있도록 한다.
- 공개된 테라폼 레지스트리의 모듈을 참고하는 것을 권장한다. 대다수의 테라폼 모듈은 공개된 모듈이 존재하고 거의 모든 인수에 대한 변수 처리, 반복문 적용 리소스, 조건에 따른 리소스 활성/비활성 등을 모범 사례로 공개해 두었다.
- 작성된 모듈은 공개 또는 비공개로 게시해 팀 또는 커뮤니티와 공유하기를 제안한다. 모듈의 사용성을 높이고 피드백을 통해 더 발전된 모듈을 구성할 수 있는 자극이 된다.
모듈 사용 방식
모듈에서 사용되는 모든 리소스는 관련 프로바이더의 정의가 필요하다. 여기서 사용자는 프로바이더 정의를 모듈 안에 두어야 할지 밖에 두어야 할지 구성을 고민할 수 있다. 두 유형에 관한 내용은 다음과 같다.
- 자식 모듈에서 프로바이더 정의: 동일한 프로바이더가 루트와 자식 양쪽에서 또는 서로 다른 자식 모듈에 버전 조건 합의가 안 되면, 오류가 발생하고 모듈에 반복문을 사용할 수 없다는 단점이 있으므로 잘 사용하지 않는다.
- 루트 모듈에서 프로바이더 정의: 자식 모듈 루트 모듈의 프로바이더 구성에 종속되는 방식이다. 자식 모듈에 특정 프로바이더 구성의 종속성은 반영할 수 없으므로 자식 모듈을 테스트한 프로바이더 조건에 대해 기록하고, 자식 모듈을 사용하는 루트 모듈에서 정의하는 프로바이더에 맞게 업데이트해야 한다.
# modules/vpc/variables.tf
variable "cidr_block" {
description = "VPC의 CIDR 블록"
type = string
default = "192.168.0.0/16"
}
variable "vpc_name" {
description = "VPC의 이름"
type = string
default = "your-vpc"
}
# modules/vpc/main.tf
resource "aws_vpc" "this" {
cidr_block = var.cidr_block # VPC의 CIDR 블록을 변수로 설정하여 유연성 제공
tags = {
Name = var.vpc_name # VPC의 이름 태그를 변수로 설정
}
}
# modules/vpc/outputs.tf
output "vpc_id" {
description = "VPC의 ID"
value = aws_vpc.this.id
}
# main.tf
terraform {
required_version = ">=1.9.8"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">=5.81.0"
}
}
}
provider "aws" {
region = "ap-northeast-2"
profile = "my-profile"
}
module "my_vpc" { # module 사용
source = "./modules/vpc"
# variables
vpc_name = "my-vpc"
cidr_block = "10.0.0.0/16"
}
# outputs.tf
output "vpc_id" {
value = module.my_vpc.vpc_id
}


위 코드는 modules/vpc에 VPC 모듈을 만들고, 루트에서 그 모듈을 호출해 VPC를 생성한다. 모듈은 cidr_block, vpc_name 변수를 받아 aws_vpc.this를 만들고 vpc_id를 출력한다. 루트는 AWS 프로바이더/버전 제약을 설정하고, module "my_vpc"롭 ㅕㄴ수를 덮어써 서울 리전에 VPC를 만들도록 했다. 이렇게 모듈로 묶여진 리소스는 module이라는 정의를 통해 단순하게 재활용하고 반복사용할 수 있다. 모듈의 결과 참조 형식은 module.<모듈 이름>.<output 이름>으로 정의된다.
테라폼 모듈 레지스트리
테라폼은 모듈을 불러올 때 source 값의 형식을 분석해 이를 HTTP, Git, 로컬 파일, 레지스트리 등 해당 프로토콜 방식으로 해석해서 가져온다. 이떄, 테라폼 모듈 레지스트리는 Terraform이 정의한 모듈 소스 프로토콜을 통해 모듈을 불러는 방식으로 공개된 테라폼 모듈을 사용하거나 HCL Terraform, Terraform Enterprise에서 제공되는 비공개 테라폼 모듈을 사용할 때 설정하는 소스 지정 방식이다.
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~>6.0"
# ...
}
위 코드는 HashiCorp의 공식 registry.terraform.io인 공개 레지스트리를 사용한 것으로 terraform-aws-modules는 네임스페이스, vpc는 모듈 이름, aws는 프로바이더를 의미한다. terraform init 시 terraform-aws/modules/vpc/aws 모듈 코드를 레지스트리에서 내려받아 .terraform/modules에 캐싱한다. terraform plan에서 모듈 내 리소스 정의를 로드하고, 현재 상태와 비교해 변경 계획을 생성한다. 그리고 terraform apply에서 AWS API를 호출해 VPC를 생성한다.
출처
Terraform Workflow: Terraform Plan & AWS Create VPC Overview
'기타 > AWS' 카테고리의 다른 글
| K8S - 서비스 API 카테고리 (1) | 2025.07.24 |
|---|---|
| AWS CloudFormation으로 EKS 클러스터 생성 (2) | 2025.07.22 |
| EKS 기본 아키텍처 (2) | 2025.07.17 |
| Amazon ELB (0) | 2025.07.08 |
| Amazon VPC (3) | 2025.07.03 |
- Total
- Today
- Yesterday
- TDD
- sql
- 트랜잭션
- transaction
- 비관적 락
- 분산 락
- jvm 메모리 구조
- 구름톤챌린지
- Kafka
- nginx configuration
- mdcfilter
- redis session
- postgresql
- EKS
- 람다
- Synchronized
- Redisson
- socket
- 넥스트스탭
- 낙관적 락
- mysql
- 구름톤 챌린지
- pessimistic lock
- Java
- nginx
- annotation
- spring session
- spring webflux
- 카프카
- NeXTSTEP
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |
