Full Stack 애플리케이션 구성-2

이준석·2023년 2월 8일
0

Bare Minimum Requirement

다음의 아키텍처를 terraform을 이용해 작성합니다.


Terraform 작성: 공식 문서


1. 요구사항 작성

main.tf 파일을 만들고 terraform에서 요구되는 사항을 작성했다.

# 요구사항 작성
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.16"
    }
  }
}

provider "aws" {
  region = "ap-northeast-2"
}

2. VPC 생성

vpc.tf 파일을 만들고 myvpc를 생성했다.

# VPC 생성
resource "aws_vpc" "myvpc" {
  cidr_block       = "10.0.0.0/16"

  tags = {
    Name = "sprint-vpc"
  }
}

3. Subnet 생성

subnet.tf 파일을 만들고 퍼블릭 서브넷 2개, 프라이빗 서브넷 2개를 생성했다.

퍼블릭 서브넷

# 퍼블릭 서브넷 생성
resource "aws_subnet" "pubsub1" {
  vpc_id     = aws_vpc.myvpc.id
  cidr_block = "10.0.1.0/24"
  availability_zone = "ap-northeast-2a"
  map_public_ip_on_launch = true

  tags = {
    Name = "sprint-pub-sub-1"
  }
}

resource "aws_subnet" "pubsub2" {
  vpc_id     = aws_vpc.myvpc.id
  cidr_block = "10.0.2.0/24"
  availability_zone = "ap-northeast-2c"
  map_public_ip_on_launch = true

  tags = {
    Name = "sprint-pub-sub-2"
  }
}

프라이빗 서브넷

# 프라이빗 서브넷 생성
resource "aws_subnet" "prvsub1" {
  vpc_id     = aws_vpc.myvpc.id
  cidr_block = "10.0.3.0/24"
  availability_zone = "ap-northeast-2a"

  tags = {
    Name = "sprint-prv-sub-1"
  }
}

resource "aws_subnet" "prvsub2" {
  vpc_id     = aws_vpc.myvpc.id
  cidr_block = "10.0.4.0/24"
  availability_zone = "ap-northeast-2c"

  tags = {
    Name = "sprint-prv-sub-2"
  }
}

4. 라우팅 테이블 생성

퍼블릭 서브넷 라우팅 테이블

퍼블릭 서브넷 라우팅 테이블을 생성하고 인터넷 게이트웨이에 연결시켰다.

# IGW 생성
resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.myvpc.id

  tags = {
    Name = "sprint-igw"
  }
}

# 라우팅 테이블 생성
resource "aws_route_table" "pubroutetable" {
  vpc_id = aws_vpc.myvpc.id
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.igw.id
  }

  tags = {
    Name = "sprint-public-route-table"
  }
}

# 라우팅 테이블 연결
resource "aws_route_table_association" "pubassociation1" {
  subnet_id      = aws_subnet.pubsub1.id
  route_table_id = aws_route_table.pubroutetable.id
}

resource "aws_route_table_association" "pubassociation2" {
  subnet_id      = aws_subnet.pubsub2.id
  route_table_id = aws_route_table.pubroutetable.id
}

프라이빗 서브넷 라우팅 테이블

프라이빗 서브넷 라우팅 테이블을 생성하고 NAT 게이트웨이에 연결시켰다.

# NGW 생성
resource "aws_eip" "eip" {
  vpc   = true

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_nat_gateway" "ngw" {
  allocation_id = aws_eip.eip.id
  subnet_id = aws_subnet.pubsub1.id

  tags = {
    Name = "sprint-ngw"
  }
}

# 라우팅 테이블 생성
resource "aws_route_table" "prvroutetable" {
  vpc_id = aws_vpc.myvpc.id

  tags = {
    Name = "sprint-prv-route-table"
  }
}

# 라우팅 테이블 연결
resource "aws_route_table_association" "prvassociation1" {
  subnet_id      = aws_subnet.prvsub1.id
  route_table_id = aws_route_table.prvroutetable.id
}

resource "aws_route_table_association" "prvassociation2" {
  subnet_id      = aws_subnet.prvsub2.id
  route_table_id = aws_route_table.prvroutetable.id
}

resource "aws_route" "prvroute" {
  route_table_id         = aws_route_table.prvroutetable.id
  destination_cidr_block = "0.0.0.0/0"
  nat_gateway_id         = aws_nat_gateway.ngw.id
}

5. 보안 그룹 생성

퍼블릭 보안 그룹

퍼블릭 보안 그룹을 생성하고 22, 80, 8080, 0.0.0.0/0의 인바운드 규칙을 설정했다.

#퍼블릭 보안 그룹 생성
resource "aws_security_group" "pubsg" {
    vpc_id = aws_vpc.myvpc.id
    name = "sprint-pub-sg"
    description = "sprint-pub-sg"

    tags = {
        Name = "sprint-pub-sg"
    }
}

#퍼블릭 보안 그룹 규칙
resource "aws_security_group_rule" "pubsghttp" {
    type = "ingress"
    from_port = 80
    to_port=80
    protocol = "TCP"
    cidr_blocks = ["0.0.0.0/0"]
    security_group_id = aws_security_group.pubsg.id
    lifecycle{
        create_before_destroy = true
    }
}

resource "aws_security_group_rule" "pubsghttp2" {
    type = "ingress"
    from_port = 8080
    to_port=8080
    protocol = "TCP"
    cidr_blocks = ["0.0.0.0/0"]
    security_group_id = aws_security_group.pubsg.id
    lifecycle{
        create_before_destroy = true
    }
}

resource "aws_security_group_rule" "pubsgssh" {
    type = "ingress"
    from_port = 22
    to_port= 22
    protocol = "TCP"
    cidr_blocks=["0.0.0.0/0"]
    security_group_id = aws_security_group.pubsg.id
    lifecycle{
        create_before_destroy = true
    }
}

resource "aws_security_group_rule" "pubsgall" {
    type = "egress"
    from_port = 0
    to_port= 0
    protocol = "-1"
    cidr_blocks=["0.0.0.0/0"]
    security_group_id = aws_security_group.pubsg.id
    lifecycle{
        create_before_destroy = true
    }
}

프라이빗 보안 그룹

프라이빗 보안 그룹을 생성하고 3306포트 인바운드 규칙을 설정했다.

#프라이빗 보안 그룹 생성
resource "aws_security_group" "prvsg" {
    vpc_id = aws_vpc.myvpc.id
    name = "sprint-prv-sg"
    description = "sprint-prv-sg"

    tags = {
        Name = "sprint-prv-sg"
    }
}
#프라이빗 보안 그룹 규칙
resource "aws_security_group_rule" "prvsgrds" {
    type = "ingress"
    from_port = 3306
    to_port= 3306
    protocol = "TCP"
    cidr_blocks=["0.0.0.0/0"]
    security_group_id = aws_security_group.prvsg.id
    lifecycle{
        create_before_destroy = true
    }
}

resource "aws_security_group_rule" "prvsgrds2" {
    type = "egress"
    from_port = 0
    to_port= 0
    protocol = "-1"
    cidr_blocks=["0.0.0.0/0"]
    security_group_id = aws_security_group.prvsg.id
    lifecycle{
        create_before_destroy = true
    }
}

6. EC2 생성

key pair를 현재 디렉토리에 생성하고 연결시킨 뒤, EC2를 두 개 생성했다.

# 키페어 생성
resource "aws_key_pair" "ec2key" {
	key_name = "sprint-key"
  public_key = file("./sprint-key.pub")
}

#EC2 생성
resource "aws_instance" "ec21" {
    ami = "ami-0cb1d752d27600adb"
    instance_type = "t2.micro"
    security_groups = [aws_security_group.pubsg.id]
    subnet_id = aws_subnet.pubsub1.id
    key_name = aws_key_pair.ec2key.key_name
    associate_public_ip_address = "true"
    user_data = <<-EOF
        #!/bin/bash
        echo "Hello, World" > index.html
        nohup busybox httpd -f -p ${var.server_port} &
        EOF

    tags ={ 
	    Name = "sprint-ec21"
    }
}

resource "aws_instance" "ec22" {
    ami = "ami-0cb1d752d27600adb"
    instance_type = "t2.micro"
    security_groups = [aws_security_group.pubsg.id]
    subnet_id = aws_subnet.pubsub2.id
    key_name = aws_key_pair.ec2key.key_name
    associate_public_ip_address = "true"
    user_data = <<-EOF
        #!/bin/bash
        echo "Hello, World" > index.html
        nohup busybox httpd -f -p ${var.server_port} &
        EOF

    tags ={ 
	    Name = "sprint-ec22"
    }
}

7. RDS 생성

DB 서브넷 그룹을 만들고 RDS를 생성했다.

# DB 서브넷 그룹 생성
resource "aws_db_subnet_group" "dbsubg" {
  name = "sprint-db-subg"
  subnet_ids = [
    aws_subnet.prvsub1.id,
    aws_subnet.prvsub2.id
  ]
  tags = {
    "Name" = "sprint-db-subg"
  }
}

# RDS 생성
resource "aws_db_instance" "dbrds" { 
    allocated_storage = 20
    skip_final_snapshot = true
    availability_zone = "ap-northeast-2a"
    vpc_security_group_ids = [aws_security_group.prvsg.id ]
    db_subnet_group_name = aws_db_subnet_group.dbsubg.name
    engine = "mysql"
    engine_version = "8.0.28"
    instance_class = "db.t3.micro"
    db_name = "sprintrds"
    username = var.username
    password = var.password

    tags = {
        "Name" = "sprint-rds"
    }
}

variable 파일에 민감 정보 다루기: 공식 문서


8. ALB 생성

ALB를 만들고 EC2 인스턴스 두 개를 타겟으로 지정하고 타겟 그룹으로 만든 뒤, 80 포트 Forward 방식으로 리스너를 생성했다.

# ALB 생성
  resource "aws_alb" "alb" {
  name               = "sprint-alb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.pubsg.id]
  subnets            = [
    aws_subnet.pubsub1.id,
    aws_subnet.pubsub2.id
    ]
  enable_cross_zone_load_balancing = true
}

# 타켓 그룹 생성
  resource "aws_alb_target_group" "albtg" {
  name     = "sprint-alb-tg"
  port     = 8080
  protocol = "HTTP"
  vpc_id   = aws_vpc.myvpc.id
}

# 인스턴스 연결
resource "aws_alb_target_group_attachment" "albtg1" {
  target_group_arn = aws_alb_target_group.albtg.arn
  target_id        = aws_instance.ec21.id
  port             = 8080
}

resource "aws_alb_target_group_attachment" "albtg2" {
  target_group_arn = aws_alb_target_group.albtg.arn
  target_id        = aws_instance.ec22.id
  port             = 8080
}

# 리스너 생성
resource "aws_alb_listener" "alblis" {
  load_balancer_arn = aws_alb.alb.arn
  port              = 80
  protocol          = "HTTP"

  default_action {
    type             = "forward"
    target_group_arn = aws_alb_target_group.albtg.arn
  }
}

9. Auto Scailing 생성

최소 2개, 최대 10개로 오토 스케일링 그룹을 생성했다.

# 시작 구성 생성
  resource "aws_launch_configuration" "launch" {
    name_prefix = "laun-"
    image_id = "ami-0cb1d752d27600adb"
    instance_type = "t2.micro"
    security_groups = [aws_security_group.pubsg.id]
    user_data = <<-EOF
         #!/bin/bash
         echo "Hello, World" > index.html
         nohup busybox httpd -f -p ${var.server_port} &
         EOF
    lifecycle {
    create_before_destroy = true
    }
  }

# Auto Scailing 그룹 생성
  resource "aws_autoscaling_group" "autogr" {
    name = "sprint-auto"
    launch_configuration = aws_launch_configuration.launch.name
    vpc_zone_identifier = [
        aws_subnet.pubsub1.id,
        aws_subnet.pubsub2.id
        ]
    health_check_type = "ELB"
    target_group_arns = [aws_alb_target_group.albtg.arn]
    force_delete = true

    min_size = 2
    max_size = 10

    tag {
        key                 = "Name"
        value               = "sprint-auto"
        propagate_at_launch = true
  }
}

0개의 댓글