๐ ํ์ฌ ๊ตฌ์กฐ ๊ธฐ๋ฐ ์์ ๊ฐ์ด๋
ํ์ฌ๋ main.tf ๋จ์ผ ํ์ผ์ด๋๊น, ๊ธฐ์กด ํ์ผ์ ์ถ๊ฐํ๋ ๋ฐฉ์์ผ๋ก ์๋ดํ ๊ฒ์.
1 Private Subnet ์ถ๊ฐ (๊ฐ์ฅ ๋จผ์ )
variables.tf์ ์ถ๊ฐ
# === Private Subnet ===
variable "private_subnet_a_cidr" {
default = "10.0.11.0/24"
}
variable "private_subnet_b_cidr" {
default = "10.0.12.0/24"
}main.tf ์๋ธ๋ท ์น์ ์๋์ ์ถ๊ฐ
# ============================================
# Private Subnets (Backend EC2, RDS์ฉ)
# ============================================
resource "aws_subnet" "private_a" {
vpc_id = aws_vpc.main.id
cidr_block = var.private_subnet_a_cidr
availability_zone = data.aws_availability_zones.available.names[0]
tags = { Name = "${var.project_name}-private-a" }
}
resource "aws_subnet" "private_b" {
vpc_id = aws_vpc.main.id
cidr_block = var.private_subnet_b_cidr
availability_zone = data.aws_availability_zones.available.names[1]
tags = { Name = "${var.project_name}-private-b" }
}
# Private Route Table (NAT ์์ด ์ผ๋จ ์์ฑ)
resource "aws_route_table" "private_rt" {
vpc_id = aws_vpc.main.id
# NAT Gateway ์ถ๊ฐ ์ ์ฌ๊ธฐ์ route ๋ธ๋ก ์ถ๊ฐ
tags = { Name = "${var.project_name}-private-rt" }
}
resource "aws_route_table_association" "private_a" {
subnet_id = aws_subnet.private_a.id
route_table_id = aws_route_table.private_rt.id
}
resource "aws_route_table_association" "private_b" {
subnet_id = aws_subnet.private_b.id
route_table_id = aws_route_table.private_rt.id
}2 RDS PostgreSQL ์ถ๊ฐ
variables.tf์ ์ถ๊ฐ
# === RDS ===
variable "db_username" {
default = "pposiraegi"
}
variable "db_password" {
description = "RDS master password"
sensitive = true
}
variable "db_name" {
default = "ecommerce"
}terraform.tfvars์ ์ถ๊ฐ
db_password = "์ฌ๊ธฐ์_๊ฐ๋ ฅํ_๋น๋ฐ๋ฒํธ_์
๋ ฅ"main.tf Security Group ์น์ ์ ์ถ๊ฐ
# ============================================
# RDS Security Group
# ============================================
resource "aws_security_group" "rds_sg" {
vpc_id = aws_vpc.main.id
name = "${var.project_name}-rds-sg"
ingress {
description = "PostgreSQL from Backend EC2"
from_port = 5432
to_port = 5432
protocol = "tcp"
security_groups = [aws_security_group.backend_sg.id]
}
tags = { Name = "${var.project_name}-rds-sg" }
}main.tf ๋งจ ์๋์ RDS ๋ฆฌ์์ค ์ถ๊ฐ
# ============================================
# RDS PostgreSQL
# ============================================
resource "aws_db_subnet_group" "main" {
name = "${var.project_name}-db-subnet-group"
subnet_ids = [aws_subnet.private_a.id, aws_subnet.private_b.id]
tags = { Name = "${var.project_name}-db-subnet-group" }
}
resource "aws_db_instance" "postgres" {
identifier = "${var.project_name}-postgres"
# ์์ง ์ค์
engine = "postgres"
engine_version = "15.4"
# ์ธ์คํด์ค ์ค์
instance_class = "db.t3.micro" # ํ๋ฆฌํฐ์ด
allocated_storage = 20
storage_type = "gp2"
# ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ค์
db_name = var.db_name
username = var.db_username
password = var.db_password
# ๋คํธ์ํฌ ์ค์
db_subnet_group_name = aws_db_subnet_group.main.name
vpc_security_group_ids = [aws_security_group.rds_sg.id]
publicly_accessible = false
# ๊ฐ์ฉ์ฑ ์ค์ (๋น์ฉ ์ ๊ฐํ๋ ค๋ฉด false)
multi_az = false
# ๊ธฐํ ์ค์
skip_final_snapshot = true # ๊ฐ๋ฐ์ฉ: ์ญ์ ์ ์ค๋
์ท ์ ์ฐ์
tags = { Name = "${var.project_name}-postgres" }
}outputs.tf์ ์ถ๊ฐ
output "rds_endpoint" {
description = "RDS PostgreSQL endpoint"
value = aws_db_instance.postgres.endpoint
}
output "rds_port" {
description = "RDS PostgreSQL port"
value = aws_db_instance.postgres.port
}3 user_data.sh ์์ (RDS ์ฐ๊ฒฐ)
# docker-compose.override.yml ์์ฑ ๋ถ๋ถ์ ์๋๋ก ๊ต์ฒด
cat > /home/ec2-user/app/docker-compose.override.yml <<EOF
services:
backend:
environment:
# RDS ์ฐ๊ฒฐ ์ ๋ณด
PROD_DB_URL: "jdbc:postgresql://${rds_endpoint}/${db_name}"
PROD_DB_USERNAME: "${db_username}"
PROD_DB_PASSWORD: "${db_password}"
# ๊ธฐ์กด ์ค์
JWT_SECRET: "${jwt_secret}"
CORS_ALLOWED_ORIGINS: "${cors_allowed_origins}"
SPRING_PROFILES_ACTIVE: "prod"
EOFmain.tf EC2 user_data ๋ถ๋ถ ์์
resource "aws_instance" "backend" {
# ... ๊ธฐ์กด ์ค์ ์ ์ง ...
user_data = templatefile("user_data.sh", {
jwt_secret = var.jwt_secret
cors_allowed_origins = "https://${aws_cloudfront_distribution.frontend.domain_name}"
# RDS ๋ณ์ ์ถ๊ฐ
rds_endpoint = aws_db_instance.postgres.endpoint
db_name = var.db_name
db_username = var.db_username
db_password = var.db_password
})
# โ ๏ธ ์ค์: RDS๊ฐ ๋จผ์ ์์ฑ๋์ด์ผ EC2๊ฐ ์ฐ๊ฒฐ ๊ฐ๋ฅ
depends_on = [aws_db_instance.postgres]
}4 Bastion Host ์ถ๊ฐ (์ ํ์ฌํญ)
main.tf Security Group ์น์ ์ ์ถ๊ฐ
resource "aws_security_group" "bastion_sg" {
vpc_id = aws_vpc.main.id
name = "${var.project_name}-bastion-sg"
ingress {
description = "SSH from my IP"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = [var.my_ip]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = { Name = "${var.project_name}-bastion-sg" }
}main.tf EC2 ์น์ ์ ์ถ๊ฐ
resource "aws_instance" "bastion" {
ami = var.ec2_ami
instance_type = "t3.micro"
subnet_id = aws_subnet.public_a.id
vpc_security_group_ids = [aws_security_group.bastion_sg.id]
key_name = aws_key_pair.main_key.key_name
associate_public_ip_address = true
tags = { Name = "${var.project_name}-bastion" }
}backend_sg SSH ๊ท์น ์์ (Bastion๋ง ํ์ฉ)
# ๊ธฐ์กด backend_sg์ SSH ingress๋ฅผ ์ด๋ ๊ฒ ๋ณ๊ฒฝ
ingress {
description = "SSH from Bastion only"
from_port = 22
to_port = 22
protocol = "tcp"
security_groups = [aws_security_group.bastion_sg.id] # cidr_blocks ๋์
}outputs.tf์ ์ถ๊ฐ
output "bastion_ip" {
value = aws_instance.bastion.public_ip
}
output "ssh_to_backend" {
description = "SSH via Bastion"
value = "ssh -J ec2-user@${aws_instance.bastion.public_ip} ec2-user@${aws_instance.backend.private_ip}"
}๐ ์ ์ฉ ์์ (์ค์!)
# 1. ๋ณ์ ํ์ธ
terraform plan
# 2. Private Subnet๋ง ๋จผ์ (๋น ๋ฆ)
terraform apply -target=aws_subnet.private_a -target=aws_subnet.private_b
# 3. RDS ์์ฑ (5~10๋ถ ์์)
terraform apply -target=aws_db_instance.postgres
# 4. ๋๋จธ์ง ์ ์ฒด
terraform applyโ ๏ธ ์ฃผ์์ฌํญ
| ํญ๋ชฉ | ์ฃผ์์ |
|---|---|
| RDS ์์ฑ ์๊ฐ | 5~10๋ถ ๊ฑธ๋ฆผ, ๊ธฐ๋ค๋ ค์ผ ํจ |
| db_password | terraform.tfvars์ ์ ๋ ฅ, ์ ๋ ์ปค๋ฐ ๊ธ์ง |
| EC2 ๊ต์ฒด | subnet ๋ณ๊ฒฝ ์ EC2๊ฐ ์ฌ์์ฑ๋จ โ ๊ธฐ์กด ๋ฐ์ดํฐ ๋ ์๊ฐ |
| ๋น์ฉ | RDS db.t3.micro๋ ํ๋ฆฌํฐ์ด ์ ์ฉ ๊ฐ๋ฅ |
๐ ์ฒดํฌ๋ฆฌ์คํธ
โก variables.tf์ private_subnet, db ๋ณ์ ์ถ๊ฐ
โก terraform.tfvars์ db_password ์
๋ ฅ
โก main.tf์ Private Subnet ์ถ๊ฐ
โก main.tf์ RDS Security Group ์ถ๊ฐ
โก main.tf์ RDS ๋ฆฌ์์ค ์ถ๊ฐ
โก user_data.sh์ RDS ํ๊ฒฝ๋ณ์ ์ถ๊ฐ
โก outputs.tf์ rds_endpoint ์ถ๊ฐ
โก terraform plan์ผ๋ก ๋ณ๊ฒฝ์ฌํญ ํ์ธ
โก terraform apply ์คํ
โก seed.sh๋ก ์ด๊ธฐ ๋ฐ์ดํฐ ์ฃผ์