Search
moon
sun

AWS 네트워크 이해하기 2 - 로드밸런서

제목
Tag
작성일
지난 글에서는 VPC 안에서 패킷이 나가고 들어오는 길을 만드는 구성 요소를 다뤘다. 이번 글은 그 길 위에서 요청을 받아주는 입구인 로드밸런서를 다룬다. 서비스를 외부나 다른 네트워크에 노출할 때는 거의 항상 로드밸런서가 앞에 선다. 로드밸런서가 어떤 구조로 동작하는지, 요청을 어떤 규칙으로 어디에 나눠 보내는지, 보안 그룹은 어떻게 나눠 붙이는지 순서대로 살펴본다.

탄력적 로드밸런서(Elastic Load Balancer)

로드밸런서는 들어온 요청을 뒤에 있는 여러 대상(타깃)에 나눠주는 장치다. AWS에서는 이를 ELB(Elastic Load Balancing)라는 관리형 서비스로 제공한다.
클라이언트들 → 로드밸런서 ─┬→ 타깃 A ├→ 타깃 B └→ 타깃 C
Plain Text
복사
•
부하 분산: 요청을 여러 타깃에 나눠 한 대에 몰리지 않게 함. 타깃이 늘거나 줄어도 클라이언트는 주소 하나만 알면 됨
•
타깃을 직접 노출하지 않음: 클라이언트는 로드밸런서에만 접속하고, EC2 같은 타깃은 프라이빗 서브넷에 숨겨둘 수 있음
•
AZ 장애 대응: 여러 AZ에 걸쳐 동작하므로 한 AZ에 장애가 나도 나머지 AZ의 타깃으로 보내 서비스를 이어감
•
다른 AWS 서비스와 연동: ACM 인증서로 HTTPS 처리, AWS WAF로 요청 필터링, 접근 로그를 S3에 저장, CloudWatch 지표, Auto Scaling 그룹과 연결한 타깃 자동 등록, Route 53으로 도메인 연결

ALB와 NLB

ELB에는 여러 종류가 있지만 실무에서 주로 쓰는 것은 두 가지임
ALB (Application Load Balancer)
NLB (Network Load Balancer)
동작 계층
L7 (응용 계층)
L4 (전송 계층)
보는 정보
HTTP 메서드, 호스트, 경로, 헤더
IP 주소, 포트, TCP/UDP
주로 쓰는 곳
웹, REST API, gRPC
DB·메시지 브로커 노출, 고정 IP가 필요한 입구
둘의 차이는 계층보다 연결을 어떻게 다루느냐에서 더 분명하게 드러난다.
ALB는 클라이언트 입장에서는 서버처럼 타깃 입장에서는 클라이언트처럼 행동한다. 서버 앞에 서서 요청을 대신 받아 전달하는 이런 장치를 리버스 프록시라고 한다. NLB는 NAT GW처럼 연결을 끊지 않고 넘기는 쪽에 가깝다.
NLB (게이트웨이형)
ALB (리버스 프록시)
연결
클라이언트의 연결 하나를 그대로 통과시킴
클라이언트 ↔ ALB, ALB ↔ 타깃 두 개의 연결
하는 일
패킷을 타깃으로 넘김
요청을 받아 해석한 뒤 타깃에 새 요청을 보냄
타깃이 보는 출발지
설정에 따라 원래 클라이언트 IP
ALB의 IP. 원래 클라이언트 IP는 X-Forwarded-For 헤더로 전달

작동 방식

인터넷용과 내부용

로드밸런서는 만들 때 scheme를 고르고 그에 맞는 서브넷을 지정해야함
internet-facing
internal
IP
공인 IP
사설 IP
두는 서브넷
퍼블릭 서브넷
프라이빗 서브넷
접근
인터넷 어디서나
VPC 안, 그리고 TGW·Peering으로 연결된 네트워크
인터넷에서 프라이빗 서브넷의 서비스로 들어오려면 퍼블릭 서브넷에 인터넷용 로드밸런서를 두고 거기서 프라이빗 서브넷의 타깃으로 넘겨야 한다.

AZ마다 생기는 로드밸런서 노드

로드밸런서는 콘솔에서 리소스 하나로 보이지만 실제로는 지정한 AZ마다 로드밸런서 노드가 생겨 요청을 처리한다.
•
여러 AZ에 걸쳐 부하를 분산하려면 각 AZ의 서브넷을 하나씩 지정해야 함. ALB는 최소 2개 AZ가 필요
•
각 노드는 우리 서브넷에 ENI를 만들어 IP를 가져감. EC2 목록에는 보이지 않고 ENI 목록에서만 보임
•
노드가 서브넷 IP를 쓰므로 로드밸런서 서브넷에는 여유 IP가 있어야 함. ALB는 서브넷 크기 최소 /27, 여유 IP 8개 이상을 요구함

확장 방식과 IP

노드가 ENI로 IP를 가져간다는 점은 트래픽이 늘어 로드밸런서가 확장할 때 차이를 만든다.
ALB: 노드가 바뀌면 IP도 바뀜
트래픽이 늘면 AWS가 ALB 노드를 더 큰 것으로 바꾸거나 개수를 늘린다. 노드가 늘고 교체될 때마다 ENI도 새로 생기고 사라지므로 ALB의 IP는 계속 바뀐다.
•
ALB는 IP가 아니라 DNS 이름으로 접근해야 함. AWS가 DNS 응답을 현재 살아 있는 노드 IP로 계속 갱신해줌
•
IP가 계속 바뀌므로 ALB에는 고정 IP(EIP)를 붙일 수 없음
NLB: Hyperplane과 고정 IP
NLB는 Hyperplane이라는 AWS 내부 네트워크 기술 위에서 동작하기 때문에 IP 변경이 일어나지 않는다.
•
AZ당 ENI 하나를 두고 확장은 그 ENI 뒤쪽에서 보이지 않게 일어남
•
겉으로 보이는 ENI가 그대로라 IP가 고정됨
•
연결을 끊고 새로 맺지 않고 넘기기만 하는 L4 장비라 이런 구조가 가능함
IP가 고정이므로 인터넷용 NLB에는 AZ마다 EIP를 지정할 수 있고 내부용 NLB는 AZ마다 사설 IP를 직접 지정할 수 있다. 상대방 방화벽에 목적지 IP를 등록해야 하거나 클라이언트가 IP로만 접속할 수 있는 경우에 NLB를 쓰는 이유다.

대상 그룹 (Target Group)

역할

대상 그룹은 요청을 받을 타깃들의 묶음. 로드밸런서는 타깃을 직접 알지 않고 요청을 대상 그룹에 넘기면 대상 그룹이 안에 등록 타깃 중 하나를 골라 보내는 구조이다.
로드밸런서와 서버 사이에 이 단계를 하나 더 두는 이유는 다음과 같다.
1. 서버가 바뀌어도 로드밸런서는 그대로
•
EC2를 늘리거나 교체할 때 대상 그룹에 등록하고 빼기만 하면 됨
•
Auto Scaling 그룹을 대상 그룹에 연결하면 새로 뜬 인스턴스가 자동으로 등록되고 종료된 인스턴스는 자동으로 빠짐
•
로드밸런서와 리스너 설정은 건드리지 않음
2. 로드밸런서 하나로 여러 서비스를 받기
대상 그룹을 서비스마다 하나씩 만들어 두면 로드밸런서 하나가 요청을 보고 알맞은 묶음으로 나눠 보낼 수 있다.
예를 들어 도메인 두 개를 같은 ALB에 연결했다고 해보자.
Route 53 api.example.com ─┐ admin.example.com ─┴→ 같은 ALB (같은 IP)
Plain Text
복사
두 도메인 모두 같은 ALB의 IP로 풀리므로 IP만 봐서는 사용자가 어느 주소로 접속했는지 알 수 없다. 이때 쓰는 것이 HTTP 요청에 담긴 Host 헤더다. 브라우저는 요청을 보낼 때 사용자가 입력한 도메인을 Host: api.example.com처럼 헤더에 적어 보낸다. ALB는 이 값을 보고 대상 그룹을 고른다.
같은 방식으로 URL 경로(/orders/*)나, NLB라면 요청이 들어온 포트(:9092 → 브로커 묶음, :5432 → DB 묶음)로도 나눌 수 있다.
3. 묶음마다 상태를 따로 관리
헬스 체크와 등록 해제 지연은 대상 그룹마다 설정한다. API 서버는 /health로, 관리 도구는 /status로 확인하는 식으로 서비스에 맞게 다르게 잡을 수 있다.
대상 그룹에 정하는 것은 다음과 같다.
항목
내용
타깃 유형
인스턴스, IP, Lambda(ALB만), ALB(NLB만)
프로토콜·포트
타깃이 요청을 받는 프로토콜과 포트. 로드밸런서가 443으로 받아도 타깃에는 8080으로 보낼 수 있음
헬스 체크
주기적으로 요청을 보내 정상인지 확인하고, 실패한 타깃에는 요청을 보내지 않음
등록 해제 지연
타깃을 뺄 때 처리 중인 요청이 끝나기를 기다리는 시간 (기본 300초)

리스너와 규칙

요청이 로드밸런서에 들어와서 타깃에 닿기까지는 다음 순서를 거친다.
요청 → 리스너 (어느 포트로 왔나) → 규칙 (어떤 조건에 맞나) → 대상 그룹 → 타깃
Plain Text
복사
앞에서 본 대상 그룹이 어디로 보낼지의 묶음이라면 리스너와 규칙은 어떤 요청을 어느 묶음으로 보낼지를 정한다.

리스너

리스너는 로드밸런서가 어떤 프로토콜과 포트로 요청을 받을지 정한다.
•
로드밸런서를 만들어도 리스너가 없으면 아무 요청도 받지 않음
•
로드밸런서 하나에 리스너를 여러 개 둘 수 있음. 포트마다 하나씩
ALB에 흔히 두는 리스너 구성
ALB ├─ 리스너 HTTP:80 → 모든 요청을 HTTPS로 리다이렉트 └─ 리스너 HTTPS:443 → 규칙에 따라 대상 그룹으로
Plain Text
복사
NLB는 요청 내용을 보지 않으므로 리스너가 곧 분기 기준임. 포트마다 리스너를 만들고 각 리스너를 대상 그룹 하나에 연결(포트 기반 라우팅)
NLB ├─ 리스너 TCP:9092 → 대상 그룹 broker └─ 리스너 TCP:5432 → 대상 그룹 db
Plain Text
복사
ALB
NLB
리스너 프로토콜
HTTP, HTTPS
TCP, UDP, TCP_UDP, TLS
분기
리스너 안의 규칙으로 여러 대상 그룹에
리스너 하나에 대상 그룹 하나
HTTPS 리스너에는 ACM 인증서를 붙인다. ALB가 Host 헤더나 경로를 보기위해 여기서 암호화를 풀고(TLS 종료), 타깃에는 평문이나 재암호화로 보낸다.

규칙

ALB 리스너에는 규칙을 여러 개 둘 수 있다. 하나의 규칙은 조건, 동작, 우선순위로 이루어진다.
조건: 어떤 요청에 적용할지
조건
예
호스트 (Host 헤더)
admin.example.com
경로
/orders/*
HTTP 헤더
X-Version: beta
쿼리 문자열
?version=2
HTTP 메서드
POST
출발지 IP
10.0.0.0/16
•
규칙 하나에 다른 종류의 조건을 여러 개 넣으면 모두 맞아야 적용됨 (AND). 예: 호스트가 api.example.com 이고 경로가 /orders/*
•
조건 하나에 값을 여러 개 넣으면 하나만 맞아도 적용됨 (OR). 예: 호스트가 api.example.com 또는 api2.example.com
동작: 조건에 맞으면 무엇을 할지
•
대상 그룹으로 전달
•
리다이렉트 (HTTP → HTTPS, 다른 도메인으로 이동 등)
•
고정 응답 (404, 점검 페이지 등)
우선순위: 어떤 규칙부터 볼지
•
숫자가 작은 규칙부터 차례로 확인하고, 처음 맞는 규칙 하나만 적용함
•
아무 규칙에도 맞지 않으면 기본 규칙으로 감
대상 그룹 섹션의 예를 HTTPS:443 리스너 규칙으로 옮기면 이렇다.
우선순위
조건
동작
1
Host가 admin.example.com
대상 그룹 admin으로 전달
2
Host가 api.example.com 이고 경로가 /orders/*
대상 그룹 orders로 전달
3
Host가 api.example.com
대상 그룹 api로 전달
기본
(나머지 전부)
404 고정 응답
규칙은 우선순위 숫자가 작은 것부터 차례로 확인하고 처음 맞는 규칙 하나만 적용한다.
규칙 2와 3의 순서가 바뀌면 /orders 요청도 규칙 3에 먼저 걸려 api로 가버린다. 규칙은 자동으로 정렬되지 않으므로 더 구체적인 조건을 앞에 둬야 한다.
admin.example.com/users → 규칙 1 → admin api.example.com/orders/123 → 규칙 2 → orders api.example.com/products → 규칙 2 안 맞음 → 규칙 3 → api unknown.example.com → 다 안 맞음 → 기본 규칙 → 404
Plain Text
복사

부하 분산 알고리즘

대상 그룹 안에서 어떤 타깃에 보낼지는 알고리즘이 정한다.
알고리즘
동작
사용하는 경우
라운드 로빈 (ALB 기본)
타깃에 돌아가며 하나씩 보냄
요청 처리 시간이 비슷할 때
최소 미해결 요청 (ALB)
처리 중인 요청이 가장 적은 타깃에 보냄
요청마다 처리 시간 편차가 클 때
가중치 랜덤 (ALB)
가중치에 따라 무작위로 고름. 이상 타깃의 가중치를 자동으로 낮추는 기능과 함께 씀
일부 타깃이 느려지는 상황에 자동 대응하고 싶을 때
흐름 해시 (NLB)
프로토콜·출발지·목적지 IP와 포트로 해시를 계산해 타깃을 고름
같은 연결은 끝날 때까지 같은 타깃으로

교차 영역 로드 밸런싱

로드밸런서 노드는 AZ마다 하나씩 있고 요청은 노드들에 나눠 들어온다. 이때 노드가 자기 AZ의 타깃에만 보낼지, 모든 AZ의 타깃에 보낼지를 정하는 것이 교차 영역(cross-zone) 로드 밸런싱이다.
꺼져 있으면 AZ마다 타깃 수가 다를 때 분산이 한쪽으로 쏠린다. AZ-a에 1대, AZ-b에 3대가 있으면 AZ-a의 1대가 전체 요청의 절반을 혼자 받게된다.
ALB
NLB
기본값
항상 켜짐 (대상 그룹 단위로 끌 수는 있음)
꺼짐 (옵션으로 켤 수 있음)
AZ 간 데이터 전송 요금
없음
켜면 발생
NLB에서 AZ마다 타깃 수가 다르다면 교차 영역을 켜야 고르게 분산된다. 대신 AZ를 넘나드는 트래픽에 요금이 붙으니 가능하면 AZ마다 타깃 수를 맞추는 것도 방법이다.

보안 그룹 배치

•
보안 그룹은 ENI에 붙는데 로드밸런서도 서브넷에 ENI를 가지므로 SG를 붙일 수 있음
•
로드밸런서를 두면 요청은 클라이언트 → 로드밸런서, 로드밸런서 → 타깃 두 구간을 지남. 즉 두군데 다 보안그룹을 붙임
•
각 구간에서는 요청을 받는 쪽의 SG 인바운드만 열면 됨

구간별 규칙

구간
받는 쪽
인바운드 허용
상대방
클라이언트 → 로드밸런서
로드밸런서 SG
리스너 포트 (443 등)
인터넷용: 0.0.0.0/0 / 내부용: 사내망·VPC 대역
로드밸런서 → 타깃
타깃 SG
앱 포트 + 헬스 체크 포트
로드밸런서 SG
헬스 체크도 로드밸런서에서 타깃으로 가는 트래픽이라 두 번째 구간에 포함된다. 이 허용이 빠지면 타깃이 멀쩡해도 unhealthy로 보이게 된다.

SG 체이닝

SG 체이닝은 각 계층의 SG 인바운드에 바로 앞 계층의 SG를 상대방으로 적어 계층을 사슬처럼 잇는 방식이다.
•
경로가 강제됨: DB는 앱을 거쳐서만 앱은 로드밸런서를 거쳐서만 접근할 수 있음. 앞 계층을 건너뛰고 들어오는 요청은 막힘
•
IP와 무관함: 상대방이 IP가 아니라 SG라서 ALB 노드나 앱 서버의 IP가 바뀌어도 규칙을 고칠 필요가 없음
•
범위가 최소: 서브넷 대역을 열면 같은 서브넷의 다른 리소스도 통과하지만 SG를 참조하면 그 SG가 붙은 리소스만 허용됨
•
의도가 읽힘: 규칙만 보고 앱은 로드밸런서에서 오는 것만 받는다는 것을 바로 알 수 있음
예외: NLB가 클라이언트 IP를 전달할 때
NLB는 설정에 따라 원래 클라이언트 IP를 그대로 타깃에 전달한다. 이 경우 타깃이 보는 출발지는 NLB가 아니라 클라이언트다. 그래서 타깃 SG 인바운드에 무엇을 허용할지가 NLB에 SG가 있느냐에 따라 달라진다.
NLB 설정
타깃 SG가 허용할 대상
NLB에 SG 없음
클라이언트 대역
NLB에 SG 있음
NLB SG
NLB의 SG는 만들 때만 지정할 수 있으므로 처음부터 붙여두는 편이 관리가 쉽다.

정리

ALB 요청 흐름: 리스너 규칙에 따라 대상 그룹으로 분배
ALB와 NLB의 비교표
ALB
NLB
계층
L7
L4
연결
두 개 (리버스 프록시)
하나 (통과)
라우팅
호스트, 경로, 헤더 등
포트
부하 분산
라운드 로빈, 최소 미해결 요청, 가중치 랜덤
흐름 해시
교차 영역
항상 켜짐
기본 꺼짐(비용 있음)
IP
계속 바뀜 → DNS로 접근
AZ당 고정, EIP 지정 가능
타깃이 보는 출발지
ALB IP (X-Forwarded-For로 원래 IP)
설정에 따라 클라이언트 IP
보안 그룹
지원
지원 (생성할 때 지정해야 함)