관리 메뉴

근묵자흑

Terraform Module 본문

IaC/terraform

Terraform Module

Luuuuu 2025. 1. 5. 17:56

인프라를 코드로 관리하다 보면 비슷한 패턴의 코드가 자주 반복되는 것을 발견하게 됩니다. 예를 들어 개발 환경과 운영 환경에서 동일한 구조의 VPC를 생성하거나, 여러 리전에 비슷한 구성의 웹 서버를 배포해야 할 수 있습니다. 이런 상황에서 테라폼의 모듈(Module) 기능을 활용하면 코드의 재사용성을 높이고 유지보수를 쉽게 만들 수 있습니다.

테라폼 모듈이란?

테라폼 모듈은 여러 리소스를 하나의 논리적 단위로 패키징한 것입니다. 마치 프로그래밍 언어의 함수처럼, 입력값을 받아 정의된 로직에 따라 리소스를 생성하고 필요한 값을 출력할 수 있습니다. 잘 설계된 모듈은 다음과 같은 장점을 제공합니다:

  • 코드 재사용을 통한 생산성 향상
  • 일관된 인프라 구성 유지
  • 리소스 생성 로직의 캡슐화
  • 인프라 변경의 용이성

모듈의 기본 구조

 

가장 기본적인 테라폼 모듈은 다음과 같은 파일들로 구성됩니다:

modules/web_server/
├── main.tf      # 주요 리소스 정의
├── variables.tf  # 입력 변수 정의
├── outputs.tf    # 출력 값 정의
└── README.md     # 모듈 사용 설명서

예를 들어 EC2 웹 서버를 생성하는 모듈을 만들어보겠습니다:

# main.tf
resource "aws_instance" "web" {
  ami           = var.ami_id
  instance_type = var.instance_type

  tags = {
    Name = "${var.environment}-web-server"
  }

  user_data = <<-EOF
              #!/bin/bash
              yum update -y
              yum install -y httpd
              systemctl start httpd
              systemctl enable httpd
              EOF
}

resource "aws_security_group" "web" {
  name        = "${var.environment}-web-sg"
  description = "Security group for web server"

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

모듈 입력 변수 설계하기

모듈의 재사용성을 높이기 위해서는 적절한 입력 변수를 정의하는 것이 중요합니다. variables.tf 파일에서 다음과 같이 변수를 정의할 수 있습니다:

# variables.tf
variable "environment" {
  description = "배포 환경 (예: dev, prod)"
  type        = string
}

variable "ami_id" {
  description = "사용할 AMI ID"
  type        = string
}

variable "instance_type" {
  description = "EC2 인스턴스 타입"
  type        = string
  default     = "t2.micro"  # 기본값 설정
}

variable "vpc_id" {
  description = "VPC ID"
  type        = string
}

변수 정의 시 고려사항:

  1. 필수 변수와 선택적 변수를 구분 (default 값 유무로 구분)
  2. 적절한 변수 타입 지정 (string, number, bool, list, map 등)
  3. 명확한 설명 추가 (description 필드 활용)
  4. 가능한 경우 validation 규칙 추가

모듈의 지역 변수 활용

모듈 내부에서만 사용되는 값들은 locals 블록을 통해 관리할 수 있습니다:

locals {
  # 공통으로 사용되는 태그 정의
  common_tags = {
    Environment = var.environment
    ManagedBy   = "Terraform"
    Project     = var.project_name
  }

  # 인스턴스 이름 생성 규칙
  instance_name = "${var.project_name}-${var.environment}-server"

  # 보안 그룹 규칙 정의
  security_group_rules = {
    http = {
      port        = 80
      cidr_blocks = ["0.0.0.0/0"]
    }
    https = {
      port        = 443
      cidr_blocks = ["0.0.0.0/0"]
    }
  }
}

지역 변수를 활용하면:

  • 반복되는 값들을 한 곳에서 관리할 수 있습니다
  • 복잡한 표현식을 단순화할 수 있습니다
  • 모듈 내부 로직을 더 명확하게 표현할 수 있습니다

모듈 출력 설계하기

모듈은 생성된 리소스의 중요 정보를 출력할 수 있습니다. outputs.tf 파일에서 다음과 같이 정의합니다:

# outputs.tf
output "instance_id" {
  description = "생성된 EC2 인스턴스 ID"
  value       = aws_instance.web.id
}

output "public_ip" {
  description = "EC2 인스턴스의 공개 IP 주소"
  value       = aws_instance.web.public_ip
}

output "security_group_id" {
  description = "생성된 보안 그룹 ID"
  value       = aws_security_group.web.id
}

출력값 설계 시 고려사항:

  1. 외부에서 필요한 정보만 선별적으로 노출
  2. 명확한 설명 추가
  3. 민감한 정보는 sensitive = true 설정

모듈 사용하기

정의된 모듈은 다음과 같이 사용할 수 있습니다:

# 개발 환경 웹 서버
module "web_server_dev" {
  source = "./modules/web_server"

  environment    = "dev"
  ami_id         = "ami-12345678"
  instance_type  = "t2.micro"
  vpc_id         = module.vpc.vpc_id
}

# 운영 환경 웹 서버
module "web_server_prod" {
  source = "./modules/web_server"

  environment    = "prod"
  ami_id         = "ami-12345678"
  instance_type  = "t2.large"  # 운영 환경은 더 큰 인스턴스 사용
  vpc_id         = module.vpc.vpc_id
}

모듈 버전 관리

테라폼 모듈의 버전 관리는 GitHub의 태그 기능을 활용합니다. 이는 모듈의 안정적인 배포와 버전 추적을 가능하게 합니다.

Git 태그를 이용한 버전 관리

시맨틱 버저닝(Semantic Versioning)을 따라 Git 태그를 생성합니다:

# 태그 생성
git tag -a v1.0.0 -m "Initial stable release"

# 태그 푸시
git push origin v1.0.0

버전 번호 체계:

  • MAJOR.MINOR.PATCH (예: v1.2.3)
  • MAJOR: 호환성이 깨지는 변경사항 (예: 필수 변수 추가)
  • MINOR: 하위 호환성이 있는 기능 추가 (예: 선택적 변수 추가)
  • PATCH: 버그 수정 (기존 기능 수정)

태그된 모듈 사용

GitHub 저장소의 특정 태그를 참조하여 모듈을 사용:

module "web_server" {
  source = "github.com/username/repo//modules/web_server?ref=v1.2.3"
}

# 특정 메이저 버전의 최신 릴리스 사용
module "web_server" {
  source = "github.com/username/repo//modules/web_server?ref=v1.2.3"
}

모듈 작성 시 주의사항

1. 파일 경로 참조

모듈의 source 속성에는 다양한 형태의 경로를 지정할 수 있습니다:

# 로컬 경로
module "example" {
  source = "./modules/example"  # 상대 경로
  source = "/modules/example"   # 절대 경로
}

# Git 저장소
module "example" {
  source = "github.com/username/repo//modules/example"  # GitHub
  source = "git::https://example.com/repo.git//modules/example"  # 일반 Git
}

# Terraform Registry
module "example" {
  source  = "hashicorp/consul/aws"  # 공식 레지스트리
  version = "0.1.0"
}

# S3 버킷
module "example" {
  source = "s3::https://s3-eu-west-1.amazonaws.com/examplebucket/example.zip"
}

주의할 점:

  • 로컬 경로 사용 시 상대 경로 권장 (이식성)
  • Git 저장소 참조 시 특정 태그나 커밋 지정 권장
  • 외부 모듈 사용 시 반드시 버전 명시

2. 인라인 블록 사용

테라폼에서는 일부 리소스 설정을 인라인 블록으로 정의할 수 있습니다. 하지만 모듈에서는 인라인 블록 사용을 주의해야 합니다:

# 좋지 않은 예 - 인라인 블록 사용
resource "aws_security_group" "example" {
  # ... 기타 설정 ...

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

# 좋은 예 - 독립적인 리소스로 분리
resource "aws_security_group" "example" {
  # ... 기타 설정 ...
}

resource "aws_security_group_rule" "ingress_http" {
  type              = "ingress"
  security_group_id = aws_security_group.example.id
  from_port         = 80
  to_port           = 80
  protocol          = "tcp"
  cidr_blocks       = ["0.0.0.0/0"]
}

인라인 블록 사용 시 주의사항:

  • 변경이 어려움 (전체 리소스를 재생성해야 할 수 있음)
  • 동적 구성이 제한적
  • 상태 관리가 복잡해짐

3. 단일 책임 원칙

  • 하나의 모듈은 하나의 논리적 단위만 담당
  • 너무 많은 기능을 하나의 모듈에 넣지 않기

4. 적절한 추상화 수준

  • 너무 세부적이면 사용성이 떨어짐
  • 너무 추상적이면 유연성이 떨어짐

5. 문서화

  • README.md 파일에 사용 방법 상세히 기술
  • 예제 코드 포함
  • 변수와 출력값에 대한 설명 추가

6. 테스트

  • terraform plan을 통한 기본 검증
  • 다양한 입력값으로 테스트
  • 가능하다면 자동화된 테스트 추가

결론

테라폼 모듈은 인프라 코드의 재사용성과 유지보수성을 크게 향상시킬 수 있는 강력한 도구입니다. 하지만 좋은 모듈을 만들기 위해서는 신중한 설계와 지속적인 관리가 필요합니다. 위에서 설명한 사항들을 고려하여 모듈을 작성한다면, 보다 효율적이고 안정적인 인프라 관리가 가능할 것입니다.

'IaC > terraform' 카테고리의 다른 글

프로덕션 수준의 테라폼 코드  (3) 2025.01.19
테라폼 팁과 요령: 반복문, if문, 배포 및 주의사항  (3) 2025.01.12
Terraform State  (3) 2024.12.29
테라폼 로드밸런서 배포  (5) 2024.12.22
왜 테라폼 인가?  (4) 2024.12.15