AWS Application Load Balancer 쉽게 이해하기 #2
지난 문서에 이어서 계속해서 ALB에 대해 이야기하도록 하겠습니다. 이 문서에서는 ALB의 구성요소인 리스너 / 규칙 / 대상그룹과 라우팅(부하분산) 규칙을 상세하게 설명합니다. 또한 ALB의 기타 기능에 대해서도 설명하도록 하겠습니다.
Application Load Balancer의 구성 요소
ALB에는 크게 3가지 요소가 있습니다. 먼저 사용자에게서 요청을 받아들여 이 요청을 처리할 적절한 대상그룹으로 전달하는 리스너, 어느 대상그룹에 전달할지 판단하는 기준이 되는 규칙, 마지막으로 요청을 처리할 EC2가 모여 있는 대상그룹입니다.
위의 그림은 ALB를 도식화한 그림입니다. 로드밸런서 아래 다수의 리스너, 규칙, 대상그룹, 헬스 체크가 있는 것을 확인하실 수 있습니다. 하나의 ALB는 여러 개의 리스너를 거느릴 수 있고, 리스너 안에 다수의 규칙을 보유할 수 있으며, 하나의 리스너는 여러 대상그룹을 거느릴 수 있음을 알 수 있습니다.
리스너(Listener)
(설정 화면 : EC2 서비스 - 로드밸런서 - 리스너)
ALB의 리스너는 HTTP와 HTTPS에 해당하는 요청을 받아들이며, HTTP 관련 정보를 해석할 수 있습니다. 그 정보를 기반으로 어느 대상그룹에 요청을 전달할 것인지 규칙을 세우고 라우팅을 실시합니다. 그렇기에 HTTP / HTTPS 리스너는 공통적으로 자신의 이름에 해당하는 '리스너 ID', 대상그룹에 사용자의 요청을 건네줄 판단 기준이 되는 '규칙'을 보유합니다. 또한 ALB의 HTTPS 리스너는 암호화된 HTTP 요청을 받아들여 수행하기 때문에 이를 충족하기 위해 자신의 신원을 보증해 줄 'SSL 인증서'와 주고받을 데이터의 암호화 방안인 '보안 정책'을 추가로 보유합니다. 즉 HTTPS 리스너를 사용하기 위해서는 SSL 인증서는 필수임을 의미합니다. 위 그림을 보시면 'HTTPS:443'에 해당하는 리스너가 SSL 인증서와 보안정책을 보유한 것을 보실 수 있습니다. 해당 리스너로 접속하는 사용자들은 HTTPS를 이용하여 연결합니다.
HTTP 리스너의 포트는 기본적으로 '80'이며 HTTPS 리스너의 포트는 기본적으로 '443'입니다. ALB의 리스너가 사용 가능한 포트 범위는 1 ~ 65535이기 때문에 HTTP/HTTPS 리스너 또한 포트 번호를 변경할 수 있습니다. 위 그림을 보시면 HTTPS 리스너는 기본 포트인 '443'을 사용하지만 2개의 HTTP 리스너는 각각 '80'과 '8080'을 사용하고 있는 것을 보실 수 있습니다. '80' 포트가 이미 사용 중일 때 '8080' 혹은 '8888'을 쓰는 방식으로 새로운 HTTP 리스너를 생성하여 사용할 수 있음을 의미합니다.
규칙(Rule)
규칙은 사용자의 요청을 받은 리스너가 헤더에 담긴 HTTP 관련 정보를 해석한 뒤 그 정보를 기반으로 어느 대상그룹에 전달할지 판단하는 기준이 되는 요소입니다. 아래 그림은 ALB의 HTTP 리스너(포트 80)의 규칙을 담고 있습니다. 규칙은 '규칙 조건'과 '규칙 작업'으로 나뉩니다. 사용자의 요청을 전달받은 이를 아래 '규칙 조건'에 대조해보고 적합한 규칙에 연결된 '규칙 작업'을 실시합니다. 아래 그림에서 'IF'에 해당하는 부분이 '규칙 조건'이며, 'THEN'에 해당하는 부분이 '규칙 작업'입니다. 이러한 규칙은 몇 가지 특징을 지닙니다.
(설정 화면 : EC2 서비스 - 로드밸런서 - 리스너 - 규칙 편집)
첫 번째, 규칙이 여러 개 존재하면 가장 상단의 규칙부터 순서대로 한 개씩 비교합니다. 위의 그림에서는 6개의 사용자 정의 규칙과 1개의 기본 작업 규칙이 보입니다. 사용자의 요청이 들어오면 1번부터 순서대로 규칙을 비교하며 그중에 정확하게 일치하는 규칙을 선택합니다.
두 번째, 규칙 조건(IF)은 여러 개(최대 5개)가 포함될 수 있으며 모든 규칙 조건을 충족시켜야 합니다. 아래 그림을 보시면 가장 먼저 적용될 1번 규칙에 3개의 규칙 조건이 적용된 것을 확인하실 수 있습니다. 3가지 요건 모두 갖추어져야 비로소 규칙 작업을 실시하게 됩니다.
세 번째, 규칙 작업(THEN)은 규칙 조건을 충족한 요청을 처리하기 위한 라우팅 작업이며 3가지 작업이 존재합니다. '전달 대상', '리디렉션 대상', '고정 응답 반환' 3가지가 그것입니다.
'전달 대상'은 EC2로 이루어진 그룹인 대상그룹으로 전달하는 것을 의미합니다. 즉 대상그룹을 지정하여 사용자의 요청을 보내는 것을 의미합니다. 또한 하나의 리스너에 여러 개의 대상그룹을 지정할 수 있으며 각 대상그룹의 요청 처리 비중을 정할 수 있습니다. 아래 그림을 보시면 3개의 대상그룹이 각각 33%씩 트래픽 배포를 분담하여 처리할 수 있음을 알 수 있습니다.
'리디렉션 대상'은 사용자의 요청을 또 다른 URL로 전달하는 것을 의미합니다. 예를 들어 사용자가 HTTP 리스너에 접속하고 입력한 URL이 'second.aws-hyoh.com'일 경우 'www.naver.com'로 연결하여 네이버 웹페이지를 띄워야 한다면 다음과 같이 설정할 수 있습니다. 아래 그림에서는 규칙 조건이 맞다면 리디렉션 대상을 'https://www.naver.com'으로 지정하여 영구(응답 코드 301) 혹은 임시(응답 코드 302)로 리디렉션할 수 있으며 경로와 쿼리까지 지정할 수 있습니다.
'고정 응답 반환'은 대상그룹으로 전달하거나 리디렉션하는 것이 아닌 사용자가 정한 html, css, javascript, json 등 형식의 웹페이지를 HTTP 응답 코드(2xx, 3xx, 4xx)와 함께 전달하는 것입니다. 사용자가 원하는 방식의 콘텐츠 유형과 응답 코드를 자유롭게 설정할 수 있어 매우 편리합니다.
고정 응답 반환은 여러모로 좋은 기능이라고 생각합니다. 잘못된 경로로 진입한 사용자에게 주의 메시지를 전달하거나, 장애 혹은 사용자 폭주로 일시적으로 서비스가 마비되었을 경우, 고정 응답 반환을 이용해 사용자에게 공지할 수 있습니다.
대상 그룹(Target Group)
대상그룹은 사용자의 요청을 처리할 EC2의 집합입니다. '전달 대상'에 포함된 대상그룹이 리스너에게 요청을 전달받아 작업을 실시하죠. 아래 그림은 ALB의 대상그룹을 상세화면으로 본 것입니다.
(설정 화면 : EC2 서비스 - 대상그룹)
ALB의 대상그룹의 특징은 아래 기본 설정(Basic Configuration)과 헬스 체크(Health Check)에서 드러납니다. ALB의 대상그룹이기에 'Protocol : Port'는 HTTP 혹은 HTTPS를 사용합니다. 이는 이 대상그룹에 소속된 EC2들이 설정된 'Protocol : Port'만 받는다는 것을 의미합니다. 대상그룹의 프로토콜과 포트를 정의하는 것이죠. 예를 들어 HTTP:80으로 설정하면 이 대상그룹에 소속된 EC2들은 80 포트로 설정된 요청만을 받아들인다는 의미가 됩니다. 물론 리스너의 포트번호(8080)와 대상그룹의 포트번호(80)를 다르게 설정할 수 있으며 리스너에서 대상그룹으로 요청이 전달될 때 포트번호가 변경됩니다.
헬스 체크는 대상그룹에 소속된 EC2들의 상태를 점검할 때 HTTP 혹은 HTTPS를 사용하겠다는 것을 의미합니다. HTTP를 사용하기 때문에 3-way handshake를 통한 상태 체크에서 끝나지 않고 사용자가 원하는 웹페이지를 요청하여 상태 체크를 실시할 수 있고 경로 또한 지정할 수 있습니다. 모니터링 역시 HTTP에 대한 항목이 포함되어 있습니다. HTTP 2xx, 3xx, 4xx 응답 코드에 대한 모니터링을 제공하는 것이 특징입니다. HTTP를 지원하는 ALB의 대상그룹이기에 가능한 것입니다.
Application Load Balancer의 주요 라우팅 규칙
(설정 화면 : EC2 서비스 - 로드밸런서 - 리스너 - 규칙 편집)
ALB의 라우팅 규칙은 위에서 설명한 규칙, 사용자가 전달한 요청을 어느 대상그룹에 전달할 것인가를 판단하는 것으로 규칙 작업에 전달하는 기준이 됩니다. ALB는 HTTP 헤더를 활용할 수 있는 로드밸런서이기에 위의 그림에서 보시는 것처럼 매우 다양합니다. 그중에서 HTTP 헤더 활용에 해당하는 호스트 헤더, 경로 HTTP 헤더, HTTP 요청 메서드 등의 사용에 대해 설명하고자 합니다. 이와 별개로 대상 그룹에 속한 서버에게 요청을 고르게 분산하는 방법인 라우팅 알고리즘은 기본적으로 Rounb Robin(이하 라운드 로빈)이 사용됩니다.
호스트 헤더
호스트 헤더는 HTTP 헤더 중 하나인 호스트 헤더(도메인 네임)를 기준으로 삼아 라우팅을 결정하는 규칙입니다. 사용자가 입력한 도메인 네임을 읽고 정확히 일치하는 규칙을 결정합니다. 아래 그림은 호스트 헤더를 규칙조건으로 삼은 규칙을 보여주고 있습니다.
'규칙 1'은 호스트 헤더에 'first.aws-hyoh.com'가 포함될 경우 규칙 작업인 '고정 응답 반환'을 실시할 것을 정의하고 있습니다. 제가 도메인 네임을 'first.aws-hyoh.com'으로 입력하여 접속하면 '당신의 접속 도메인은 first.aws-hyoh.com입니다.'라는 문장이 적힌 웹페이지를 반환할 것입니다.
'규칙 2'는 호스트 헤더에 'second.aws-hyoh.com'가 포함될 경우 규칙 작업인 '리디렉션 대상'을 실시할 것을 정의하고 있습니다. 제가 도메인 네임을 'second.aws-hyoh.com'으로 입력하면 'www.naver.com'로 리디렉션되어 네이버 메인 화면이 나타납니다.
Wireshark의 패킷에서도 ALB가 활용하는 호스트 헤더를 확인하실 수 있습니다. 아래 그림을 보시면 빨간색 박스가 호스트 헤더입니다. ALB의 리스너는 이 부분을 보고 규칙 적합 여부를 판단한 것이죠.
경로(Path)
경로(Path)는 호스트가 제공하는 자원이 존재하는 위치를 뜻합니다. 사용자가 도메인 네임과 함께 경로를 입력하면 리스너는 그 경로를 읽고 규칙 조건으로 삼을 수 있습니다.
'규칙 1'과 '규칙 2' 모두 호스트 뒤에 연결된 경로를 읽고 이를 규칙 조건으로 삼아 규칙 작업을 실시합니다.
HTTP 헤더
'HTTP 헤더'는 위에서 봤던 호스트 헤더와 경로를 포함한 모든 HTTP 헤더를 의미합니다. 즉 사용자가 원하는 공통 헤더 혹은 요청 헤더를 골라 지정하여 라우팅 규칙으로 삼을 수 있다는 뜻이지요. AWS Application Load Balancer 쉽게 이해하기 #1에서 한 번 언급한 적이 있습니다.
위의 그림에서 볼 수 있는 수많은 HTTP 헤더들을 활용하여 라우팅 규칙으로 삼을 수 있습니다. 그 중에서 'User-Agent'를 활용하여 HTTP 헤더 규칙 조건을 테스트해보도록 하겠습니다. 'User-Agent'는 사용자가 사용 중인 기기에 대한 정보를 담고 있는 헤더로 어느 기기를 사용하는지, 운영체제는 무엇인지에 대한 정보가 담겨있습니다.
'규칙 1'은 사용자가 사용중인 브라우저가 '크롬(Chrome)'일 경우, '고정 응답 반환'을 통해 'From Chrome!'이라는 문장이 담긴 웹페이지를 반환하도록 하고 있습니다.
'규칙 2'는 사용자가 사용중인 브라우저가 '파이어폭스(Firefox)'일 경우, '고정 응답 반환'을 통해 'From Firefox'라는 문장이 담긴 웹페이지를 반환하도록 하고 있습니다.
이 밖에도 다른 헤더를 사용하여 규칙 조건으로 삼을 수 있습니다. 'Accept-Language'를 통해 사용자가 브라우저를 통해 요청한 언어를 판단하여 그에 맞는 언어의 웹페이지를 반환할 수도 있습니다. 각국의 다양한 사용자를 고객으로 두고 있는 회사라면 유용하게 사용할 수 있겠죠. 'Content-Type'을 통해 사용자가 요청하는 데이터의 타입, 인코딩 방식도 알 수 있고 'Authorization' 헤더를 통해 인증 토큰을 서버로 전달할 수 있습니다. 사용 방법이 무궁무진하죠?
HTTP 요청 메서드
HTTP 요청 메서드는 사용자가 서버에게 자신의 요청 목적 혹은 종류를 알리는 수단을 의미합니다. 종류에는 'GET', 'POST', 'HEAD', 'PUT', 'DELETE' 등이 있습니다. 예를 들어 'GET' 메서드는 서버의 리소스 전달을 요청하는 메서드이고 'HEAD' 메서드는 메시지 헤더, 문서 정보를 요청하는 메서드입니다. 이처럼 요청 메서드를 규칙 조건으로 삼아 규칙 작업을 실시할 수 있습니다. 또한 사용자가 만든 사용자 정의 메서드도 여기에 포함시킬 수 있습니다. 아래 그림을 보시면 'GET' 메서드 이외에 제가 임의로 만든 'USER' 메서드가 보입니다.
'규칙 1'은 'GET' 요청 메서드일 경우, '고정 응답 반환'을 통해 'HTTP GET Method 실시 확인!'이라는 문장이 담긴 웹페이지를 반환, '규칙 2'는 'USER' 사용자 정의 요청 메서드일 경우, '고정 응답 반환'을 통해 'HTTP USER Method 실시 확인!'이라는 문장이 담긴 웹페이지를 반환하도록 하고 있습니다. HTTP 요청 메서드를 이용해 라우팅을 실시한다는 점에서 'AWS API Gateway'를 연상케하는 기능입니다.
Application Load Balancer의 기타 기능
Connection Timeout(유휴 제한 시간)
Connection Timeout(이하 유휴 제한 시간)은 사용자의 요청으로 생성된 사용자와 서버 간의 커넥션이 유지되는 시간을 뜻합니다. Connection이하 커넥션) 이 생성되고 난 후, 유휴 제한 시간에 도달하기 전까지 커넥션을 유지하고 클라이언트가 보낸 패킷을 부하분산 대상으로 지정된 EC2에 지속적으로 전송합니다. ALB의 기본 유휴 제한 시간은 60초로 지정되어 있습니다. 60초가 지날 때까지 커넥션이 사용되지 않는다면 ALB가 보유하고 있는 사용자와 서버 간의 연결을 끊습니다.
(설정 화면 : EC2 서비스 - 로드밸런서 - 설명 - 속성)
사용자가 요청한 리소스를 서버가 모두 전달하면 사용중인 커넥션을 닫는 HTTP의 특성상, 60초는 짧은 시간이 아닙니다. HTTP/1.1의 고질적인 문제점인 'Head of line blocking'을 의식하여 일부러 길게 잡았다는 생각이 드는군요.
Sticky
Sticky(이하 스티키)는 사용자가 한 번 접속한 적이 있는 서버를 기억해두고 커넥션이 사라진 상태에서 사용자가 다시 접속하더라도 기존 커넥션이 있었던 서버로 연결해주는 기능입니다. ALB 역시 로드밸런서이기에 이 기능을 지원하며 Cookie(이하 쿠키)를 이용하여 스티키를 지원합니다. L4 스위치 쉽게 이해하기 #8에서 한 번 언급한 적이 있습니다.
(설정 화면 : EC2 서비스 - 대상그룹 - 그룹 상세 - 속성)
사용자가 ALB에 요청을 전달하고 EC2가 응답을 보낼 때 ALB가 쿠키를 응답 헤더에 쿠키를 포함시켜 사용자에게 전달합니다. 그리고 사용자는 ALB에 요청을 재차 전달할 때마다 해당 쿠키를 동봉하여 전달하고 ALB는 커넥션이 생성되었던 대상그룹의 EC2를 기억하고 다시 연결합니다. 스티키 유지 시간은 1초에서 7일까지 다양하게 설정할 수 있습니다. 원래 ALB가 생성하는 쿠키만이 스티키에 사용되었으나 21년 2월 업데이트에서 사용자 정의 쿠키도 사용할 수 있도록 기능이 추가되었습니다. 'Application-based cookie'가 바로 그것입니다.
X-Forwarded-For
'X-Forwared-For'는 HTTP 헤더 중 하나로 요청을 전달한 사용자의 IP를 담고 있는 헤더입니다. 아래 그림을 보시면 사용자 요청의 HTTP 헤더에 X-Forwared-For 헤더가 포함된 것을 확인할 수 있습니다. 그 밖에도 프로토콜을 알려주는 'X-Forwared-Proto', 포트를 알려주는 'X-Forwared-Port'도 보입니다. ALB는 사용자의 요청을 대상그룹으로 전달할 때 기본적으로 X-Forwared-For 헤더를 탑재하여 전달하게 됩니다.
X-Forwared-For 헤더가 필요한 이유는 바로 ALB가 사용자의 요청을 EC2로 전달할 때 자신의 사설 IP로 Source IP NAT를 실시하기 때문입니다. 즉 EC2로 요청이 전달될 때에는 사용자의 IP가 아닌 ALB의 IP가 Source IP로 보이기 때문에 실제 사용자의 IP를 EC2가 알 길이 없습니다. 그리하여 X-Forwared-For 헤더를 사용하여 사용자 IP를 전달하는 것입니다. 그리하면 해당 헤더를 통해 사용자 IP를 구별할 수 있게 되죠.
HTTP/2
HTTP/2는 월드 와이드 웹에서 쓰이는 HTTP 프로토콜의 두 번째 버전이다. 웹 브라우저의 페이지 로드 속도 개선을 목적으로 개발되었다.
다음과 같은 방법들을 이용하여 지연 시간을 감소시켜 웹 브라우저의 페이지 로드 속도를 개선하였다.
- HTTP 헤더 데이터 압축
- 서버 푸시 기술
- 요청을 HTTP 파이프라인으로 처리
- HTTP 1.x의 HOL blocking 문제 해결
- TCP 연결 하나로 여러 요청을 다중화 처리
- 출처 : 위키백과 -
HTTP/2는 HTTP의 두 번째 버전으로 현재 가장 많이 사용하고 있는 HTTP/1.1의 다음 버전입니다. HTTP/1.1이 가지고 있는 문제점들을 해결하기 위해 탄생하였습니다. 위에서 한 번 언급한 적이 있는 'Head of line blocking' 문제가 해결된 버전이 바로 'HTTP/2'입니다. ALB 또한 속도 향상을 위해 기본적으로 HTTP/2이 활성화되어있습니다. 아래 그림을 보시면 HTTP/2가 활성화된 로드밸런서의 모습을 확인할 수 있습니다.
(설정화면 : EC2 서비스 - 로드밸런서 - 설명 - 속성)
HTTP/2 활용을 위해서는 로드밸런서뿐만 아니라, 대상그룹에서도 '요청 프로토콜'을 설정해야 합니다. 'HTTP2'를 설정해야 HTTP/2을 사용하여 대상으로 요청을 전송합니다. 로드밸런서에서 HTTP/2를 지원한다하더라도 대상그룹의 프로토콜 버전이 'HTTP1'로 설정되어 있다면 HTTP/1을 사용하여 요청을 전송하게 되죠. 물론 서버도 HTTP/2를 지원해야 합니다.
(설정화면 : EC2 서비스 - 대상그룹 - 대상그룹 생성)
여기까지가 Application Load Balancer에 대한 설명입니다. HTTP를 활용하는 전문적인 로드밸런서인만큼 내용이 길어지네요. 다음 문서에서는 Network Load Balancer에 대해 알아보도록 하겠습니다. 감사합니다.