개인 프로젝트 배포환경을 고민하다가, ALB를 적용한 이야기다.
- L4와 L7 기본 특징
- AWS의 ALB(L7 수준)와 NLB(L4 수준)
- 각 계층별 로드 밸런서의 Trade-off & TLS 어느 계층에 적용하는게 나은 선택일까?
세 챕터로 나눴지만 궁긍적으로 궁금했던 점은 TLS를 L4와 L7 계층 중, 어디에 적용하는게 나은 선택이냐는 것이다.
그 안에서 필요한 내용(TLS handshake, offload 등)들을 정리하느라 추가된 내용도 있다.
1. L4와 L7 기본 특징
네트워크에서는 각 계층별 헤더 구조를 이해하면, 그 차이에서 계층별 역할을 명확하게 이해할 수 있다. 때문에, L4와 L7의 기본적인 특징만 아주 간단하게 짚고 넘어가고자 한다. (여기서 L7는 HTTP 기반으로 설명한다.)
1.1. L4
L4는 전송 계층으로, 흔히 알고있는 TCP/UDP와 관련있는 계층이다.
TCP/UDP 헤더에는 공통적으로 있는 것들이 있는데, 바로 port # 이다. (source port #, dest port #)
즉, L4에서는 들어온 메시지가 어떤 소켓으로 요청이 온 것인지 판단할 수 있음을 의미한다.
1.2. L7
L7는 응용 계층으로, 여기서는 HTTP, HTTPS, FTP 등 관련 있는 계층이다.
본 글에서는 HTTP에 대해 다루기 때문에, HTTP Header, Payload 정보 등을 가지고 있다고 볼 수 있다.
2. AWS의 ALB와 NLB
사실 AWS에서의 ALB, NLB라고는 했지만 각각 L7에서의 로드밸런싱, L4에서의 로드밸런싱으로 이해하면 된다.
2.1. L4에서의 로드밸런싱
말그대로 L4 수준의 정보를 가지고 로드밸런싱 하는 것이다.
여기서 말하고 싶은 L4 수준의 정보라는 것은 ip, port 번호이다.
즉, L4 스위치는 ip와 port 번호를 기반으로 스위칭 되는 것이고, 주로 부하를 분산시키는 로드 밸런싱에 사용되는 것이다.
2.2. L7에서의 로드밸런싱
이것도 말그대로 L7 수준의 정보를 가지고 로드밸런싱 하는 것이다.
잠깐 다른 이야기를 해보자.
지금 L4, L7과 같이 레이어를 나눠서 설명하고 있다. 즉, 계층적으로 구성되어 있고 각 계층별 로드밸런서마다 가질 수 있는 정보가 다르다는 것이다.
생각해보면 L4는 L7에 비해 하위계층이고, 그렇다는 말은 가지고 있는 정보가 상대적으로 적다는 것이다.(기본적인 부분이지만 이걸 인지해야 TLS를 L4 수준에서 적용할지, L7 수준에서 적용할지를 선택하는데 있어 trade-off를 고려할 수 있다.)
예를 들어, TCP 기반으로 이루어진 HTTP 프로토콜은 L4에서는 해석할 수 없다.
즉, L7 로드밸런서는 HTTP, DNS, FTP 등 Application Layer 프로토콜을 다룰 수 있는 로드 밸런서인 것이다.
정리하면 아래와 같다.
L4 로드밸런서와 L7 로드밸런서의 큰 차이는 가지고 있는 정보의 차이이고, 가지고 있는 정보로 적절한 곳으로 부하를 분산시켜 주는 로드밸런서라고 이해하면 된다.
2.3. 그래서, AWS의 ALB와 NLB의 차이는?
2.3.1. AWS - NLB(Network Load Balancer)
NLB는 Network Load Balancer로, L4 로드 밸런서 역할을 하는 녀석이다.
로드밸런서 선택화면으로 가면 위와 같이 NLB 설명이 나온다.- 클라이언트는 요청을 보낸다.
- 리스너는 요청과 일치하는 프로토콜이나 지정된 포트를 기반으로 대상을 선택한다. (e.g. TLS:443)
- 일치하는 대상은 트래픽을 수신해서 처리한다.
즉, 로드밸런서가 요청을 받으면 VPC 내의 대상그룹에서 요청에 맞는 대상을 선택하여 포워딩하는 것이다.
L4 로드밸런서의 리스너만 살펴보고 넘어가자. (리스너는 위 로드밸런서가 수신한 요청에 대해 어떻게 처리할지 정의할 수 있다.)
NLB listener의 프로토콜은 위 사진과 같이 네 가지를 지원한다.
TCP
TCP 요청에 대해서는 3-way handshake 작업을 수행하여, 로드밸런서와 대상 간에 연결을 맺는다.
예를 들어, EC2 대상과의 연결을 위해 3-way handshake를 통한 커넥션을 맺고 이 커넥션을 관리한다.
UDP
UDP 요청은 연결지향이 아니므로, 즉시 대상으로 요청을 전달한다.
TLS
TLS 요청은 TLS offload(SSL offload)를 위한 설정을 하게된다.
때문에 TLS 프로토콜을 사용하기 위해서는 보안 리스너를 따로 등록해야 한다. 그리고, 이 보안 리스너는 인증서 등록이 되어야 한다.
TLS offload에 대해서는 아래 챕터 3에 정리되어 있다.
2.3.2. AWS - ALB(Application Load Balancer)
ALB는 Application Load Balancer로, L7 로드밸런서 역할을 하는 녀석이다.
로드밸런서 선택화면으로 가면 위와 같이 ALB 설명이 나온다.
- 클라이언트는 요청을 보낸다.
- 리스너는 HTTP 또는 HTTPS 트래픽 요청을 구분하고, 원하는 대상으로 요청을 전달한다.
즉, ALB의 역할은 HTTP 헤더, HTTP 요청 메서드, source ip, 쿼리 파라미터 등을 세부적으로 구분해서 원하는 대상으로 라우팅 하는 것이다.
3. 각 계층별 로드밸런서의 Trade-off & TLS 어느 계층에 적용하는게 나은 선택일까?
3.1. 각 계층별 로드밸런서의 trade-off
- L4 로드밸런서는 상대적으로 성능면에서 상위 프로토콜에 대한 이해가 없어도 되기 때문에, 리소스 소모가 적다.
- L7 로드밸런서는 상대적으로 HTTP 헤더, URL 경로 등을 기반으로 세부적인 규칙을 세울 수 있다.
3.2. TLS는 어느 로드밸런서에 적용하는게 나은 선택일까?
우선, "로드밸런서에 TLS를 적용한다는게 무슨 의미일까?" 에 대해부터 이야기해보고자 한다.
3.2.1. TLS Handshake
TLS handshake는 TLS 통신이 시작될 때, 클라이언트와 서버 간에 암/복호화할 키(대칭키)를 얻기위한 정보교환 작업이다.
작업 과정을 간단하게 요약하면 아래와 같다.
-
클라이언튼는 본인이 지원하는 암호화 알고리즘 목록과 TLS Version 등을 전송한다.
-
서버는 클라이언트가 지원하는 알고리즘 목록 중에 하나를 선택하고, 자신의 TLS 인증서(공개키 포함)를 클라이언트에게 전달한다.
- 클라이언트는 CA의 공개키를 사용해서 서버의 TLS 인증서를 복호화한다.
- 이 복호화를 통해 TLS 인증서가 CA에 의해 발행된 것이고, 위조되지 않았음을 확인한다.
-
클라이언트는 대칭키를 선택하고, TLS 인증서에 포함된 공개키를 사용하여 대칭키를 암호화한다. 그리고, 서버로 전달한다.
-
이 대칭키를 통해 데이터를 암호화하여 클라이언트와 서버 간 데이터를 송수신한다.
위와 같은 TLS handshake 과정은 꽤나 부담스러운 작업일 수 있다.(TCP 3-way handshake처럼)
그래서, 이 부담을 좀 줄여주기 위해서 로드밸런서가 TLS handshake를 수행하고, 다음으로 전달되는 대상 서버에겐 HTTP 프로토콜을 사용하여 평문으로 데이터를 주고받게 해주는 과정을 TLS offload라고 한다. (HTTP의 keep-alive 처럼 네트워크 성능 최적화를 목적으로 하는 것.)
3.2.2. TLS offload
만약 서버에서 직접 가지고 있는 TLS 인증서를 클라이언트에게 전달하게 된다면, 위와 같이 TLS handshake를 서버마다 진행해야 한다.
로드밸런서에게 TLS handshake를 위임함으로써, 리소스 부담을 줄이고 로드밸런서와 각 서버 간에는 평문으로 통신이 가능해진다. NAT처럼 private ip를 통해 평문으로 데이터를 송수신하는 것이다.
위 과정을 TLS offload라고 하며, AWS에선 L4 로드밸런서인 NLB에서도 지원한다.
(참고: https://aws.amazon.com/ko/elasticloadbalancing/features/#Product_comparisons)
3.2.3. 그렇다면 TLS를 L4 로드밸런서에? L7 로드밸런서에?
이 내용에 대해 결정하기 위해 고려해야 할 사항은 매우 많겠지만, 고민해 본 나의 생각은 아래와 같다.
- HTTPS와 같이 복잡하고 정교한 처리를 요구하는 트래픽에 대해서는 L7 로드밸런서가 적합할 것 같다.
- SMTP, FTP와 같은 프로토콜은 L4 로드밸런서로 처리해도 충분하지 않을까 싶다.
(FTP와 SMTP의 구성에 대한 깊은 이해는 없다. 단지 "이러한 기준으로 고려해 볼 수 있지 않을까"라는 나의 개인적인 생각이다)
SMTP나 FTP의 경우 HTTP처럼 심층적이고 정교하게 라우팅 규칙을 세울 필요가 없다고 생각한다.
- 복잡하고 정교한 처리를 요구하지 않음
- 데이터의 안정성과 무결성을 보장
- ip와 port와 같은 L4 수준의 정보로 라우팅이 가능한 경우
위 세 가지 조건을 만족한다면 L4 로드밸런서에 TLS를 적용하는 것이 적합하지 않을까 생각한다.
p.s 안녕하세요, 혹시 위 글을 보신 분들 중에 마지막 생각에 대한 의견이 있으신 분은 댓글 달아주시면 진심으로 감사드리겠습니다!!! :)
[참고 자료]
https://docs.aws.amazon.com/ko_kr/elasticloadbalancing/latest/network/introduction.html https://docs.aws.amazon.com/ko_kr/elasticloadbalancing/latest/application/introduction.html