Terraform 모듈들을 조립하는 총괄 설계도
terraform.tfvars에 모든 변수들의 값을 저장해두고 각기 모듈들에서 필요한 변수들을 넣어주는 역할을 main.tf에서 한다.
# 프로덕션 환경을 위한 메인 Terraform 설정 파일
# 이 파일은 모든 모듈을 조합하여 전체 인프라를 구성합니다
terraform {
# Terraform 버전 요구사항 - 1.0 이상 필요
required_version = ">= 1.0"
# 필요한 Provider 정의
required_providers {
aws = {
source = "hashicorp/aws" # AWS Provider 소스
version = "~> 5.0" # 5.x 버전 사용 (5.0 이상, 6.0 미만)
}
tls = {
source = "hashicorp/tls" # TLS Provider - 키 페어 생성용
version = "~> 4.0"
}
local = {
source = "hashicorp/local" # Local Provider - 파일 저장용
version = "~> 2.0"
}
}
# Terraform State 원격 저장소 설정 (현재는 로컬 테스트용으로 주석 처리)
# 프로덕션에서는 S3에 state 파일을 저장하는 것을 권장
# 주석 해제하려면:
# 1. S3 버킷을 먼저 생성
# 2. bucket 이름을 고유한 값으로 변경
# 3. terraform init -backend-config 명령 실행
# backend "s3" {
# bucket = "project-terraform-state-YOUR-UNIQUE-ID" # S3 버킷 이름 (전역적으로 고유해야 함)
# key = "prod/terraform.tfstate" # State 파일 경로
# region = "ap-northeast-2" # 서울 리전
# encrypt = true # State 파일 암호화
# }
}
- 테라폼 기본 설정
- Provider 정의: 이 코드가 어떤 클라우드 서비스와 상호작용할지 정의한다. 여기서는 aws, tls(키 페어 생성용), local(로컬 파일 저장용)이라는 세 가지 도구(Provider)를 사용하겠다고 선언했다.
- 테라폼은 required_providers 블록을 읽고 명시된 프로바이더들을 자동으로 다운로드하여 설치한다.
- 주석 처리 되어 있는 S3 버킷은 테라폼의 상태를 저장하는 공간으로 활용된다. 테라폼은 코드로 인프라를 정의하는데, 코드를 변경하면 인프라의 구조 또한 바뀐다. 그래서 현재 인프라의 상태를 State에 표현하게 되는데 그 State를 S3에 저장하여 로컬 환경과 프로덕션 환경을 비교하기 위한 목적으로 S3 버킷을 생성한다.
(그러나 나는 혼자 테스트 하는 것이므로 주석처리)
# AWS Provider 설정
provider "aws" {
profile = "default" # AWS CLI profile 설정
region = var.aws_region # 사용할 AWS 리전 (ap-northeast-2 = 서울)
# 모든 리소스에 자동으로 추가될 기본 태그
default_tags {
tags = {
Environment = var.environment # 환경 구분 (dev/prod)
Project = var.project_name # 프로젝트 이름
ManagedBy = "Terraform" # Terraform으로 관리됨을 표시
}
}
}
# ===== Data Sources: 기존 AWS 리소스 조회 =====
# 기본 VPC 조회 (AWS 계정에 자동으로 생성된 기본 VPC)
data "aws_vpc" "default" {
default = true # 기본 VPC를 사용 (별도 VPC 생성하지 않음)
}
# 기본 VPC의 모든 서브넷 조회
data "aws_subnets" "default" {
filter {
name = "vpc-id"
values = [data.aws_vpc.default.id] # 위에서 조회한 기본 VPC의 ID 사용
}
}
# t2.micro를 지원하는 가용 영역의 서브넷 필터링
data "aws_subnets" "available" {
filter {
name = "vpc-id"
values = [data.aws_vpc.default.id]
}
filter {
name = "availability-zone"
values = ["ap-northeast-2a", "ap-northeast-2c"] # t2.micro 지원 가용 영역
}
}
# 첫 번째 사용 가능한 서브넷 선택 (EC2를 배치할 서브넷)
data "aws_subnet" "selected" {
id = data.aws_subnets.available.ids[0] # 사용 가능한 서브넷 중 첫 번째 선택
}
# 현재 AWS 계정 ID 조회 (ECR 권한 설정에 필요)
data "aws_caller_identity" "current" {}
- data "aws_vpc" "default": AWS 계정을 처음 만들면 기본적으로 제공되는 가상 네트워크(VPC)의 정보를 찾아온다.
default = true는 기존에 있는 VPC를 가져오라는 의미
- data "aws_subnets" "default": 위에서 찾은 기본 VPC 안에 존재하는 모든 서브넷(VPC를 잘게 나눈 하위 네트워크)의 목록을 가져옴
- data "aws_subnets" "available": 가져온 서브넷 목록 중에서 t2.micro 인스턴스 타입을 지원하는
특정 가용 영역(ap-northeast-2a, ap-northeast-2c)에 속한 서브넷만 다시 한번 필터링 한다.
- data "aws_subnet" "selected": 필터링된 서브넷 목록 중, 첫 번째 서브넷(ids[0])을 최종적으로 선택한다. EC2 인스턴스는 이 서브넷에 배치됨
- data "aws_caller_identity" "current": 현재 이 테라폼 코드를 실행하는 AWS 계정의 고유 ID(Account ID)를 조회함. 이 정보는 나중에 ECR(컨테이너 저장소)의 권한을 설정하는 등 다른 리소스에서 참조하기 위해 필요
# ===== 모듈 호출: 각 모듈을 조합하여 인프라 구성 =====
# 보안 그룹 모듈 - EC2 인스턴스의 방화벽 규칙 설정
module "security_group" {
source = "../../modules/security_group" # 모듈 경로
# 모듈에 전달할 변수들
project_name = var.project_name # 프로젝트 이름
environment = var.environment # 환경 (prod)
vpc_id = data.aws_vpc.default.id # VPC ID
ssh_allowed_ips = var.ssh_allowed_ips # SSH 접속 허용 IP 목록
}
# IAM 역할 모듈 - EC2가 ECR과 CloudWatch에 접근할 수 있는 권한 설정
module "iam" {
source = "../../modules/iam"
project_name = var.project_name # 프로젝트 이름
environment = var.environment # 환경
enable_ssm = var.enable_ssm # Systems Manager 활성화 여부
}
# ECR 모듈 - Docker 이미지를 저장할 컨테이너 레지스트리
module "ecr" {
source = "../../modules/ecr"
project_name = var.project_name # 프로젝트 이름
environment = var.environment # 환경
image_count_limit = var.ecr_image_count_limit # 보관할 이미지 개수
allowed_account_ids = [data.aws_caller_identity.current.account_id] # 접근 허용 계정
}
# EC2 모듈 - 실제 애플리케이션이 실행될 서버
module "ec2" {
source = "../../modules/ec2"
# AWS 설정
aws_region = var.aws_region # AWS 리전
instance_type = var.instance_type # 인스턴스 타입 (t2.micro 등)
security_group_id = module.security_group.security_group_id # 보안 그룹 ID
instance_profile_name = module.iam.instance_profile_name # IAM 인스턴스 프로파일
subnet_id = data.aws_subnet.selected.id # 서브넷 ID
volume_size = var.volume_size # EBS 볼륨 크기
use_elastic_ip = var.use_elastic_ip # Elastic IP 사용 여부
# 애플리케이션 관련 설정
project_name = var.project_name # 프로젝트 이름
environment = var.environment # 환경
domain_name = var.domain_name # 도메인 이름
ecr_registry = split("/", module.ecr.repository_url)[0] # ECR 레지스트리 URL
ecr_repository_name = module.ecr.repository_name # ECR 리포지토리 이름
}
- 앞서 만들었던 각 모듈들을 여기서 조립해서 사용한다.
- var에 정의된 값들을 가져와서 각 모듈들에 넣어줌으로써 각 모듈들이 실제로 aws에 생성된다.