이전 DNS 개념을 정리한 게시글에서 아래와 같은 배경이 있었다. 이제 고정 IP를 요청서에 적어야 하는 것은 알겠다.
이번에 학교 중앙 동아리 홈페이지 프로젝트를 시작하며, 학교측에 우리의 서비스와 학교측 도메인 주소(OO.ac.kr)를 연결하기 위해 요청하는 작업이 필요했다. 그런데 요청서 양식에 고정 IP 대역을 요구하는 것이었다. 그래서 읭? 우리는 AWS에 서비스를 배포할 것인데 IP 대역을 어떻게 고정시키지? 해서 궁금해서 담당부서에 문의를 해보았다. 다행히 '그러한 경우에는 그냥 고정 IP 주시면 저희 DNS에 등록해줍니다.'라고 하셨다.
그런데 문득 든 생각이 내가 아는 지식 선에서는 AWS에서 고정 IP를 할당받기 위해서는 탄력적 IP를 할당받는 것 뿐인데, 비용이 꽤 나오는 걸로 알고있는데..? 이 방법이 비용적으로 최선일까 고민하다가 도저히 갈피를 못잡겠어서 오픈채팅방에 질문을 올렸다. 그리고 아래와 같은 답변을 얻었다.
"NLB 사용하시면 됩니다. 근데 CNAME등록해달라고 하는게 정석이긴해요", "저 상황에서 IP대신에 CNAME을 써야하는 이유 중에 하나는 AZ장애가 될 수도 있어서예요."
NLB..? AWS 공부할 때 분명히 들어본 개념이긴 한데... '네트워크 로드 밸런서'라는 것만 알겠다🤣. 답변을 듣고 급하게 노션을 뒤져보았고, 필기한 흔적이 남아있었다. 정리한 필기 내용을 훑어보니 정말 NLB가 현재의 목적에 적합한 선택지일 것 같다는 생각이 들었다. 따라서 이참에 NLB와 AWS의 ELB 개념을 정리하고자 한다. (참고로 CNAME과 관련한 내용은 DNS 개념정리 게시글에 있다.)
ELB(Elastic Load Balancer)는 단일 또는 여러 가용 영역에서 다양한 애플리케이션의 부하를 처리할 수 있는 로드 밸런싱을 제공하는 서비스로, 네 가지 종류가 있으며 모두 애플리케이션의 내결함성에 필요한 고가용성, 자동 조정, 강력한 보안을 갖추고 있다.
요청을 동일한 클라이언트에서 동일한 대상으로 라우팅하는 메커니즘을 바탕으로 고정성은 대상 그룹 수준에서 정의하게 된다. ALB와 CLB는 쿠키(Cookie)를, NLB는 Source IP를 기억하는 방법을 사용한다.
다음의 쿠키 이름은 ELB가 선점하고 있다 (AWSALB, AWSALBAPP, AWSALBTG).

기본적으로 ELB는 대상그룹에 등록된 EC2별로 적절히 부하분산을 하는 것이 아닌, 가용영역별로 비율을 나눈다(교차영역이 2개라면 각 가용영역에 50%씩 전달). 가령, A 가용영역에 EC2가 2개이고, B 가용영역에 EC2가 8개일 경우 A/B 가용영역에 50%씩 전달되므로 A 가용영역의 EC2의 부하가 심해질 수 있다.
이를 방지하기 위해 교차영역 로드밸런싱을 활성화하면 가용영역이 아닌 EC2 갯수를 기반으로 계산하여 전달한다. 즉, 각 가용 영역에 위치한 로드 밸런서 인스턴스가 모든 가용 영역에 등록된 모든 인스턴스에 부하를 고르게 분배한다.
Client의 IP를 담고 있는 HTTP 헤더로, HTTP를 활용하는 ALB와 CLB에서 사용 가능하다. EC2 내 서비스가 Client의 IP를 확인할 필요가 있는 경우 ELB는 HTTP Header에 X-Forwared-for를 장착하여 대상그룹에 전달한다.
Autoscaling과 ELB를 함께 사용 시, 필요에 따라 EC2가 없어질 경우(등록 취소, 비정상 상태), 해당 EC2에 요청이 들어와 있다면 사용중인 커넥션(세션)이 피해를 볼 수 있다. 이를 방지하기 위해 해당 인스턴스의 사용중인 커넥션(세션)이 작업을 마칠 때까지 기다리는 기능으로, ALB, NLB, CLB 모두에서 사용 가능하다. Connection draining은 1부터 3600초 사이의 값으로 설정할 수 있으며, 기본적으로는 300초(5분)이다. 요청의 길이에 비례하여 설정하는 것이 이론상 적절하다.
CLB에서는 Connection Draining, ALB와 NLB에서는 Deregistration Delay라고 부른다.
ELB에서 삭제 방지를 활성화하여 우발적 삭제를 방지
EC2, ECS/EKS, Global Accelerator 및 운영 도구 등의 다른 AWS 서비스와 긴밀하게 통합할 수 있다.
클라이언트로부터 받은 요청을 로드밸런싱 대상 서버에 순서대로 할당받는 방식이다. 서버의 성능이 동일하고 처리 시간이 짧은 애플리케이션의 경우, 균등하게 분산이 이루어진다.
실제 서버에 서로 다른 처리 용량을 지정하는 방식이다. 각 서버에 가중치를 부여할 수 있으며, 여기서 지정한 정숫값을 통해 처리 용량을 정한다.
연결 수가 가장 적은 서버에 네트워크 연결 방향을 정하는 동적 분산 알고리즘으로 각 서버에 대한 현재 연결 수를 동적으로 카운트할 수 있고, 동적으로 변하는 요청에 대한 부하를 분산시킬 수 있다.
| 기능 | ALB | NLB | GWLB | CLB |
|---|---|---|---|---|
| 로드 밸런서 유형 | layer 7 | layer 4 | layer 3 gateway + layer 4 load balancing | layer 4/7 |
| 대상 유형 | IP, 인스턴스, Lambda | IP, 인스턴스 | IP, 인스턴스 | |
| 흐름/프록시 동작 종료 | 예 | 예 | 아니오 | 예 |
| 프로토콜 리스너 | HTTP, HTTPS, WebSocket, gRPC | TCP, UDP, TLS | IP | TCP, SSL/TLS, HTTP, HTTPS |
| 다음을 통해 연결 가능 | VIP | VIP | 라우팅 테이블 항목 | |
| 교차 영역 로드밸런싱 (기본값) | 활성화 (비용x, 대상그룹 수준에서 비활성화 가능) | 비활성화 (활성화시 비용 발생) | 비활성화 (활성화시 비용 발생) | 비활성화 (활성화시에도 비용x) |
| SSL 인증서 | 여러개 가능 | 여러개 가능 | 1개 | |
| SNI(Server Name Indication) 동작여부 | o | o | x |
리스너
연결 요청을 확인하는 프로세스로, 리스너는 프로토콜 및 포트로 구성되며 로드밸런서의 앞단과 뒷단을 연결하는 역할을 한다.
HTTP 및 HTTPS 프로토콜과 1~65535의 TCP 포트, Lambda 호출, ECS를 사용하는 애플리케이션의 로드 밸런싱을 지원한다.
IP 프로토콜 데이터를 기반으로 Amazon VPC 내의 대상(Amazon EC2 인스턴스, 마이크로서비스 및 컨테이너)으로 연결을 라우팅한다.
서드파티 가상 어플라이언스를 쉽게 배포, 확장 및 관리 가능하게 한다.
EC2 인스턴스(오토스케일링 그룹에 의해 관리될 수 있음), ECS 작업, 람다 함수, IP 주소(사설만 가능)

먼저 두 개의 인스턴스를 생성한다. 이 인스턴스는 아마존 리눅스 기반이며 nginx1이 설치되어 있고 실행중이다. 만약 nginx가 설치되어 있지 않다면 아래 명령어를 참고하거나 구글링을 통해 설치해준다. (여기서는 기존의 시작 템플릿(launch template)을 사용하였다.)
sudo amazon-linux-extras install nginx1
sudo systemctl enable nginx
템플릿 선택

네트워크 설정: 생성한 VPC의 서브넷을 특정 가용영역 내 public 서브넷으로 지정합니다. 보안 그룹은 VPC 단위로 동작하므로, 생성한 VPC에 대해 새 보안 그룹을 적용합니다.

인바운드 규칙

리소스 태그 지정 (필수 x)
두 번째 인스턴스도 위와 같은 순서로 생성하되, 다른 가용영역의 퍼블릭 서브넷, 기존 보안 그룹(새로 생성한 보안 그룹)을 선택한 후, 태그명을 달리하여 생성합니다. 아래는 두 개의 인스턴스 생성이 완료된 후의 모습이다.

/usr/share/nginx/html/index.html 의 내용을 이후 테스트에서 구별 가능하게끔 수정해준다. cd /usr/share/nginx/html/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
</head>
<body>
<h1>Hello from the frontend1-ec2!</h1> => 인스턴스 a에 적용
<h1>Hello from the frontend2-ec2!</h1> => 인스턴스 b에 적용
</body>
</html>
이제 로드 밸런서가 바라보게 될 대상 그룹을 생성해야 한다. (EC2>로드 밸런싱>대상 그룹>대상 그룹 생성)



Application Load Balancer 생성을 선택합니다. (EC2>로드 밸런싱>로드 밸런서>로드 밸런서 생성)

네트워크 매핑

보안 그룹: ‘새 보안 그룹’ 생성 누른 후, 로드 밸런서 전용 보안 그룹을 생성합니다.
기본 세부 정보

인바운드/아웃바운드 규칙

로드 밸런서의 보안 그룹을 별도로 설정하는 이유
- 독립적인 접근 제어: ELB에만 적용되는 인바운드 및 아웃바운드 규칙을 설정하여, 로드 밸런서가 처리하는 트래픽을 정확히 제어할 수 있습니다. 이를 통해 인스턴스와는 다른 규칙을 적용할 수 있습니다.
- 보안의 유연성: VPC의 인스턴스와 로드 밸런서가 서로 다른 보안 요구 사항을 가질 수 있기 때문에, 별도의 보안 그룹을 통해 각 리소스에 맞는 보안 정책을 설정할 수 있습니다
리스너 및 라우팅: 로드 밸런서에 HTTP 프로토콜, 80 포트에 대한 요청을 위에서 생성한 대상 그룹으로 전달하기 위해 해당 리스너를 등록합니다.

결과 확인: 로드밸런서 프로비저닝 완료 후 상태가 활성화로 변경되면 해당 로드밸런서의 DNS 이름을 브라우저에서 접속한다. 그리고 계속하여 새로고침을 시도해본다.


서로 다른 문구가 랜덤하게 나오면 성공!

로드 밸런서를 통한 트래픽만을 허용하려면 인스턴스가 속한 보안그룹의 인바운드 규칙을 수정해야 한다. 기존의 HTTP 인바운드를 삭제한 후, 로드 밸런서가 속한 보안그룹을 지정한다.
⇒ 이렇게 수정하면 인스턴스 공인 IP로 직접 접속은 제한되며, 로드 밸런서를 통한 접속만이 가능하다.

로드 밸런서에 규칙을 추가하여 특정 조건 하에 수행할 작업을 지정(대상 그룹으로 포워딩, URL 리다이렉션, 고정 응답 반환)할 수 있다.

리소스 정리
인스턴스 삭제 → NAT 게이트 웨이 삭제 → 네트워크 인터페이스 삭제 → 로드 밸런서 삭제 → 대상 그룹 삭제 → 로드밸런서 보안 그룹 삭제 → 인터넷 게이트 웨이 분리 및 삭제