본문 바로가기

IT 엔지니어/CLOUD

AWS -NLB

provider "aws" {
    region = "ap-northeast-2"
  }
  
  # 최신 Amazon Linux 2 AMI
  data "aws_ami" "amzn2" {
    most_recent = true
    owners      = ["amazon"]
    filter {
      name   = "name"
      values = ["amzn2-ami-hvm-*-x86_64-gp2"]
    }
  }
  
  # 키페어
  resource "aws_key_pair" "tf_keypair" {
    key_name   = "tf_keypair"
    public_key = file("C:/ssh/tf_keypair.pub")
    tags = {
      Description = "TF-KeyPair"
    }
  }
  
  # VPC, Subnet
  resource "aws_vpc" "main" {
    cidr_block = "10.0.0.0/16"
  }
  
  resource "aws_subnet" "public" {
    vpc_id                  = aws_vpc.main.id
    cidr_block              = "10.0.1.0/24"
    map_public_ip_on_launch = true
    availability_zone       = "ap-northeast-2a"
  }
  
  # 인터넷 게이트웨이
  resource "aws_internet_gateway" "gw" {
    vpc_id = aws_vpc.main.id
  }
  
  resource "aws_route_table" "rt" {
    vpc_id = aws_vpc.main.id
    route {
      cidr_block = "0.0.0.0/0"
      gateway_id = aws_internet_gateway.gw.id
    }
  }
  
  resource "aws_route_table_association" "rt_assoc" {
    subnet_id      = aws_subnet.public.id
    route_table_id = aws_route_table.rt.id
  }
  
  # 보안 그룹
  resource "aws_security_group" "web_sg" {
    vpc_id = aws_vpc.main.id
  
    ingress {
      from_port   = 80
      to_port     = 80
      protocol    = "tcp"
      cidr_blocks = ["0.0.0.0/0"]
    }
  
    egress {
      from_port   = 0
      to_port     = 0
      protocol    = "-1"
      cidr_blocks = ["0.0.0.0/0"]
    }
  }
  
  # EC2 인스턴스 2개
  resource "aws_instance" "web1" {
    ami                    = data.aws_ami.amzn2.id
    instance_type          = "t3.micro"
    subnet_id              = aws_subnet.public.id
    key_name = aws_key_pair.tf_keypair.key_name
    vpc_security_group_ids = [aws_security_group.web_sg.id]
  
    user_data = <<-EOF
                #!/bin/bash
                echo "root:aws1234!" | chpasswd
                sed -i 's/^PasswordAuthentication no/PasswordAuthentication yes/' /etc/ssh/sshd_config
                sed -i 's/^#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
                systemctl restart sshd
                yum update -y
                yum install -y httpd
                sed -i 's/^Listen .*/Listen 0.0.0.0:80/' /etc/httpd/conf/httpd.conf
                echo "<h1>Web Server 1</h1>" > /var/www/html/index.html
                systemctl start httpd
                systemctl enable httpd
                EOF
  }
  
  resource "aws_instance" "web2" {
    ami                    = data.aws_ami.amzn2.id
    instance_type          = "t3.micro"
    subnet_id              = aws_subnet.public.id
    key_name               = aws_key_pair.tf_keypair.key_name
    vpc_security_group_ids = [aws_security_group.web_sg.id]
  
    user_data = <<-EOF
                #!/bin/bash
                echo "root:aws1234!" | chpasswd
                sed -i 's/^PasswordAuthentication no/PasswordAuthentication yes/' /etc/ssh/sshd_config
                sed -i 's/^#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
                systemctl restart sshd
                yum update -y
                yum install -y httpd
                sed -i 's/^Listen .*/Listen 0.0.0.0:80/' /etc/httpd/conf/httpd.conf
                echo "<h1>Web Server 2</h1>" > /var/www/html/index.html
                systemctl start httpd
                systemctl enable httpd
                EOF
  }
  
  # NLB
  resource "aws_lb" "nlb" {
    name               = "my-nlb"
    internal           = false
    load_balancer_type = "network"
    subnets            = [aws_subnet.public.id]
  }
  
  resource "aws_lb_target_group" "tg" {
    name        = "nlb-tg"
    port        = 80
    protocol    = "TCP"
    target_type = "instance"
    vpc_id      = aws_vpc.main.id
  }
  
  resource "aws_lb_target_group_attachment" "attach1" {
    target_group_arn = aws_lb_target_group.tg.arn
    target_id        = aws_instance.web1.id
    port             = 80
  }
  
  resource "aws_lb_target_group_attachment" "attach2" {
    target_group_arn = aws_lb_target_group.tg.arn
    target_id        = aws_instance.web2.id
    port             = 80
  }
  
  resource "aws_lb_listener" "listener" {
    load_balancer_arn = aws_lb.nlb.arn
    port              = 80
    protocol          = "TCP"
    default_action {
      type             = "forward"
      target_group_arn = aws_lb_target_group.tg.arn
    }
  }
  
  # 출력
  output "nlb_dns" {
    value = aws_lb.nlb.dns_name
  }
  

 

 

 

 

 

🔍 문제 원인 요약
✅ 1. NLB는 L4 (TCP) 기반
NLB는 HTTP 프로토콜을 이해하지 못하고, 단순히 TCP 포트만 로드밸런싱합니다.

브라우저는 HTTP 요청에 대해 **정상적인 응답 코드(200 등)**을 기대하지만, NLB는 그걸 보장하지 않음.

특히 웹서버가 부팅 후 포트 80이 열려 있더라도, Health Check 실패 시 트래픽 전달이 되지 않음.

✅ 2. NLB Target Group의 기본 상태 확인 방식은 TCP
EC2가 포트 80에 단순 TCP 응답만 하면 Healthy로 간주됨.

웹 서버가 아직 Apache 서비스를 띄우지 않았거나, yum update 지연 등으로 응답이 늦어지면 브라우저에서 응답 지연 또는 실패 발생 가능.

🔧 해결 방법
옵션 1: ALB 사용 (권장)
HTTP 기반 상태 확인 가능 (path = "/")

웹 브라우저와의 호환성이 뛰어남 (L7 레벨에서 동작)

로드밸런싱 동작이 눈에 보이게 확인 가능함

옵션 2: NLB에서 상태 확인과 딜레이 조정
NLB를 꼭 써야 한다면 아래처럼 health check를 잘 설정해줘야 합니다:

hcl
코드 복사
resource "aws_lb_target_group" "tg" {
  name     = "nlb-tg"
  port     = 80
  protocol = "TCP"
  target_type = "instance"
  vpc_id  = aws_vpc.main.id

  health_check {
    protocol            = "TCP"
    interval            = 30
    timeout             = 10
    healthy_threshold   = 3
    unhealthy_threshold = 3
  }
}

'IT 엔지니어 > CLOUD' 카테고리의 다른 글

AWS - Transit GW  (0) 2025.06.16
AWS - VPC Peering  (0) 2025.06.15
AWS - ALB  (0) 2025.06.13
AWS - troubleshooting  (0) 2025.06.12
AWS - Terraform -3  (0) 2025.06.11