상세 컨텐츠

본문 제목

Terraform으로 EC2에 백엔드 서버 배포 (with ECR) 1장 EC2 모듈

DevOps/Terraform

by rakyun 2025. 8. 20. 11:59

본문

먼저 나의 배포 계획은 ecr에 백엔드 서버 도커 이미지를 올리고 올라간 도커 이미지를 ec2 서버에서 pull 받아서 사용하는 방법을 선택했다.

 

Terraform 모듈 설정

  • 모듈은 총 4개를 만들었다. ec2, ecr iam, security_group이다.
    • iam은 ecr에 이미지를 올리는 권한 ec2에서 ecr의 이미지를 가져오는 권한 등을 주기 위함이다.
    • security_group은 ec2의 인바운드/아웃받운드 트래픽을 제어하기 위해 만들었다.

EC2

# 백엔드를 위한 EC2 인스턴스
# 실제 애플리케이션이 실행될 서버입니다

# 최신 Ubuntu AMI 조회
# AMI(Amazon Machine Image)는 EC2 인스턴스의 템플릿입니다
data "aws_ami" "ubuntu" {
  most_recent = true              # 가장 최신 버전 선택
  owners      = ["099720109477"]  # Canonical(Ubuntu 제작사)의 공식 AMI만

  # Ubuntu 22.04 LTS 필터
  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
  }

  # 가상화 타입 필터
  filter {
    name   = "virtualization-type"
    values = ["hvm"]  # Hardware Virtual Machine
  }
}
  • EC2의 AMI 설정
  • ubuntu 이미지를 사용하고 가상 하드웨어 HVM 사용
# User Data 스크립트를 위한 로컬 변수
# templatefile 함수를 사용하기 위해 locals 블록 사용
locals {
  user_data_vars = {
    domain_name        = var.domain_name                      # 도메인 이름
    aws_region         = var.aws_region                       # AWS 리전
    ecr_registry       = var.ecr_registry                     # ECR 레지스트리 URL
    ecr_repository     = var.ecr_repository                   # ECR 리포지토리 이름
    django_secret_key  = var.django_secret_key                # Django 시크릿 키
    db_password        = var.db_password                      # DB 비밀번호
    # OAuth 설정
    google_client_id   = var.google_client_id
    google_secret_key  = var.google_secret_key
    naver_client_id    = var.naver_client_id
    naver_secret_key   = var.naver_secret_key
    kakao_client_id    = var.kakao_client_id
    kakao_secret_key   = var.kakao_secret_key
    # 이메일 설정
    email_host_user    = var.email_host_user
    email_host_password = var.email_host_password
  }
}
  • user data script 라는 스크립트 파일의 인자이다.
    •  user data script 파일은 ec2가 서버에 배포될때 실행되는 ec2의 환경설정이다.
  • user data script 파일은 ec2의 기본 설정을 담당한다. (nginx 설정, docker-compose 작성 등)
# EC2 인스턴스 리소스
resource "aws_instance" "backend" {
  # 기본 설정
  ami                    = data.aws_ami.ubuntu.id         # Ubuntu AMI ID
  instance_type          = var.instance_type              # 인스턴스 타입 (t2.micro 등)
  key_name              = var.key_pair_name              # SSH 접속용 키페어
  vpc_security_group_ids = [var.security_group_id]       # 보안 그룹 ID
  iam_instance_profile   = var.instance_profile_name     # IAM 인스턴스 프로파일
  
  # 네트워크 설정
  subnet_id                   = var.subnet_id            # 서브넷 ID (기본 VPC의 퍼블릭 서브넷)
  associate_public_ip_address = true                     # 퍼블릭 IP 자동 할당

  # 초기화 스크립트 - templatefile 함수 사용
  user_data = templatefile("${path.module}/user_data.sh", local.user_data_vars)

  # 루트 볼륨 설정 (EBS)
  root_block_device {
    volume_type = "gp3"                                  # SSD 타입 (gp3가 최신)
    volume_size = var.volume_size                        # 볼륨 크기 (GB)
    encrypted   = true                                   # 암호화 활성화
    
    tags = {
      Name        = "${var.project_name}-${var.environment}-root-volume"
      Environment = var.environment
      Project     = var.project_name
    }
  }

  # 인스턴스 태그
  tags = {
    Name        = "${var.project_name}-${var.environment}-backend"
    Environment = var.environment
    Project     = var.project_name
    ManagedBy   = "Terraform"
  }

  # 라이프사이클 설정
  lifecycle {
    create_before_destroy = true  # 교체 시 새 인스턴스 먼저 생성 후 기존 인스턴스 삭제
  }
}
  • ec2의 인스턴스를 aws 콘솔에서 만들 듯이 똑같이 코드로 정의해놓는 것이다.
  • 여기서 나오는 var는 모두 미리 코드로 정의해놓은 variables.tf에 있는 값들이다.
    • 이렇게 변수를 따로 관리함으로써 이 ec2 인스턴스 생성 코드를 여러 인프라에서 사용 가능하다.
  • lifecycle의 create_before_destory = true 코드는 terraform apply 명령어로 terraform 코드를 인프라로 구축할때
    기존의 ec2가 있다면 새로운 ec2를 띄우고 트래픽을 새로운 ec2로 보낸 후에 기존에 있던 ec2를 삭제한다는 뜻이다.
# Elastic IP (선택사항)
# 고정 IP를 사용하면 인스턴스가 재시작되어도 IP가 변경되지 않습니다
resource "aws_eip" "backend" {
  count    = var.use_elastic_ip ? 1 : 0  # use_elastic_ip가 true일 때만 생성
  instance = aws_instance.backend.id
  domain   = "vpc"  # VPC에서 사용

  tags = {
    Name        = "${var.project_name}-${var.environment}-eip"
    Environment = var.environment
    Project     = var.project_name
    ManagedBy   = "Terraform"
  }
}
  • Elastic IP는 ec2를 새로 만들때 마다 변경되는 public ip가 아닌 ec2가 새로 생성되어도 항상 똑같이 연결되어 있을 IP를 말한다.
다른 모듈은 다음장에서 설명하겠습니다!

관련글 더보기