Home
home

4장 실습 - ALB와 NLB를 통한 부하 분산

1. CloudFormation을 통한 기본 인프라 배포

이번 실습의 기본 인프라 구성을 CloudFormation을 통해 스택을 생성하고 자원을 배포할 것입니다.
CloudFormation 템플릿 다운로드
아래 CloudFormation 템플릿 파일을 다운로드합니다.
CH4_LAB1.yaml
8.2 KB
Parameters: KeyName: Description: Name of an existing EC2 KeyPair to enable SSH access to the instances. Linked to AWS Parameter Type: AWS::EC2::KeyPair::KeyName ConstraintDescription: must be the name of an existing EC2 KeyPair. InstanceType: Description: Enter t2.nano, t2.micro Default is t2.micro. Type: String Default: t2.micro AllowedValues: - t2.nano - t2.micro LatestAmiId: Description: (DO NOT CHANGE) Type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>' Default: '/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64' AllowedValues: - /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64 Resources: ELBVPC: Type: AWS::EC2::VPC Properties: CidrBlock: 10.4.0.0/16 EnableDnsSupport: true EnableDnsHostnames: true Tags: - Key: Name Value: ELB-VPC MyVPC: Type: AWS::EC2::VPC Properties: CidrBlock: 20.0.0.0/16 Tags: - Key: Name Value: MY-VPC ELBIGW: Type: AWS::EC2::InternetGateway Properties: Tags: - Key: Name Value: ELB-IGW MyIGW: Type: AWS::EC2::InternetGateway Properties: Tags: - Key: Name Value: MY-IGW ELBIGWAttachment: Type: AWS::EC2::VPCGatewayAttachment Properties: InternetGatewayId: !Ref ELBIGW VpcId: !Ref ELBVPC MyIGWAttachment: Type: AWS::EC2::VPCGatewayAttachment Properties: InternetGatewayId: !Ref MyIGW VpcId: !Ref MyVPC ELBPublicRT: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref ELBVPC Tags: - Key: Name Value: ELB-PUBLIC-RT ELBDefaultPublicRoute: Type: AWS::EC2::Route DependsOn: ELBIGWAttachment Properties: RouteTableId: !Ref ELBPublicRT DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref ELBIGW MyPublicRT: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref MyVPC Tags: - Key: Name Value: MY-PUBLIC-RT MyDefaultPublicRoute: Type: AWS::EC2::Route DependsOn: MyIGWAttachment Properties: RouteTableId: !Ref MyPublicRT DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref MyIGW ELBPublicSN1: Type: AWS::EC2::Subnet Properties: VpcId: !Ref ELBVPC AvailabilityZone: !Select [ 0, !GetAZs '' ] CidrBlock: 10.4.0.0/24 Tags: - Key: Name Value: ELB-PUBLIC-SN-1 ELBPublicSN2: Type: AWS::EC2::Subnet Properties: VpcId: !Ref ELBVPC AvailabilityZone: !Select [ 2, !GetAZs '' ] CidrBlock: 10.4.1.0/24 Tags: - Key: Name Value: ELB-PUBLIC-SN-2 MyPublicSN: Type: AWS::EC2::Subnet Properties: VpcId: !Ref MyVPC AvailabilityZone: !Select [ 0, !GetAZs '' ] CidrBlock: 20.0.0.0/24 Tags: - Key: Name Value: MY-PUBLIC-SN ELBPublicSNRouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref ELBPublicRT SubnetId: !Ref ELBPublicSN1 ELBPublicSNRouteTableAssociation2: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref ELBPublicRT SubnetId: !Ref ELBPublicSN2 MyPublicSNRouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref MyPublicRT SubnetId: !Ref MyPublicSN MySG: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Enable HTTP access via port 80 and SSH access via port 22 VpcId: !Ref MyVPC Tags: - Key: Name Value: MY-SG SecurityGroupIngress: - IpProtocol: tcp FromPort: '22' ToPort: '22' CidrIp: 0.0.0.0/0 - IpProtocol: icmp FromPort: -1 ToPort: -1 CidrIp: 0.0.0.0/0 ELBSG: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Enable HTTP access via port 80 and SSH access via port 22 VpcId: !Ref ELBVPC Tags: - Key: Name Value: ELB-SG SecurityGroupIngress: - IpProtocol: tcp FromPort: '80' ToPort: '80' CidrIp: 0.0.0.0/0 - IpProtocol: udp FromPort: '161' ToPort: '161' CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: '22' ToPort: '22' CidrIp: 0.0.0.0/0 - IpProtocol: icmp FromPort: -1 ToPort: -1 CidrIp: 0.0.0.0/0 MyEC2: Type: AWS::EC2::Instance Properties: InstanceType: !Ref InstanceType ImageId: !Ref LatestAmiId KeyName: !Ref KeyName Tags: - Key: Name Value: MY-EC2 NetworkInterfaces: - DeviceIndex: 0 SubnetId: !Ref MyPublicSN GroupSet: - !Ref MySG AssociatePublicIpAddress: true UserData: Fn::Base64: !Sub | #!/bin/bash hostnamectl --static set-hostname MyEC2 dnf install net-snmp-utils tcpdump -y ELBEC21: Type: AWS::EC2::Instance Properties: InstanceType: !Ref InstanceType ImageId: !Ref LatestAmiId KeyName: !Ref KeyName Tags: - Key: Name Value: SERVER-1 NetworkInterfaces: - DeviceIndex: 0 SubnetId: !Ref ELBPublicSN1 GroupSet: - !Ref ELBSG AssociatePublicIpAddress: true UserData: Fn::Base64: !Sub | #!/bin/bash hostnamectl --static set-hostname SERVER-1 dnf install httpd net-snmp net-snmp-utils tcpdump -y systemctl start httpd && systemctl enable httpd echo 'rocommunity public default' >> /etc/snmp/snmpd.conf systemctl start snmpd && systemctl enable snmpd echo "<h1>SERVER-1 Web Server</h1>" > /var/www/html/index.html mkdir /var/www/html/dev echo "<h1>SERVER-1 DEV Web Page</h1>" > /var/www/html/dev/index.html ELBEC22: Type: AWS::EC2::Instance Properties: InstanceType: !Ref InstanceType ImageId: !Ref LatestAmiId KeyName: !Ref KeyName Tags: - Key: Name Value: SERVER-2 NetworkInterfaces: - DeviceIndex: 0 SubnetId: !Ref ELBPublicSN2 GroupSet: - !Ref ELBSG AssociatePublicIpAddress: true UserData: Fn::Base64: !Sub | #!/bin/bash hostnamectl --static set-hostname SERVER-2 dnf install httpd net-snmp net-snmp-utils tcpdump -y systemctl start httpd && systemctl enable httpd echo 'rocommunity public default' >> /etc/snmp/snmpd.conf systemctl start snmpd && systemctl enable snmpd echo "<h1>SERVER-2 Web Server</h1>" > /var/www/html/index.html mkdir /var/www/html/mgt echo "<h1>SERVER-2 MGT Web Page</h1>" > /var/www/html/mgt/index.html ELBEC23: Type: AWS::EC2::Instance Properties: InstanceType: !Ref InstanceType ImageId: !Ref LatestAmiId KeyName: !Ref KeyName Tags: - Key: Name Value: SERVER-3 NetworkInterfaces: - DeviceIndex: 0 SubnetId: !Ref ELBPublicSN2 GroupSet: - !Ref ELBSG AssociatePublicIpAddress: true UserData: Fn::Base64: !Sub | #!/bin/bash hostnamectl --static set-hostname SERVER-3 dnf install httpd net-snmp net-snmp-utils tcpdump -y systemctl start httpd && systemctl enable httpd echo 'rocommunity public default' >> /etc/snmp/snmpd.conf systemctl start snmpd && systemctl enable snmpd echo "<h1>SERVER-3 Web Server</h1>" > /var/www/html/index.html mkdir /var/www/html/mgt echo "<h1>SERVER-3 MGT Web Page</h1>" > /var/www/html/mgt/index.html Outputs: server1: Value: !GetAtt ELBEC21.PublicIp server2: Value: !GetAtt ELBEC22.PublicIp server3: Value: !GetAtt ELBEC23.PublicIp
YAML
복사
# CH4_LAB1.yaml 파일 내용
CloudFormation 스택 생성 설정
CloudFormation 서비스 → 스택 (메뉴 진입) → 스택 생성 (버튼 클릭)
1단계 - 스택 생성
템플릿 준비: 기존 템플릿 선택 (선택)
템플릿 소스: 템플릿 파일 업로드 (선택)
파일 선택 → 템플릿 파일 선택 (CH4_LAB1.yaml) → 열기
다음 (버튼 클릭)
2단계 - 스택 세부 정보 지정
스택 이름: LAB4-CF (입력)
InstanceType: t2.micro or t2.nano
KeyName: 각자 생성한 키 페어 (선택)
InstanceType: t2.micro 혹은 t2.nano (선택)
다음 (버튼 클릭)
3단계 - 스택 옵션 구성
다음 (버튼 클릭)
4단계 - 검토 및 작성
전송 (버튼 클릭)
생성 자원 확인
VPC
VPC 서비스 → VPC (메뉴 진입) → 대상 VPC (선택)
리소스 맵 (탭 진입)
EC2 인스턴스
EC2 서비스 → 인스턴스 (메뉴 진입) → 대상 인스턴스 (선택)
보안 그룹
EC2 서비스 → 보안 그룹 (메뉴 진입) → 대상 보안 그룹 (선택)
인바운드 규칙 (탭 진입)
CloudFormation
CloudFormation 서비스 → 스택 (메뉴 진입) → 출력 (탭 진입)
Server1, Server2, Server3의 퍼블릭 IP 주소 확인
기본 통신 확인
SVR1=[각자의 SERVER-1 IP] SVR2=[각자의 SERVER-2 IP] SVR3=[각자의 SERVER-3 IP]
Bash
복사
# SERVER-1, SERVER-2, SERVER-3의 퍼블릭 IP 주소 변수 선언
echo $SVR1 echo $SVR2 echo $SVR3
Bash
복사
CloudFormation 스택에서 출력 탭에서 각각의 퍼블릭 IP 주소를 확인합니다.
curl $SVR1 curl $SVR1/dev/ curl $SVR1/mgt/
Bash
복사
# SERVER-1의 HTTP 접근
curl $SVR2 curl $SVR2/dev/ curl $SVR2/mgt/
Bash
복사
# SERVER-2의 HTTP 접근
curl $SVR3 curl $SVR3/dev/ curl $SVR3/mgt/
Bash
복사
# SERVER-1의 HTTP 접근
snmpget -v2c -c public $SVR1 1.3.6.1.2.1.1.5.0 snmpget -v2c -c public $SVR2 1.3.6.1.2.1.1.5.0 snmpget -v2c -c public $SVR3 1.3.6.1.2.1.1.5.0
Bash
복사
# SERVER-1/2/3에 대한 SNMP GET

2. ALB 생성 및 검증

Amazon ELB의 로드 밸런서 중에 ALB를 생성하고 통신 검증을 수행합니다.

2.1. ALB 생성 및 부하 분산 확인

대상 그룹(ALB-TG) 생성
EC2 서비스 → 로드 밸런싱 → 대상 그룹 (메뉴 진입) → 대상 그룹 생성 (버튼 클릭)
1단계 - 그룹 세부 정보 지정
대상 유형 선택: 인스턴스 (선택)
대상 그룹 이름: ALB-TG (입력)
프로토콜: HTTP
포트: 80
VPC: ELB-VPC (선택)
상태 검사 프로토콜: HTTP
상태 검사 경로: /
다음 (버튼 클릭)
2단계 - 대상 등록
사용 가능한 인스턴스: SERVER-1, SERVER-2, SERVER-3 (선택)
아래에 보류 중인 것으로 포함 (버튼 클릭)
대상 그룹 생성 (버튼 클릭)
로드 밸런서(ALB) 생성
EC2 서비스 → 로드 밸런싱 → 로드 밸런서 (메뉴 진입) → 로드 밸런서 생성 (버튼 클릭)
로드 밸런서 유형: Application Load Balancer → 생성 (버튼 클릭)
로드 밸런서 이름: LAB4-ALB (입력)
체계: 인터넷 경계 (선택)
VPC: ELB-VPC (선택)
가용 영역 및 서브넷: ap-northeast-2a, ap-northeast-2c (체크)
서브넷: ELB-PUBLIC-SN-1, ELB-PUBLIC-SN-2 (선택)
보안 그룹
default (삭제)
LAB4-CF-ELBSG… (선택)
리스너
프로토콜: HTTP
포트: 80
대상 그룹 선택: ALB-TG (선택)
로드 밸런서 생성 (버튼 클릭)
ALB DNS 주소 확인
EC2 서비스 → 로드 밸런싱 → 로드 밸런서 (메뉴 진입) → LAB4-ALB (체크)
세부 정보 → DNS 이름 (복사 아이콘 클릭)
ALB 부하 분산 검증
ALB_DNS=[ALB_DNS_ADDRESS]
Bash
복사
# ALB 도메인 주소 변수 지정
dig +short $ALB_DNS
Bash
복사
# ALB 도메인 주소 해석
curl $ALB_DNS
Bash
복사
# HTTP 1회 접근
for i in {1..60}; do curl $ALB_DNS --silent ; done | sort | uniq -c | sort -nr
Bash
복사
# HTTP 60회 접근 (반복문)

2.2. ALB 고급 라우팅 확인 (경로 기반 라우팅)

경로 기반 HTTP 접근
curl $ALB_DNS/dev/ --silent
Bash
복사
# dev 경로로 HTTP 1회 접근
curl $ALB_DNS/mgt/ --silent
Bash
복사
# mgt 경로로 HTTP 1회 접근
DEV-TG 대상 그룹 생성
EC2 서비스 → 로드 밸런싱 → 대상 그룹 (메뉴 진입) → 대상 그룹 생성 (버튼 클릭)
1단계 - 그룹 세부 정보 지정
대상 유형 선택: 인스턴스 (선택)
대상 그룹 이름: DEV-TG (입력)
VPC: ELB-VPC (선택)
다음 (버튼 클릭)
2단계 - 대상 등록
사용 가능한 인스턴스: SERVER-1 (선택)
아래에 보류 중인 것으로 포함 (버튼 클릭)
대상 그룹 생성 (버튼 클릭)
MGT-TG 대상 그룹 생성
EC2 서비스 → 로드 밸런싱 → 대상 그룹 (메뉴 진입) → 대상 그룹 생성 (버튼 클릭)
1단계 - 그룹 세부 정보 지정
대상 유형 선택: 인스턴스 (선택)
대상 그룹 이름: MGT-TG (입력)
VPC: ELB-VPC (선택)
다음 (버튼 클릭)
2단계 - 대상 등록
사용 가능한 인스턴스: SERVER-2, SERVER-3 (선택)
아래에 보류 중인 것으로 포함 (버튼 클릭)
대상 그룹 생성 (버튼 클릭)
로드 밸런서 - 규칙 추가
EC2 서비스 → 로드 밸런싱 → 로드 밸런서 (메뉴 진입) → LAB4-ALB (선택) → 리스너 및 규칙 (탭 진입)
대상 리스너 선택 (체크) → 규칙 관리 (버튼 클릭) → 규칙 추가 (선택)
dev 규칙 추가
조건 추가 (버튼 클릭) → 경로 (선택)
경로 조건 값: /dev/*
라우팅 액션: 대상 그룹으로 전달 (선택)
대상 그룹: DEV-TG (선택)
다음 (버튼 클릭)
우선 순위: 10
다음 (버튼 클릭)
생성 (버튼 클릭)
mgt 규칙 추가
조건 추가 (버튼 클릭) → 경로 (선택)
경로 조건 값: /mgt/*
라우팅 액션: 대상 그룹으로 전달 (선택)
대상 그룹: MGT-TG (선택)
다음 (버튼 클릭)
우선 순위: 20
다음 (버튼 클릭)
생성 (버튼 클릭)

2.3. ALB 고급 라우팅 확인 (HTTP 헤더 기반 라우팅)

로드 밸런서 - 규칙 추가
EC2 서비스 → 로드 밸런싱 → 로드 밸런서 (메뉴 진입) → LAB4-ALB (선택) → 리스너 및 규칙 (탭 진입)
대상 리스너 선택 (체크) → 규칙 관리 (버튼 클릭) → 규칙 추가 (선택)
User Agent 규칙 추가
조건 추가 (버튼 클릭) → HTTP 헤더 (선택)
HTTP 헤더 이름: User-Agent
HTTP 헤더 값: *iPhone*
OR 조건 값 추가 (클릭)
HTTP 헤더 값: *Android*
라우팅 액션: 고정 응답 반환 (선택)
응답 본문: Smart Phone Access Deny!!
다음 (버튼 클릭)
우선 순위: 30
다음 (버튼 클릭)
생성 (버튼 클릭)

3. NLB 생성 및 검증

Amazon ELB의 로드 밸런서 중에 NLB를 생성하고 통신 검증을 수행합니다.

3.1. NLB 생성 및 부하 분산 확인

대상 그룹(NLB-TG) 생성
EC2 서비스 → 로드 밸런싱 → 대상 그룹 (메뉴 진입) → 대상 그룹 생성 (버튼 클릭)
1단계 - 그룹 세부 정보 지정
대상 유형 선택: 인스턴스 (선택)
대상 그룹 이름: NLB-TG (입력)
프로토콜: UDP
포트: 161
VPC: ELB-VPC (선택)
상태 검사 프로토콜: HTTP
상태 검사 경로: /
고급 상태 검사 설정 (확장)
상태 검사 포트: 재정의 (선택)
80 (유지)
다음 (버튼 클릭)
2단계 - 대상 등록
사용 가능한 인스턴스: SERVER-1, SERVER-2, SERVER-3 (선택)
아래에 보류 중인 것으로 포함 (버튼 클릭)
대상 그룹 생성 (버튼 클릭)
로드 밸런서(NLB) 생성
EC2 서비스 → 로드 밸런싱 → 로드 밸런서 (메뉴 진입) → 로드 밸런서 생성 (버튼 클릭)
로드 밸런서 유형: Network Load Balancer → 생성 (버튼 클릭)
로드 밸런서 이름: LAB4-NLB (입력)
체계: 인터넷 경계 (선택)
VPC: ELB-VPC (선택)
가용 영역 및 서브넷: ap-northeast-2a, ap-northeast-2c (체크)
서브넷: ELB-PUBLIC-SN-1, ELB-PUBLIC-SN-2 (선택)
보안 그룹
default (삭제)
LAB4-CF-ELBSG… (선택)
리스너
프로토콜: UDP
포트: 161
대상 그룹 선택: NLB-TG (선택)
로드 밸런서 생성 (버튼 클릭)
NLB DNS 주소 확인
EC2 서비스 → 로드 밸런싱 → 로드 밸런서 (메뉴 진입) → LAB4-NLB (체크)
세부 정보 → DNS 이름 (복사 아이콘 클릭)
NLB 부하 분산 검증을 위한 변수 선언
NLB_DNS=[NLB_DNS_ADDRESS]
Shell
복사
# NLB 도메인 주소 변수 지정
dig +short $NLB_DNS
Shell
복사
# NLB 도메인 주소 해석
NLB_1=[First_NLB_IP] NLB_2=[Second_NLB_IP]
Shell
복사
# NLB 도메인의 IP 주소 변수 선언
echo $NLB_DNS echo $NLB_1 echo $NLB_2
Shell
복사
# 변수 확인
NLB 부하 분산 검증 (SNMP GET)
for i in {1..60}; \ do snmpget -v2c -c public $NLB_DNS 1.3.6.1.2.1.1.5.0 ; \ done | sort | uniq -c | sort -nr
Shell
복사
# NLB DNS로 SNMP GET 60회 수행
for i in {1..60}; \ do snmpget -v2c -c public $NLB_1 1.3.6.1.2.1.1.5.0 ; \ done | sort | uniq -c | sort -nr
Shell
복사
# NLB_1 IP로 SNMP GET 60회 수행
for i in {1..60}; \ do snmpget -v2c -c public $NLB_2 1.3.6.1.2.1.1.5.0 ; \ done | sort | uniq -c | sort -nr
Shell
복사
# NLB_2 IP로 SNMP GET 60회 수행

3.2. NLB - 교차 영역 로드 밸런싱

NLB의 교차 영역 로드 밸런싱 설정
EC2 서비스 → 로드 밸런싱 → 로드 밸런서 (메뉴 진입) → LAB4-NLB (체크)
속성 (탭 진입) → 편집 (버튼 클릭)
로드 밸런서 대상 선택 정책: 교차 영역 로드 밸런싱 활성화 (선택)
변경 내용 저장 (버튼 클릭)
교차 영역 로드 밸런싱 설정은 바로 적용되지 않습니다.
약 2~3분 정도 후 적용되니, 약간의 대기 후 실습을 진행합니다.
NLB 부하 분산 검증 (SNMP GET)
for i in {1..60}; \ do snmpget -v2c -c public $NLB_DNS 1.3.6.1.2.1.1.5.0 ; \ done | sort | uniq -c | sort -nr
Shell
복사
# NLB DNS로 SNMP GET 60회 수행
for i in {1..60}; \ do snmpget -v2c -c public $NLB_1 1.3.6.1.2.1.1.5.0 ; \ done | sort | uniq -c | sort -nr
Shell
복사
# NLB_1 IP로 SNMP GET 60회 수행
for i in {1..60}; \ do snmpget -v2c -c public $NLB_2 1.3.6.1.2.1.1.5.0 ; \ done | sort | uniq -c | sort -nr
Shell
복사
# NLB_2 IP로 SNMP GET 60회 수행

3.3. NLB - 출발지 IP 주소 보존

실습을 위한 SSH 접근
MY-EC2 인스턴스 접속
SERVER-1 인스턴스 접속
ALB - 출발지 IP 주소 보존 확인
sudo tcpdump tcp port 80 -A -nn | grep --before-context=12 'ALB-TEST'
Shell
복사
# [SERVER-1] tcpdump로 HTTP 트래픽 확인
curl ipinfo.io/ip
Shell
복사
# [MY-EC2] 클라이언트의 퍼블릭 IP 주소 확인
curl -H "X-Test: ALB-TEST" $ALB_DNS
Shell
복사
# [MY-EC2] ALB 도메인으로 HTTP 접근
NLB - 출발지 IP 주소 보존 확인
sudo tcpdump udp port 161 -nn
Shell
복사
# [SERVER-1] tcpdump로 SNMP 트래픽 확인
snmpget -v2c -c public $NLB_DNS 1.3.6.1.2.1.1.5.0
Shell
복사
# [MY-EC2] NLB 도메인으로 SNMP 접근

4. 생성 자원 삭제

로드 밸런서 삭제
EC2 서비스 → 로드 밸런싱 → 로드 밸런서 (메뉴 진입) → 전체 로드 밸런서 (체크)
작업 → 로드 밸런선 삭제 (선택)
삭제 (버튼 클릭)
대상 그룹 삭제
EC2 서비스 → 로드 밸런싱 → 대상 그룹 (메뉴 진입) → 전체 대상 그룹 (체크)
작업 → 삭제 (선택)
삭제 (버튼 클릭)
CloudFormation 스택 삭제
CloudFormation 서비스 → 스택 (메뉴 진입)
대상 스택 선택 → 삭제 (버튼 클릭)
약 5분 내외 시간 소요
여기까지 4장 실습 - ALB와 NLB를 통한 부하 분산 실습을 마칩니다.
수고하셨습니다 :)