CI CD (aws terraform) - prgrms-web-devcourse-final-project/WEB4_5_ServerSOS_BE GitHub Wiki
CI/CD ๊ตฌ์ถ
ํ๋ก ํธ์ ๊ณ ๋ คํ ์ฌํญ
- cors โ cors ์ ํ๋ก ํธurl์ถ๊ฐ
- cookie โ samesite strict x
- redirectUrl (์์ ๋ก๊ทธ์ธ)
ํฐ ํ๋ฆ
- aws ์๋ฒ ๊ตฌ์ถ(ํ ๋ผํผ)
- docker๋ฅผ ํตํด ์ปจํ ์ด๋ํ
AWS ๊ตฌ์กฐ์ ํ ๋ผํผ ์ดํดํ๊ธฐ
๊ตฌ์กฐ
์ ์ฒด์ ์ธ ๊ตฌ์กฐ : ๋ฆฌ์ > ๊ฐ์ฉ ์์ต(AZ) > VPC > ์๋ธ๋ท > EC2
๋ฆฌ์ : ์ ์ธ๊ณ์ ๋ถ์ฐ๋ AWS ์ผํฐ ๋ฌถ์
๊ฐ์ฉ ์์ญ : ๋ฆฌ์ ์์ ๋ฐ์ดํฐ ์ผํฐ๋ค
VPC : ๋ฆฌ์ ์์์ ๋ง๋๋ ๋คํธ์ํฌ ๊ณต๊ฐ
ํ ๋ผํผ ์์ ์ ๋น์ ๋ก ์ดํดํ๊ธฐ
-
๋น์
- VPC : ํ๋์ ๋ง์
- ์๋ธ๋ท : ๋ง์ ์์ ํ๋์ ๊ตฌ์ญ
- IGW(์ธํฐ๋ท ๊ฒ์ดํธ์จ์ด) : ์ธ๋ถ์ ๋ง์์ ์ฐ๊ฒฐ ํด์ฃผ๋ ์ ์ถ๊ตฌ
- ๋ผ์ฐํ ํ ์ด๋ธ(rt) : ๊ธธ ์๋ด ํ์งํ
- ์ธํ๋ฆฌํฐ ๊ทธ๋ฃน(sg) : ๋๊ตฌ๋ฅผ ๋ค์ด๊ณ ๊ฒ ํ ์ง ์ ํ๋ ๋ณด์๋ฌธ
- EC2 : ์ง (ํ๋์ ์๋ธ๋ท์ ์ํ๋ค) - ์๋ฒ
- iam role : ๊ถํ ์ฆ๋ช ์
- user_data : ์ด๊ธฐ ๋ฐ์ดํฐ ์ธํ
-
์ฝ๋ ํ๋ฆ ์ค๋ช
- ๊ธฐ์ด ๊ณต์ฌ
- VPC
- IP์ ๋ฒ์๋ฅผ 10.0.0.0/16 ์ผ๋ก ์ ํจ
- Subnet
- VPC IP์ ๋ฒ์ ์์ IP ์ค์
- ๊ฐ์ฉ ์์ญ ์ค์
- ํ์ฌ 4๊ฐ์ ๊ตฌ์ญ์ ๋ง๋ค์์
- IG
- ์ธ๋ถ๋ก ๋๊ฐ ์ ์๋ ํต๋ก ๋ง๋ฌ
- ๋ผ์ฐํ
ํ
์ด๋ธ
- 0.0.0.0/0(๋ชจ๋ IP) ๋ IG๋ก ๋๊ฐ๊ฒํจ
- assosiation ์ ํตํด 4๊ฐ์ ์๋ธ๋ท์ ์ค์ ํด์ค
- ์ํ๋ฆฌํฐ ๊ทธ๋ฃน
- ingress : ๋ชจ๋ ๋ฐฉ๋ฌธ์ ๋ํด์ ์ด์ด๋
- egress : ๋ชจ๋ ์ธ์ถ์ ๋ํด์ ์ด์ด๋
- VPC
- ์ง ์ง๊ธฐ
- EC2
- IAM ์ญํ ๋ง๋ค๊ธฐ โ ๊ถํ ๋ถ์ฌ
- ํ๋กํ ๋ง๋ค๊ธฐ(EC2๊ฐ ๋ถ์ฐฉํจ)
- ์ค์
- ami : ์ด์์ฒด์
- instance_type : ์๋ฒ ํฌ๊ธฐ
- ์์ ์ค์ ํ ๊ธฐ์ด ๊ณต์ฌ๋ฅผ ์ค์ ํด์ค
- user_data : ๊ธฐ์ด ๋ฐ์ดํฐ ๋ฃ์ด์ค
- EC2
- ๊ธฐ์ด ๊ณต์ฌ
terraform {
// aws ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ถ๋ฌ์ด
required_providers {
aws = {
source = "hashicorp/aws"
}
}
}
# AWS ์ค์ ์์
provider "aws" {
region = var.region
}
# AWS ์ค์ ๋
# VPC ์ค์ ์์
resource "aws_vpc" "vpc_1" {
cidr_block = "10.0.0.0/16"
enable_dns_support = true
enable_dns_hostnames = true
tags = {
Name = "${var.prefix}-vpc-1"
}
}
# Subnet ์ค์ ์์
resource "aws_subnet" "subnet_1" {
vpc_id = aws_vpc.vpc_1.id
cidr_block = "10.0.1.0/24"
availability_zone = "${var.region}a"
map_public_ip_on_launch = true
tags = {
Name = "${var.prefix}-subnet-1"
}
}
# Subnet ์ค์ ์์
resource "aws_subnet" "subnet_2" {
vpc_id = aws_vpc.vpc_1.id
cidr_block = "10.0.2.0/24"
availability_zone = "${var.region}b"
map_public_ip_on_launch = true
tags = {
Name = "${var.prefix}-subnet-2"
}
}
# Subnet ์ค์ ์์
resource "aws_subnet" "subnet_3" {
vpc_id = aws_vpc.vpc_1.id
cidr_block = "10.0.3.0/24"
availability_zone = "${var.region}c"
map_public_ip_on_launch = true
tags = {
Name = "${var.prefix}-subnet-3"
}
}
# Subnet ์ค์ ์์
resource "aws_subnet" "subnet_4" {
vpc_id = aws_vpc.vpc_1.id
cidr_block = "10.0.4.0/24"
availability_zone = "${var.region}d"
map_public_ip_on_launch = true
tags = {
Name = "${var.prefix}-subnet-4"
}
}
resource "aws_internet_gateway" "igw_1" {
vpc_id = aws_vpc.vpc_1.id
tags = {
Name = "${var.prefix}-igw-1"
}
}
resource "aws_route_table" "rt_1" {
vpc_id = aws_vpc.vpc_1.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw_1.id
}
tags = {
Name = "${var.prefix}-rt-1"
}
}
resource "aws_route_table_association" "association_1" {
subnet_id = aws_subnet.subnet_1.id
route_table_id = aws_route_table.rt_1.id
}
resource "aws_route_table_association" "association_2" {
subnet_id = aws_subnet.subnet_2.id
route_table_id = aws_route_table.rt_1.id
}
resource "aws_route_table_association" "association_3" {
subnet_id = aws_subnet.subnet_3.id
route_table_id = aws_route_table.rt_1.id
}
resource "aws_route_table_association" "association_4" {
subnet_id = aws_subnet.subnet_4.id
route_table_id = aws_route_table.rt_1.id
}
resource "aws_security_group" "sg_1" {
name = "${var.prefix}-sg-1"
ingress {
from_port = 0
to_port = 0
protocol = "all"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "all"
cidr_blocks = ["0.0.0.0/0"]
}
vpc_id = aws_vpc.vpc_1.id
tags = {
Name = "${var.prefix}-sg-1"
}
}
# EC2 ์ญํ ์์ฑ
resource "aws_iam_role" "ec2_role_1" {
name = "${var.prefix}-ec2-role-1"
# ์ด ์ญํ ์ ๋ํ ์ ๋ขฐ ์ ์ฑ
์ค์ . EC2 ์๋น์ค๊ฐ ์ด ์ญํ ์ ๊ฐ์ ํ ์ ์๋๋ก ์ค์
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Action": "sts:AssumeRole",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Effect": "Allow"
}
]
}
EOF
}
# EC2 ์ญํ ์ AmazonS3FullAccess ์ ์ฑ
์ ๋ถ์ฐฉ
resource "aws_iam_role_policy_attachment" "s3_full_access" {
role = aws_iam_role.ec2_role_1.name
policy_arn = "arn:aws:iam::aws:policy/AmazonS3FullAccess"
}
# EC2 ์ญํ ์ AmazonEC2RoleforSSM ์ ์ฑ
์ ๋ถ์ฐฉ
resource "aws_iam_role_policy_attachment" "ec2_ssm" {
role = aws_iam_role.ec2_role_1.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM"
}
# IAM ์ธ์คํด์ค ํ๋กํ์ผ ์์ฑ
resource "aws_iam_instance_profile" "instance_profile_1" {
name = "${var.prefix}-instance-profile-1"
role = aws_iam_role.ec2_role_1.name
}
locals {
ec2_user_data_base = <<-END_OF_FILE
#!/bin/bash
# ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ 4GB ์ค์
sudo dd if=/dev/zero of=/swapfile bs=128M count=32
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
sudo sh -c 'echo "/swapfile swap swap defaults 0 0" >> /etc/fstab'
# ๋์ปค ์ค์น ๋ฐ ์คํ/ํ์ฑํ
yum install docker -y
systemctl enable docker
systemctl start docker
# ๋์ปค ๋คํธ์ํฌ ์์ฑ
docker network create common
# nginx ์ค์น
docker run -d \
--name npm_1 \
--restart unless-stopped \
--network common \
-p 80:80 \
-p 443:443 \
-p 81:81 \
-e TZ=Asia/Seoul \
-v /dockerProjects/npm_1/volumes/data:/data \
-v /dockerProjects/npm_1/volumes/etc/letsencrypt:/etc/letsencrypt \
jc21/nginx-proxy-manager:latest
# redis ์ค์น
docker run -d \
--name=redis_1 \
--restart unless-stopped \
--network common \
-p 6379:6379 \
-e TZ=Asia/Seoul \
redis --requirepass ${var.password_1}
# mysql ์ค์น
docker run -d \
--name mysql_1 \
--restart unless-stopped \
-v /dockerProjects/mysql_1/volumes/var/lib/mysql:/var/lib/mysql \
-v /dockerProjects/mysql_1/volumes/etc/mysql/conf.d:/etc/mysql/conf.d \
--network common \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=${var.password_1} \
-e TZ=Asia/Seoul \
mysql:latest
# MySQL ์ปจํ
์ด๋๊ฐ ์ค๋น๋ ๋๊น์ง ๋๊ธฐ
echo "MySQL์ด ๊ธฐ๋๋ ๋๊น์ง ๋๊ธฐ ์ค..."
until docker exec mysql_1 mysql -uroot -p${var.password_1} -e "SELECT 1" &> /dev/null; do
echo "MySQL์ด ์์ง ์ค๋น๋์ง ์์. 5์ด ํ ์ฌ์๋..."
sleep 5
done
echo "MySQL์ด ์ค๋น๋จ. ์ด๊ธฐํ ์คํฌ๋ฆฝํธ ์คํ ์ค..."
docker exec mysql_1 mysql -uroot -p${var.password_1} -e "
CREATE USER 'lldjlocal'@'127.0.0.1' IDENTIFIED WITH caching_sha2_password BY '1234';
CREATE USER 'lldjlocal'@'172.18.%.%' IDENTIFIED WITH caching_sha2_password BY '1234';
CREATE USER 'lldj'@'%' IDENTIFIED WITH caching_sha2_password BY '${var.password_1}';
GRANT ALL PRIVILEGES ON *.* TO 'lldjlocal'@'127.0.0.1';
GRANT ALL PRIVILEGES ON *.* TO 'lldjlocal'@'172.18.%.%';
GRANT ALL PRIVILEGES ON *.* TO 'lldj'@'%';
CREATE DATABASE glog_prod;
FLUSH PRIVILEGES;
"
echo "${var.github_access_token_1}" | docker login ghcr.io -u ${var.github_access_token_1_owner} --password-stdin
END_OF_FILE
}
data "aws_ami" "latest_amazon_linux" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-2023.*-x86_64"]
}
filter {
name = "architecture"
values = ["x86_64"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
filter {
name = "root-device-type"
values = ["ebs"]
}
}
# EC2 ์ธ์คํด์ค ์์ฑ
resource "aws_instance" "ec2_1" {
# ์ฌ์ฉํ AMI ID
ami = data.aws_ami.latest_amazon_linux.id
# EC2 ์ธ์คํด์ค ์ ํ
instance_type = "t3.micro"
# ์ฌ์ฉํ ์๋ธ๋ท ID
subnet_id = aws_subnet.subnet_2.id
# ์ ์ฉํ ๋ณด์ ๊ทธ๋ฃน ID
vpc_security_group_ids = [aws_security_group.sg_1.id]
# ํผ๋ธ๋ฆญ IP ์ฐ๊ฒฐ ์ค์
associate_public_ip_address = true
# ์ธ์คํด์ค์ IAM ์ญํ ์ฐ๊ฒฐ
iam_instance_profile = aws_iam_instance_profile.instance_profile_1.name
# ์ธ์คํด์ค์ ํ๊ทธ ์ค์
tags = {
Name = "${var.prefix}-ec2-1"
}
# ๋ฃจํธ ๋ณผ๋ฅจ ์ค์
root_block_device {
volume_type = "gp3"
volume_size = 12 # ๋ณผ๋ฅจ ํฌ๊ธฐ๋ฅผ 12GB๋ก ์ค์
}
user_data = <<-EOF
${local.ec2_user_data_base}
EOF
}