Terraform IaC AWS 구성2

Son_Doobu96·2023년 2월 9일
0

sprint Troubleshooting

목록 보기
6/7
post-thumbnail

구성하려는 아키텍처 구성도

진행 단계

▶ STEP 1 VPC 생성

1. VPC 및 서브넷 생성

  • 프라이빗 서브넷과 퍼블릭 서브넷이 각각 두개, 총 네개가 있어야 합니다.

2. VPC 보안 그룹 생성

  • 퍼블릭 웹 서버가 사용할 VPC 보안 그룹을 만들어야 합니다.
  • 프라이빗 DB 웹 서버가 사용할 VPC 보안 그룹을 만들어야 합니다.

3. DB 서브넷 그룹 생성

  • RDS 인스턴스가 사용할 VPC 서브넷 그룹을 만들어야 합니다.

▶ STEP 2 EC2 생성

만들어야 하는 사양

  • AMI: Ubuntu Server 18
  • 인스턴스 타입: t2.micro
  • 사용자 데이터
#!/bin/bash
echo "Hello, World" > index.html
nohup busybox httpd -f -p ${var.server_port} &
  • 키 페어: 수동으로 만들고 EC2에 할당합니다.

Advanced Challenges

STEP 3: 자습서: DB 인스턴스 생성

  • 자습서에 표시된 사양대로 RDS 인스턴스를 생성합니다.

STEP 4: 애플리케이션 로드 밸런서 및 Auto Scaling Group 적용

  • Auto Scaling Group은 최소 2개, 최대 10개로 설정해놓습니다.

이 포스팅에서는 Advanced Challenges를 다룹니다.


IaC 작성 참고 : Terraform Registry

▶ 진행 순서

기존과 같이 진행해야 할 순서를 정한 후 테라폼을 작성했습니다.
순서는 아래와 같이 작성했습니다.

1. RDS 생성

가장 먼저 프라이빗 서브넷에 위치할 RDS를 생성했습니다.
가장 주의할 점은 RDS를 프라이빗 서브넷으로 올바르게 위치시켜야 했기에
프라이빗 서브넷 그룹을 명시해줬습니다.

#RDS 생성
resource "aws_db_instance" "Sprint_terraform_RDS" {
  allocated_storage    = 10
  db_name              = "Sprint_terraform_RDS"
  availability_zone    = "ap-northeast-2c"
  db_subnet_group_name = "sprint_subnetgroup"
  vpc_security_group_ids = [aws_security_group.Sprint_security_DB.id]

  engine               = "mysql"
  engine_version       = "8.0"
  instance_class       = "db.t3.micro"
  username             = "admin"
  password             = "admin1234"
  skip_final_snapshot  = true
//  deletion_protection = true

  tags = {
    Name = "Sprint_terraform_RDS"
  }
}

2. 탄력적 IP 생성

다음은 탄력적 IP주소를 생성해줬습니다. 프라이빗 서브넷에 위치한 RDS와의 통신을 위해 퍼블릭 서브넷에 유동적인 IP가 아닌 고정 IP가 필요했기에 이 작업을 진행했습니다.

# 탄력적 IP 생성
resource "aws_eip" "sprint_eip" {
  vpc      = true

  tags = {
    Name = "sprint_eip"
  }
}

3. NAT Gateway 생성

프라이빗 서브넷에 위치한 RDS가 외부와 통신하기 위해 NAT Gateway를 이용했습니다.

# NAT Gateway 생성
resource "aws_nat_gateway" "sprint_natgw" {
  allocation_id = aws_eip.sprint_eip.id
  subnet_id     = aws_subnet.sprint_public2.id

  tags = {
    Name = "sprint_natgw"
  }
  depends_on = [aws_internet_gateway.sprint_gw]
}

4. 프라이빗 서브넷에 위치할 라우팅 테이블 생성

다음으로 라우팅 테이블을 세팅하여 프라이빗 서브넷과 NAT Gateway를 연결해 줬습니다.

# 프라이빗 서브넷 라우팅 테이블 생성
resource "aws_route_table" "Sprint_route_table_private" {
  vpc_id = aws_vpc.Sprint_Terraform_VPC.id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_nat_gateway.sprint_natgw.id
  }

  tags = {
    Name = "Sprint_route_table_private"
  }
}

5. 라우팅 테이블과 프라이빗 서브넷 연결

# 라우팅 테이블 - 서브넷 private1 연결
resource "aws_route_table_association" "Connect_rt_pv1" {
  subnet_id      = aws_subnet.sprint_private1.id
  route_table_id = aws_route_table.Sprint_route_table_private.id
}

# 라우팅 테이블 - 서브넷 private2 연결
resource "aws_route_table_association" "Connect_rt_pv2" {
  subnet_id      = aws_subnet.sprint_private2.id
  route_table_id = aws_route_table.Sprint_route_table_private.id
}

6. 타겟 그룹 생성

위의 작업을 진행 후 ec2 인스턴스로 rds에 접속이 가능함을 확인했고 최종적으로 오토스케일링 작업을 위해 로드밸런서를 생성하기로 했습니다.
그래서 그 이전 타겟 그룹을 생성했습니다.

# 타겟 그룹 생성
resource "aws_lb_target_group" "SprintTg" {
  name     = "SprintTg"
  port     = 8080
  protocol = "HTTP"
  vpc_id   = aws_vpc.Sprint_Terraform_VPC.id

  health_check {
    enabled = true
    healthy_threshold = 3
    interval = 10
    matcher = 200
    path = "/"
    port = "traffic-port"
    protocol = "HTTP"
    timeout = 3
    unhealthy_threshold = 2
  }
}

7. 타겟 그룹과 인스턴스 연결

# 타겟 그룹과 인스턴스 연결(sprint_terraform_EC2_2a)
resource "aws_lb_target_group_attachment" "SprintTg_attachment_2a" {
  target_group_arn = aws_lb_target_group.SprintTg.arn
  target_id        = aws_instance.sprint_terraform_EC2_2a.id
  port             = 8080
}

# 타겟 그룹과 인스턴스 연결(sprint_terraform_EC2_2c)
resource "aws_lb_target_group_attachment" "SprintTg_attachment_2c" {
  target_group_arn = aws_lb_target_group.SprintTg.arn
  target_id        = aws_instance.sprint_terraform_EC2_2c.id
  port             = 8080
}

8. 로드밸런서 생성

resource "aws_lb" "SprintAlb" {
  name               = "SprintAlb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.Sprint_security_PW.id]
  subnets            = [aws_subnet.sprint_public1.id, aws_subnet.sprint_public2.id]

  tags = {
    Environment = "SprintAlb"
  }
}

9. 로드밸런서 리스너 생성

# 로드밸런서 리스너 생성
resource "aws_lb_listener" "Sprint_alb_listner" {
  load_balancer_arn = aws_lb.SprintAlb.arn
  port              = "80"
  protocol          = "HTTP"

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

해당 작업을 완료 후
로드밸런서를 통한 DNS주소 접속이 가능함을 확인했습니다.

10. 오토스케일링 시작 템플릿 설정

오토스케일링 작업을 수행하기 위해 필요한 사전구성을 작성해줬습니다.
기존의 EC2를 생성할때 사용한 내용을 기반으로 동일한 인스턴스를 생성할 수 있도록 만들어줍니다.

# 오토스케일링 시작 템플릿 설정
resource "aws_launch_configuration" "sprint_as_config" {
  name          = "sprint_as_config"
  image_id      = "ami-0cb1d752d27600adb" # ap-northeast-2
  instance_type = "t2.micro"
  associate_public_ip_address = true
  security_groups = [aws_security_group.Sprint_security_PW.id]
  key_name = "sprint_1234"

# 사용자 데이터 입력
  user_data = <<-EOF
  #!/bin/bash
  echo "Hello, World" > index.html
  nohup busybox httpd -f -p ${var.server_port} &
  EOF

  depends_on = [
    aws_key_pair.sprint_1234
  ]
    lifecycle {
    create_before_destroy = true
  }
}

11. 오토스케일링 그룹 생성

사전 구성을 마쳤다면 실제로 오토스케일링 그룹을 생성해 인스턴스가 잘 생성되는지를 확인해줍니다.

# 오토스케일링 그룹 생성
resource "aws_autoscaling_group" "sprint_as_group" {
  name                      = "sprint_as_group"
  max_size                  = 10
  min_size                  = 2
  health_check_grace_period = 300
  health_check_type         = "ELB"
  force_delete              = true
  launch_configuration      = aws_launch_configuration.sprint_as_config.name
  vpc_zone_identifier       = [aws_subnet.sprint_public1.id, aws_subnet.sprint_public2.id]
  target_group_arns = [aws_lb_target_group.SprintTg.arn]
  
  tags = [{
      key                 = "Name"
      value               = "${var.instance_name}"
      propagate_at_launch = true
  }]
}

12. 기존 작업 수정

위의 작업까지 성공적으로 끝났을때 인스턴스가 4개가 존재하고 있었습니다.
타겟그룹에도 4개의 인스턴스가 위치하고 있었죠 그래서 기존에 인스턴스를 생성하는 리소스와 타겟그룹에 인스턴스를 추가하는 리소스를 삭제했습니다.


실습에서 느낀점

테라폼을 활용해 실습을 하면서 레지스트리를 정말 많이 뒤져가면서 대부분을 하드코딩으로 진행했습니다. 하지만 Variable, data, Output, backend, lockfile등 테라폼을 통해 활용할 수 있는 많은 기능이 있는것을 작업이 끝난 후에야 알게되어서ㅠㅠ 테라폼을 더 깊게 공부해야 겠다는 생각이 들었습니다.!

profile
DevOps를 꿈꾸는 엔지니어 지망생!

0개의 댓글