먼저 나의 배포 계획은 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를 말한다.
다른 모듈은 다음장에서 설명하겠습니다!