1. Load Balancer
- Load Balancer는 네트워크나 애플리케이션 서버와 같은 컴퓨터 자원에 대한 트래픽을 균형있게 분산시켜주는 중요한 기술적인 구성 요소입니다.
- 주로 대규모 웹 서비스, 애플리케이션, 데이터베이스 서버 등의 환경에서 사용되며, 여러 대의 서버에 들어오는 요청을 골고루 분산시켜 서버 부하를 분산시키고 가용성을 높이는 데 사용됩니다.
- NCP에서는 Application Load Balancer, Network Load Balancer, Network Proxy Load Balancer를 지원 중이며 이번 글에서는 Application Load Balancer와 Network Load Balancer를 사용해보겠습니다.
Load Balancer 사용목적
1. 부하 분산
로드 밸런서는 다수의 서버에 들어오는 트래픽을 균형 있게 분산시켜 각 서버의 부하를 줄입니다. 이로 인해 서버가 과부하 상태에 빠지는 것을 방지하고 서비스의 응답 시간을 개선합니다.
2. 가용성 향상
로드 밸런서는 여러 대의 서버 중 일부가 고장 날 경우에도 트래픽을 정상적으로 처리할 수 있도록 보장합니다. 장애가 발생한 서버를 우회하고 정상적으로 작동하는 서버로 트래픽을 전달함으로써 가용성을 향상시킵니다.
3. 확장성
서비스의 트래픽이 증가할 때, 로드 밸런서를 통해 새로운 서버를 추가하여 시스템을 확장할 수 있습니다. 이로써 시스템이 더 많은 트래픽을 처리할 수 있게 됩니다.
2. Application Load Balancer
- 웹 애플리케이션과 서비스의 트래픽을 균형있게 분산시키는 역할을 합니다.
- ALB는 OSI 모델의 응용 계층(Layer 7)에서 작동하며, HTTP 및 HTTPS 트래픽의 라우팅을 지원합니다.
2-1. Application Load Balancer 생성
1. Service -> Networking -> Load Balancer를 클릭합니다.
2. 로드밸런서 생성 -> 애플리케이션 로드밸런서 생성을 클릭합니다.
3. ALB 정보들을 설정합니다.
로드밸런서 이름 : 식별하게 편한 이름으로 정합니다.
Network : 외부에서 들어오는 트래픽을 분산해야하니 Public을 선택합니다.
부하처리 성능 : Small을 선택하겠습니다.
- 초당 연결 수(CPS) 기준으로 각각 30,000 / 60,000 / 90,000개의 성능을 보장합니다.
대상 VPC : test vpc 밖에 만든게 없으니 test를 선택
서브넷 선택 : LB는 전용 서브넷이 필요하니 서브넷 생성을 클릭합니다.
ALB를 거쳐 웹 서버로 들어가야하니 Public IP 선택, LB가 배치될 서브넷도 선택해야하는데 LB용 서브넷이 필요하니 서브넷 생성을 클릭합니다.
4. LB용 서브넷은 Private에만 생성 가능하니 Private 선택 후 Load Balancer용으로 생성합니다.
5. LB용 서브넷 선택 후 다음을 클릭합니다.
6. 웹 서버 부하분산을 위한거니 HTTP,80번 포트 그대로 놔두고 추가, 다음을 클릭합니다.
7. LB가 부하분산해줄 타겟 그룹을 선택해야 하지만 아직 타겟 그룹을 만들지 않았습니다.
Target Group 생성을 클릭합니다.
8. Target Group 탭으로 들어가지면 Target Group 생성을 클릭합니다.
9. 정보들을 입력하고 다음을 클릭합니다.
Target Group 이름 : 식별하게 편한 이름으로 정합니다.
Target 유형 : VPC Server니 VPC Server 선택
VPC : test vpc 밖에 만든게 없으니 test를 선택
프로토콜 : HTTP (TCP, PROXY_TCP, HTTP, HTTPS를 지원하며
사용 프로토콜에 따라 적용 가능한 로드밸런서가 달라집니다.)
포트 : HTTP 사용이니 80번 포트 그대로 사용하겠습니다.
9. 타겟 서버들에 대한 상태를 체크하기 위한 설정 입니다.
# HTTP를 서비스하고 있으므로 헬스 체크도 HTTP로 하겠습니다.
프로토콜 : HTTP
# HTTP가 80번 포트를 사용하니 포트도 80번 입니다.
포트 : 80
# 루트 페이지를 체크하기 위해 / 그대로 사용합니다.
URL Path : /
# HEAD Method는 ㅠ서버로부터 응답 본문을 받지 않고 헤더 정보만을 요청합니다.
# 이는 서비스가 정상적으로 응답하는지 확인하는 데 유용한 Method 입니다.
HTTP Method : HEAD
# 로드 밸런서가 매 30초마다 헬스 체크를 수행합니다.
Health Check 주기(초) : 30
# 두 번 연속으로 헬스 체크 요청이 성공해야 서비스가 정상으로 간주됩니다.
정상 임계값 : 2
# 두 번 연속으로 헬스 체크 요청이 실패하면 서비스가 이상으로 간주되고
# 해당 서버는 정상으로 돌아올때까지 타겟에서 제거될 수 있음을 의미합니다.
실패 임계값 : 2
10. 타겟으로 지정할 서버들을 선택하고 > 를 클릭합니다.
11. 선택된 서버들이 적용 Target으로 넘어간걸 확인하고 다음을 클릭합니다.
12. 마지막으로 설정한 정보들을 확인하고 Target Group 생성을 클릭합니다.
13. 타겟 그룹이 생성되었습니다. Target Group을 클릭해보겠습니다.
14. StickySession과 Algorithm 옵션이 보입니다. 단순 웹페이지만 만들었으니 확인만하고 넘어가겠습니다.
StickySession
클라이언트 요청이 사용자 세션을 유지하면서 항상 동일한 서버 또는 백엔드 노드로 전달되도록 합니다.
Web01 서버에 접속해서 로그인을 했을시 서버에서 세션을 생성하는데 로드밸런서의 부하분산으로 인해
Web02 서버로 접속했을때 다시 로그인을 해야하는 일이 발생하는 것을 방지 합니다.
Algorithm
1. Round Robin
서버 커넥션 수, 응답 상황 등에 관계없이 균등하게 순차적으로 요청을 할당하는 방식
서버가 일반적인 구성일 때 다른 방식에 비해 처리 속도가 빠름
2. Least Connection
가장 적은 수의 연결이 이루어진 서버로 요청을 할당하는 방식
비슷한 성능의 서버로 구성되어 있을 때 가장 효과적인 부하 분산 가능
3. Source IP Hash
클라이언트의 Source IP 정보를 해시한 결과에 따라 요청을 할당하는 방식
SSL 프로토콜을 사용하는 경우 권장
15. 이제 다시 Load Balancer 생성으로 돌아겠습니다.
새로고침 아이콘을 클릭하면 방금 만든 타겟그룹이 보입니다. 타겟그룹을 선택합니다.
16. 타겟그룹에서 설정한 정보들이 보입니다. 확인하고 다음을 클릭합니다.
17. 전체적인 정보를 확인하고 로드 밸런서 생성을 클릭합니다.
18. Application Load Balancer가 생성되었습니다.
해당 Load Balancer는 외부에서 웹서버로의 접근을 부하분산하기위해 공인으로 생성하였기에 접속 정보를 통해 외부에서 접속하게 됩니다.
19. Target Group 탭으로 간 후 타겟 그룹 선택 -> Target 상태 확인을 클릭합니다.
20. 타겟들의 상태를 확인할 수 있습니다.
2-2. Global DNS 설정
1. 이제 LB의 접속정보를 통해 외부에서 웹서버에 접속할 수 있도록 Global DNS에서 레코드를 수정해보겠습니다.
Global DNS 서비스로 들어가 먼저 설정했단 A레코드를 선택 후 레코드 수정을 클릭합니다.
2. 레코드 수정에서 LB VPC를 선택하면 레코드 값 목록에 LB의 접속정보가 나옵니다.
레코드 값으로 LB의 접속정보를 선택하고 빠른 적용을 위해 TTL 값은 60초로 바꿔보겠습니다.
3. 잊지 말고 설정 적용을 클릭합니다.
4. 배포를 클릭합니다.
5. 레코드값이 서버의 IP에서 LB의 접속정보로 바뀌었습니다.
6. 이제 도메인으로 접속해보면 Web01과 02 서버에 번갈아가며 접속되는걸 확인할 수 있습니다.
ALB로 웹 서버로의 트래픽을 부하분산 해봤습니다.
다음은 Network Load Balancer를 생성해 Public Subnet에서 Private Subnet으로 가는 트래픽도 부하분산 해보겠습니다.
3. Network Load Balancer
- Network Load Balancer는 대용량 TCP 레이어 부하 분산 처리에 특화된 Load Balancer입니다.
- 클라이언트 IP를 그대로 로깅하며, 2가지(Round Robin, Hash) 로드밸런싱 알고리즘을 제공합니다.
- NLB의 큰 특징으로는 DSR (Direct Server Return)이라는 기능이 있습니다.
3-1. DSR (Direct Server Return)
- DSR은 네트워크 트래픽을 최적화하고 서버 응답을 로드 밸런서를 우회하여 클라이언트에 직접 전송하는 방식으로 동작합니다.
- 주로 웹 서비스 및 애플리케이션의 성능과 확장성을 향상시키는 데 사용됩니다.
1 .직접 응답 경로
서버가 요청을 처리한 후 응답을 로드 밸런서를 우회하고 클라이언트의 IP 주소로 직접 전송합니다.
이러한 직접 응답 경로는 네트워크 지연을 줄이고 응답 트래픽이 로드 밸런서를 통해 다시 전달될 필요가 없습니다.
2. 성능 및 확장성
DSR은 로드 밸런서가 응답 트래픽을 처리하지 않아 로드 밸런서의 부하를 줄이고 더 많은 동시 연결을 처리할 수 있도록 성능과 확장성을 향상시킬 수 있습니다.
3. 투명성
DSR은 클라이언트에게 투명합니다.
클라이언트는 로드 밸런서의 IP 주소와 통신하며 응답이 백엔드 서버 중 하나로부터 직접 온 것임을 알지 못합니다.
3-2. Was 서정
현재 Public에 Web서버가 생성되어있는데 Private에 Was서버를 2개 생성하고 클라이언트와의 요청은 Web서버에서, 실질적인 컨텐츠(PHP)는 Was에서 처리하도록 구성하고 Public과 Private 사이에 NLB를 배치하여 Was로의 요청을 부하분산 해보겠습니다.
1. 우선 NAT Gateway때 Private Subnet에 생성한 ubuntu 서버를 지우고 Web서버와 동일하게 Rocky Linux로 생성한 후 접속하겠습니다.
*acg도 private용으로 새로 만들어줍니다.
vpc-test-private
Inbound
TCP 0.0.0.0/0 22
TCP 0.0.0.0/0 9000 (PHP-FPM이 사용할 포트)
Outbound
TCP 0.0.0.0/0 1-65535
UDP 0.0.0.0/0 1-65535
ICMP 0.0.0.0
2. web에서 보내는 요청을 받아 was에서 php를 처리할 수 있도록 php-fpm을 설치합니다.
PHP-FPM (PHP FastCGI Process Manager)
PHP 스크립트를 처리하는 데 사용되는 프로세스 관리자입니다.
PHP-FPM은 PHP 프로그램을 실행하는 데 사용되며, 특히 웹 서버와 함께 사용됩니다.
1. FastCGI 프로토콜
PHP-FPM은 웹 서버와 PHP 스크립트 간의 통신을 담당하는 FastCGI 프로토콜을 구현합니다.
FastCGI는 웹 서버와 백엔드 프로세스 간의 효율적인 통신을 제공하며,
이를 통해 다양한 웹 서버 (예: Nginx, Apache)와 PHP 애플리케이션 간의 호환성을 확보합니다.
2. 프로세스 관리
PHP-FPM은 PHP 스크립트를 처리하는 데 사용되는 여러 PHP 프로세스를 관리합니다.
이렇게 함으로써 동시 요청을 처리하고, 프로세스를 시작하거나 종료하여 리소스를 효율적으로 사용할 수 있습니다.
3. 성능 향상
PHP-FPM은 다중 프로세스 및 스레드를 지원하므로 여러 동시 요청을 병렬로 처리할 수 있습니다.
이는 웹 애플리케이션의 성능을 향상시키는 데 도움이 됩니다.
4 .PHP 확장성
PHP-FPM을 사용하면 웹 서버와 PHP 애플리케이션을 수평으로 확장할 수 있으므로 더 많은 트래픽을 처리할 수 있습니다.
일반적으로 PHP-FPM은 Nginx, Apache와 같은 웹 서버와 함께 사용되며,
웹 호스팅 환경에서 웹 애플리케이션의 성능을 향상시키는 데 중요한 역할을 합니다.
# YUM 패키지 관리자를 사용하여 php-fpm을 설치합니다.
# -y 옵션은 패키지 설치 동안 모든 질문에 자동으로 "예"로 응답하도록 하는 옵션입니다
yum -y install php-fpm
3. php-fpm을 설치했으니 이제 설정을 해보겠습니다.
cd /ete/php-fpm
# 원본 파일 백업
mv www.conf backup
# 새로운 파일 생성하여 설정
vi www.conf
# 어떤 서브 도메인의 설정인지 명시합니다. 지금은 www를 사용중이니 www를 적겠습니다.
[www]
# PHP-FPM 프로세스가 실행될 때 사용할 사용자 및 그룹을 지정합니다.
user = nginx
group = nginx
# PHP-FPM 소켓을 포트에서 듣도록 할 것인지 지정합니다.
listen = 9000
# 소켓 소유자 및 그룹을 지정합니다.
listen.owner = nginx
listen.group = nginx
# 소켓 파일의 권한를 지정합니다.
# 0660으로 설정하여 소켓에 대한 읽기 및 쓰기 권한이 사용자와 그룹에 부여됩니다.
listen.mode = 0660
# PHP-FPM 프로세스 관리 방식을 설정합니다.
# dynamic으로 설정하여 동적 프로세스 관리를 사용합니다.
pm = dynamic
# 최대 자식 프로세스 수를 설정합니다. 여기서는 최대 5개의 자식 프로세스를 허용합니다.
pm.max_children = 5
# PHP-FPM이 시작될 때 자식 프로세스의 초기 수를 설정합니다. 이 경우 2개의 시작 서버를 설정합니다.
pm.start_servers = 2
# 최소한으로 유지할 자식 프로세스 수를 설정합니다. 이 경우 1개의 최소한으로 유지할 서버를 설정합니다.
pm.min_spare_servers = 1
# 최대한으로 유지할 자식 프로세스 수를 설정합니다. 이 경우 3개의 최대한으로 유지할 서버를 설정합니다.
pm.max_spare_servers = 3
# PHP-FPM 프로세스가 작업 디렉터리로 사용할 디렉터리를 지정합니다.
# 여기서는 "/web" 디렉터리를 작업 디렉터리로 사용합니다.
chdir = /web
[www]
user = nginx
group = nginx
listen = 9000
listen.owner = nginx
listen.group = nginx
listen.mode = 0660
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
chdir = /web
4. www.conf에서 설정한대로 /web 디렉토리를 생성 후 index.php를 생성합니다.
index.php에는 현재 이 페이지를 처리중인 Host의 이름과 IP, 문서의 경로가 나오도록 해뒀습니다.
mkdir /web
vi /web/index.php
<!DOCTYPE html>
<html>
<head>
<title>Welcome to the NCP</title>
</head>
<body>
<?php
echo "Host Name: <b>";
echo exec("hostname");
echo "</b></p>";
echo "Private IP: <b>";
echo exec("hostname -I");
echo "</b></p>";
$file_server_path = realpath(__FILE__);
echo "현재 문서의 절대 경로 : <b>$file_server_path</b>";
?>
</body>
</html>
5. php-fpm을 실행하고 부팅시 자동실행 등록 후 제대로 적용됐는지 확인합니다.
# php-fpm 서비스를 시작합니다
systemctl start php-fpm
# php-fpm 서비스를 부팅 시 자동으로 시작하도록 설정합니다
systemctl enable php-fpm
# php-fpm의 상태 확인
systemctl status php-fpm
# 서비스 목록을 불러오고 그 중 php를 출력
systemctl list-unit-files --type service | grep php
3-3. Web 설정
- was에서의 설정은 끝났으니 이제 web에서 was로 요청을 보내도록 설정을 해보겠습니다.
1. nginx에서 php에 대한 요청을 was 보내게 하기위해 nginx 파일을 수정해줘야 합니다.
cd /etc/nginx
vi nginx.conf
2. nginx.conf 파일에 php를 사용하도록 하게하고 php에 대한 요청을 was로 넘기는 설정을 추가합니다.
# Nginx에게 인덱스 파일로 "index.php"를 사용하도록 지시합니다.
# 디렉토리에 접근하는 요청이 있고 해당 디렉토리에 "index.php" 파일이 있다면
# Nginx는 "index.php" 파일을 사용하여 요청을 처리합니다.
index index.php;
# URI의 확장자가 ".php"로 끝나는 요청을 처리하는 블록을 정의합니다.
location ~ \.php$ {
# Nginx가 PHP 요청을 처리하기 위해 FastCGI 서버에 연결하도록 지시합니다.
# Was(10.0.202.6)의 9000번 포트로 연결합니다.
fastcgi_pass 10.0.202.6:9000;
# FastCGI 서버에 요청 시 "index.php" 파일을 기본 인덱스 파일로 사용하도록 지시합니다.
fastcgi_index index.php;
# Nginx의 FastCGI 구성에 필요한 기본 매개 변수를 가져옵니다. (/etc/nginx/fastcgi_params)
이 매개 변수들은 FastCGI 요청을 처리하는 데 사용됩니다.
include fastcgi_params;
# FastCGI 서버로 전달되는 PHP 스크립트 파일의 경로를 지정합니다.
# /web 경로 다음에 fastcgi_script_name 변수의 값을 붙여서 PHP 스크립트의 실제 경로를 생성합니다.
# /web은 아까 was에서 설정했던 경로 입니다.
fastcgi_param SCRIPT_FILENAME /web$fastcgi_script_name;
# FastCGI 서버로 전달되는 PATH_INFO 환경 변수를 설정합니다.
# PATH_INFO는 PHP 스크립트에 대한 추가 정보를 제공하는데 사용됩니다.
fastcgi_param PATH_INFO $fastcgi_path_info;
}
index index.php;
location ~ \.php$ {
fastcgi_pass 10.0.202.6:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /web$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
3. 수정이 끝났다면 nginx를 재실행하고 웹에 접속해서 확인합니다.
systemctl restart nginx
4. web에서 was로 php 요청을 보내는 것에 대해서는 확인이 끝났으니 NLB 테스트를 위해 Server Image로 was01을 복사해 was02 서버를 만들어줍니다.
현재 구성도 입니다.
Was 서버도 2개로 만들어놨으니 이제 Network Load Balancer로 Was로의 부하분산을 해보겠습니다.
3-4. Network Load Balancer 생성
1. Service -> Networking -> Load Balancer -> Target Group을 클릭합니다.
2. Target Group 생성을 클릭합니다.
3. 정보들을 입력하고 다음을 클릭합니다.
Target Group 이름 : 식별하게 편한 이름으로 정합니다.
Target 유형 : VPC Server니 VPC Server 선택
VPC : test vpc 밖에 만든게 없으니 test를 선택
프로토콜 : TCP (NLB에서 사용할 타겟이니 TCP를 선택하겠습니다)
포트 : 9000 (php-fpm에서 사용할 9000번 포트)
4. 타겟 서버들에 대한 상태를 체크하기 위한 설정 입니다.
# php-fpm은 TCP 소켓을 사용하니 TCP를 선택합니다.
프로토콜 : HTTP
# php-fpm에서 설정한 9000번을 입력합니다.
포트 : 9000
# 로드 밸런서가 매 30초마다 헬스 체크를 수행합니다.
Health Check 주기(초) : 30
# 두 번 연속으로 헬스 체크 요청이 성공해야 서비스가 정상으로 간주됩니다.
정상 임계값 : 2
# 두 번 연속으로 헬스 체크 요청이 실패하면 서비스가 이상으로 간주되고
# 해당 서버는 정상으로 돌아올때까지 타겟에서 제거될 수 있음을 의미합니다.
실패 임계값 : 2
5. Was01과 02를 선택 후 > 를 클릭해서 적용 Target으로 옮겨진걸 확인 후 다음을 클릭합니다.
6. 정보 확인 후 Target Group 생성을 클릭합니다.
7. Target Group 설정을 들어가보면 알고리즘으로 Hash가 선택되어 있는데 저는 Round Robin을 사용해보겠습니다.
8. 타겟그룹 생성은 끝났으니 Load Balancer 탭을 클릭합니다.
9. 로드밸런서 생성 -> 네트워크 로드밸런서 생성을 클릭합니다.
10. NLB 정보들을 설정합니다.
로드밸런서 이름 : 식별하게 편한 이름으로 정합니다.
Network : 내부(Web -> Was)의 트래픽을 분산할 용도니 Private를 선택합니다.
부하처리 성능 : Small을 선택하겠습니다.
- 초당 연결 수(CPS) 기준으로 각각 100,000 / 200,000 / 400,000개의 성능을 보장합니다.
대상 VPC : test vpc 밖에 만든게 없으니 test를 선택
서브넷 선택 : ALB 생성때 만든 test-lb 서브넷을 선택합니다.
11. 분산해야 할 요청(TCP 9000) 추가 후 다음을 클릭합니다.
12. 미리 생성한 was-tg을 선택 후 다음을 클릭합니다.
13. 마지막으로 설정한 정보들을 확인하고 로드 밸런서 생성을 클릭합니다.
14. NLB가 생성되었습니다. 접속정보를 복사해둡니다.
15. Web01과 02에서 fastcgi_pass를 was01의 IP에서 NLB의 접속 정보로 바꿔주고 nginx를 재실행 합니다.
Web01 & Web02
vi /etc/nginx/nginx.conf
변경 전
fastcgi_pass 10.0.202.6:9000;
변경 후
fastcgi_pass test-was-19602052-978a56347134.kr.lb.naverncp.com:9000;
systmectl restart nginx
16. 모든 설정이 끝났습니다. 이제 도메인으로 들어가 was01과 02로 분산되는걸 확인합니다.
ALB와 NLB를 생성해 외부에서 Web로의, Web에서 Was로의 트래픽을 부하분산 해봤습니다.
다음 글에서는 별개의 서버에서 다른 서브 도메인이나 서브 디렉토리로 웹을 운영중일시 ALB에서 설정하는 법을 다뤄보겠습니다.
Load Balancer-2 : https://angrycloud.tistory.com/31