[실습] Terraform을 통한 AWS 인프라 생성

sang yun Lee·2023년 5월 17일
0

Devops 실습

목록 보기
8/21

개요


테라폼으로 인프라를 구성하면 인프라를 손쉽게 지우고 다시 생성할 수 있다. AWS 또한 테라폼을 통해 인프라를 구성할 수 있어 실습하면서 배워보았고 실습한 결과를 공유하려 한다.

목표


테라폼을 통해서 아래와 같은 인프라 구성

실습 결과 공유


우선 AWS 콘솔을 통해 직접 리소스를 만들어본 다음, 테라폼으로 작성해보는 방식으로 진행했다.

테라폼 최종 결과 깃허브:

선수조건:

STEP 1: 인스턴스(EC2, RDS, ALB etc) 생성을 위한 환경 구성

인스턴스 생성을 위해 VPN, Routing Table, Subnet 등의 환경을 구성한다.

main.tf

테라폼의 버전 등의 테라폼 자체 설정을 해준다.

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "4.67.0"
    }
  }
  # required_version = ">= 1.3.7"
}

vpn.tf

VPN, IGW 를 생성한다.

data "aws_availability_zones" "available" {
  state = "available"
}

resource "aws_vpc" "new_vpc" {
  cidr_block  = "10.1.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support = true
  instance_tenancy = "default"

  tags = {
    Name = "TRF-VPC"
  }
}

resource "aws_internet_gateway" "new_igw" {
  vpc_id = aws_vpc.new_vpc.id
  tags = {
    Name = "TRF-IGW"
  }
}

route-table.tf

라우팅 테이블을 구성한다.

resource "aws_route_table" "public_rtb" {
  vpc_id = aws_vpc.new_vpc.id
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.new_igw.id
  }
  tags = {
    Name = "TRF-PUBC-RTB"
  }
}

resource "aws_route_table" "private_rtb" {
  vpc_id = aws_vpc.new_vpc.id
  tags = {
    Name = "TRF-PRIV-RTB"
  }
    route {
      cidr_block = "0.0.0.0/0"
      nat_gateway_id = aws_nat_gateway.ngw.id
  }
}

subnet.tf

서브넷 구성을 생성한다.

resource "aws_subnet" "public_subnet_1a" {
  vpc_id = aws_vpc.new_vpc.id
  cidr_block = "10.1.0.0/20"
  map_public_ip_on_launch = true
  availability_zone = data.aws_availability_zones.available.names[0]
  tags = {
    Name = "TRF-PUBLIC-SUBNET-1A"
  }
}
resource "aws_subnet" "private_subnet_1a" {
  vpc_id = aws_vpc.new_vpc.id
  cidr_block = "10.1.128.0/20"
  availability_zone = data.aws_availability_zones.available.names[0]
  tags = {
    Name = "TRF-PRIVATE-SUBNET-1A"
  }
}
resource "aws_subnet" "public_subnet_2c" {
  vpc_id = aws_vpc.new_vpc.id
  cidr_block = "10.1.16.0/20"
  map_public_ip_on_launch = true
  availability_zone = data.aws_availability_zones.available.names[2]
  tags = {
    Name = "TRF-PUBLIC-SUBNET-2C"
  }
}
resource "aws_subnet" "private_subnet_2c" {
  vpc_id = aws_vpc.new_vpc.id
  cidr_block = "10.1.144.0/20"
  availability_zone = data.aws_availability_zones.available.names[2]
  tags = {
    Name = "TRF-PRIVATE-SUBNET-2C"
  }
}

# 어떤 서브넷이 어떤 라우팅 테이블을 가지는지를 정의함
resource "aws_route_table_association" "public_subnet_1a_association" {
  subnet_id = aws_subnet.public_subnet_1a.id
  route_table_id = aws_route_table.public_rtb.id
}
resource "aws_route_table_association" "public_subnet_2c_association" {
  subnet_id = aws_subnet.public_subnet_2c.id
  route_table_id = aws_route_table.public_rtb.id
}
resource "aws_route_table_association" "private_subnet_1a_association" {
  subnet_id = aws_subnet.private_subnet_1a.id
  route_table_id = aws_route_table.private_rtb.id
}
resource "aws_route_table_association" "private_subnet_2c_association" {
  subnet_id = aws_subnet.private_subnet_2c.id
  route_table_id = aws_route_table.private_rtb.id
}

nat-gateway.tf

nat-gateway 생성

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.public_subnet_1a.id

  tags = {
    Name = "gw NAT"
  }

  depends_on = [aws_internet_gateway.new_igw]
}

security-group.tf

보안 그룹 설정

# vi terra-ec2.tf
resource "aws_security_group" "backend" {

  name = var.backend_sg_name
  vpc_id = "${aws_vpc.new_vpc.id}"

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["211.184.118.141/32"] # 내 IP
  }
  ingress {
    from_port   = -1
    to_port     = -1
    protocol    = "icmp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
  tags = {
    Name = "TRF-SG-backend"
  }
}

resource "aws_security_group" "db" {

  name = var.db_sg_name
  vpc_id = "${aws_vpc.new_vpc.id}"

  ingress {
    from_port   = 3306
    to_port     = 3306
    protocol    = "tcp"
    security_groups = [aws_security_group.backend.id]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
  tags = {
    Name = "TRF-SG-db"
  }
}

STEP 2: 인스턴스(EC2, RDS, Autoscaling) 생성

instance.tf

EC2를 생성한다.

# EC2 생성
resource "aws_instance" "backend" {
  ami                    = "ami-0970cc54a3aa77466"
  instance_type          = "t2.micro"
  subnet_id              = "${aws_subnet.public_subnet_1a.id}"
  vpc_security_group_ids = [aws_security_group.backend.id]
  key_name  = "key"
	user_data = <<-EOT
            #!/bin/bash
            echo "Hello, World" > index.html
            nohup busybox httpd -f -p 80 &
  EOT

  tags = {
    Name = "terraform-example"
  }
}

db.tf

MYSQL DB 를 생성

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

# DB 생성
resource "aws_db_instance" "db" {
  allocated_storage    = 20
  db_name              = "test"
  engine               = "mysql"
  engine_version       = "8.0"
  instance_class       = "db.t3.micro"
  username             = "sori"
  password             = "dltkddbs"
  identifier           = "trf-rds"
  skip_final_snapshot  = true
  vpc_security_group_ids = [aws_security_group.db.id]
  availability_zone = aws_subnet.private_subnet_1a.availability_zone
  db_subnet_group_name = aws_db_subnet_group.dbsubg.name
  tags = {
      "Name" = "TRF-MYSQL"
  }
}

target-group.tf

타겟 그룹 생성

resource "aws_lb_target_group" "backend" {
  name     = "tf-backend-lb-tg"
  port     = 80
  protocol = "HTTP"
  target_type = "instance"
  vpc_id   = aws_vpc.new_vpc.id
  health_check {
    interval  = 10
    matcher   = "200-299"
    path      = "/"
  }
}

resource "aws_lb_target_group_attachment" "test" {
  target_group_arn = aws_lb_target_group.backend.arn
  target_id        = aws_instance.backend.id
  port             = 80
}

alb.tf

Application Load Balancer리스너 생성

# ALB 생성
  resource "aws_lb" "alb" {
  name               = "trf-alb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.backend.id]
  subnets            = [
    aws_subnet.public_subnet_1a.id,
    aws_subnet.public_subnet_2c.id
    ]
}

# 리스너 생성
resource "aws_lb_listener" "backend" {
  load_balancer_arn = aws_lb.alb.arn
  port              = "80"
  protocol          = "HTTP"

  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.backend.arn
  }
}

auto-scale.tf

Auto-Scaling Group 생성

# EC2 템플릿 생성
resource "aws_launch_configuration" "as_conf" {
  name_prefix   = "terraform-lc-backend"
  image_id      = "ami-0970cc54a3aa77466"
  instance_type = "t2.micro"
  key_name = "key"
	user_data = <<-EOT
            #!/bin/bash
            echo "Hello, World" > index.html
            nohup busybox httpd -f -p 80 &
  EOT
  security_groups = [aws_security_group.backend.id]
  lifecycle {
    create_before_destroy = true
  }
}

# Auto-Scaling 그룹 생성
resource "aws_autoscaling_group" "bar" {
  name                      = "terraform-asg-backend"
  launch_configuration      = aws_launch_configuration.as_conf.name
  vpc_zone_identifier       = [aws_subnet.public_subnet_1a.id, aws_subnet.public_subnet_2c.id]
  min_size                  = 2
  max_size                  = 4
  desired_capacity          = 3
  health_check_grace_period = 120
  health_check_type         = "ELB"
  target_group_arns    = [aws_lb_target_group.backend.arn]
  lifecycle {
    create_before_destroy = true
  }
}

STEP 3: Terraform 인프라 배포

다음의 순서대로 실행하여 배포를 진행한다.

terraform init
terraform plan
terraform apply

실습 후기


테라폼 모듈 을 통해서 보다 가독성 좋게 IaC 를 생성할 수 있지만 아직 알지 못해 진행하지 못했다. 다음에는 테라폼 모듈을 적용해서 진행해보려 한다.

0개의 댓글