반응형

 

이전 포스팅에서 Auto scaling group을 통해서 EC2 인스턴스를 자동으로 Scale-out하여 관리하는 방법에 대해서 알아보았었다.

이번에는 해당 클러스터 (혹은 단일 EC2 인스턴스)를 로드밸런서에 연결해보는 과정을 해보려고 한다.

 

1. ELB (Elastic Load Balancer) 소개 
2. ELB의 구성 요소 : 대상 그룹 (Target Group), 리스너 (Listener)
3. ELB의 종류 : ALB, NLB, GLB, CLB
4. EC2 Autoscaling Group에 ALB 적용하기
5. 리스너 규칙 설정 : 2개 이상의 Autoscaling Group에 경로에 따라 트래픽 분산하기

 

 

 

 


ELB (Elastic Load Balancer)

 

두 개 이상의 가용 영역에서 EC2 인스턴스 및 Autoscaling 그룹, 컨테이너, IP 주소 등 여러 대상의 트래픽을 자동으로 분산해주는 서비스.

 

 

1. 트래픽 분산 : 다양한 대상 그룹(Target Group) 에 대해 트래픽을 균등하게 분배

2. Health Check : 주기적으로 대상에 트래픽을 발생시켜 상태를 확인하여 Unhealthy한 대상은 트래픽 분배 대상에서 제외.

3. 도메인으로 접근 필요: 기본적으로 로드 밸런서는 IP 주소가 동적으로 할당되기 때문에 IP 주소 대신 도메인 이름을 사용하여 접근

  • NLB와 같은 유형의 LB는 Elastic IP를 통해 고정 IP 사용 가능

 

 

아래의 그림은 ELB와 EC2 Autoscaling을 활용하여 아키텍쳐를 구성한 모습이다.

 

 

 

 

특히 Auto Scaling Group 사용 시 ELB(Elastic Load Balancer)는 거의 필수적으로 함께 아키텍쳐를 구성한다.

 

위의 그림은 Auto Scaling Group과 ELB의 조합을 통해 트래픽을 분산하고, 애플리케이션의 동작을 유지하는 구조를 보여준다.

 

Auto Scaling만 사용했을 경우의 가장 큰 문제점은, 클라이언트가 각 EC2의 Public Address에 직접 접근해야 하기 때문에 단일 진입점이 존재하지 않는다. 동적으로 새로 추가되거나 삭제된 인스턴스를 클라이언트가 인식하기 어렵기 때문에 라우팅 처리가 어렵다.

 

ELB는 인터넷 게이트웨이에서 들어오는 모든 트래픽을 받아 Auto Scaling Group 내의 인스턴스에 고르게 분배한다. 이 과정에서 트래픽은 각 AZ에 있는 서브넷을 통해 전달된다. 또한 비정상 인스턴스를 감지하여 해당 인스턴스로는 트래픽을 보내지 않는 등 장애에 대처할 수 있다.

 

 

 


ELB의 구성 요소

 

 

대상 그룹

대상 그룹은 로드 밸런서가 트래픽을 분배할 대상을 정의하고 관리하는 역할을 한다. 로드 밸런서는 리스너 규칙에 따라 요청을 특정 대상 그룹으로 전달하며 대상 그룹은 이러한 요청을 실제 서비스(EC2, Autoscaling Group, Lambda 등)로 연결하는 역할이다.

 

구성 요소

 

1. 대상 종류 : Instance (EC2 인스턴스), IP Address, Lambda(AWS 서버리스 Functions), ALB (또 다른 LB를 대상으로 설정 가능)

 

2. 프로토콜: HTTP, HTTPS, gRPC, TCP 등을 지원.

 

3. Health Check: 대상의 상태를 모니터링하기 위한 트래픽 발생. 트래픽 발생 엔드포인트를 지정할 수 있어 Application 내부의 문제도 파악할 수 있다. 

  • cf) EC2 : 인스턴스의 실행 여부 및 하드웨어 지표를 바탕으로 정상 여부 확인. →  Application의 정상 작동 여부는 체크할 수 없다.

4. 기타 설정:

  • 트래픽 분산 알고리즘: 기본적으로 Round Robin 방식이지만, 필요에 따라 변경 가능.
  • 고정 세션(Sticky Session): 동일 클라이언트의 요청을 항상 동일한 대상에게 전달하도록 설정.

 

 


리스너 (Listener)

ELB로 들어오는 요청을 처리하는 주체. 리스너는 특정 프로토콜과 포트를 수신하도록 설정된다.

리스너는 요청이 들어왔을 때 어떤 규칙(Rule)을 적용해 트래픽을 처리할지 결정한다. 예를 들어 특정 URL 요청은 웹 서버로 전달하고, 다른 URL 요청은 API 서버로 전달하도록 설정할 수 있다. 

 

 

규칙 (Rule)

 

리스너 규칙을 기반으로 ALB에서 어떤 요청을 받을지 결정. 요청 처리 방식과 라우팅 대상(대상 그룹)을 설정. 규칙은 크게 "조건" "처리 방식"으로 구성될 수 있다.

 

  • 트래픽 배분 조건 : 어떤 트래픽에 대해서 규칙에 정의한 처리 방식을 적용할 것인지에 대해서 기준 조건을 설정한다.
    • 경로, HTTP Header, Query String, Source IP, HTTP Method 등을 기준으로 설정할 수 있음.
  • 트래픽 처리 방식 : 트래픽을 어떤 방식으로 처리할 것이지를 결정한다.
    • Forward: 트래픽을 지정된 대상 그룹으로 전달.
    • Redirect: 클라이언트를 특정 URL로 리디렉션.
    • Fixed-response: 지정된 HTTP 상태 코드와 메시지로 응답.

 


 

 

 

다시 위의 그림을 살펴보면서 ELB의 구성에 대해서 살펴보자.

  1. 대상 그룹(Target Group)은 하나 이상의 대상(Target)을 포함하며, Health Check를 통해 가용 상태를 지속적으로 확인한다.
  2. 로드 밸런서는 요청을 수신하며, 각 요청은 리스너(Listener)로 전달된다.
  3. 리스너는 설정된 규칙(Rule)에 따라 트래픽을 분배하며, 조건에 따라 특정 대상 그룹으로 요청을 전달하거나 기타 처리 방식으로 트래픽을 처리한다.

 

 

 


ELB의 종류

 

1. Application Load Balancer (ALB)

  • OSI 7 Layer
  • HTTP/HTTPS 트래픽에 최적화되어 있으며, URL 또는 Host 기반으로 요청을 라우팅.
  • 다중 대상 그룹을 설정하여 요청을 각각 다른 인스턴스, Auto Scaling Group, 컨테이너 등으로 보낼 수 있다.
  • 주요 용도 : 유연한 애플리케이션 수준의 트래픽 관리 및 라우팅이 필요한 경우. RESTful API 서비스, 웹 애플리케이션 등

2. Network Load Balancer (NLB) 

  • OSI 4 Layer
  • 빠른 처리, TCP/UDP 트래픽 분산 처리에 최적화
  • 주요 용도 : 실시간 데이터 처리 및 고성능, 짧은 지연 시간, 확장 가능한 네트워크 수준 밸런싱 용도
  • Elastic IP를 할당하여 고정 IP 사용 가능.

3. Gateway Load Balancer (GLB)

  • 보안 및 트래픽 검증이 요구되는 환경에서 사용되며 트래픽을 필터링하거나 검사 후 전달
  • 서로 다른 리전 및 네트워크 간 트래픽 라우팅 가능. 주요 네트워크 장비(방화벽, IDS/IPS 등)와 통합하여 사용 가능
  • 주요 용도 : 트래픽 모니터링 및 검사, 여러 리전에 걸쳐 트래픽을 관리하는 경우 통합 로드밸런서의 역할 등

4. Classic Load Balancer (CLB)

  • 구버전. 현재 잘 사용되지 않음

 

 

 


EC2 Autoscaling Group에 ALB 적용하기

 

 

 

우리는 다음 사진처럼 Auto Scaling Group의 단일 엔드포인트로서의 사용 목적, 정상 인스턴스로의 자동 트래픽 분배 목적을 위해서 ELB를 적용시켜 볼 예정이다.

 

 

 

 

 


1. 시작 템플릿 준비 및 Autoscaling Group 생성

 

 

이전 포스팅에서 EC2의 Auto scaling을 위해서 다음 작업을 거쳤었다.


시작 템플릿 및 유저데이터 설정 : EC2 서버에 HTTP 기본 포트에 간단한 HTML을 띄우는 웹 서버를 구축하기 위한 템플릿 준비

Autoscaling Group 생성 : 시작 템플릿을 기반으로 EC2 클러스터 생성

 

#!/bin/bash
# Root 권한 획득
sudo -s

# Apache 설치
dnf install httpd -y

# Apache 서비스 시작 및 부팅 시 자동 실행 설정
service httpd start
chkconfig httpd on

# 메타데이터에서 인스턴스 ID 가져오기
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
INSTANCE_ID=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/instance-id)

# 인스턴스 ID를 기본 index.html에 기록
echo "SERVICE A : $INSTANCE_ID" > /var/www/html/index.html

 

Autoscaling Group을 구성하는 각 EC2 인스턴스에서는 Apache Server를 통해서 HTTP 80번 포트에 index.html을 제공하는 웹 서버를 Userdata를 통해 구축하도록 설정했었다.

 

 

 

생성된 Autoscaling 그룹과 그것을 구성하는 EC2 서버에 접속한 모습

 

 

 

자세한 내용은 아래의 포스팅을 참조하도록 하자.

https://sjh9708.tistory.com/251

 

[AWS] Autoscaling : EC2 클러스터 구성 및 스케일링 정책 적용

이번 포스팅에서는 고가용성을 위한 Scale-out이 필요할 때 AWS EC2 인스턴스를 여러 AZ에 분산하여 운영하는 것을 자동화하여 지원하는 Autoscaling 기능에 대해서 살펴보려고 한다.  주요 목차1. EC2 Au

sjh9708.tistory.com

 

 

 

 


2. 대상 그룹 생성

 

로드 밸런서가 트래픽을 분배할 대상을 정의하고 관리하기 위해서 대상 그룹을 생성해보자.

로드밸런서의 트래픽을 넘겨받아 처리할 EC2 Autoscaling Group을 대상 그룹으로 등록해두어야 로드 밸런서에서의 규칙(Rule)과 연동이 가능해지는 것이다.

 


 

대상 유형 : 앞에서 언급했던 것 처럼 EC2 인스턴스, IP주소, Lambda, ALB 등을 등록할 수 있다. 우리는 Auto scaling 그룹을 등록해야 하지만 일단 인스턴스로 설정하고 넘어가보자.

 

프로토콜 : 포트 : 대상 그룹인 EC2 인스턴스 (클러스터)가 트래픽을 넘겨받을 네트워크 프로토콜과 포트를 지정하는 것이다.

즉 백엔드 서버(EC2 인스턴스)가 수신 대기하는 프로토콜과 포트에 맞게 설정해야 한다.  우리는 기본 HTTP (80번 포트)를 사용하여 배포했으므로 80번을 선택해주었다.

 

 


 

대상 그룹과 ELB간의 통신 방법 및 Health Check의 트래픽을 정의하는 곳이다.

  • IP 주소 유형: EC2 인스턴스의 사용 네트워크 프로토콜. (대부분은 IPv4를 사용하는 편)
  • VPC: 대상 그룹에 속한 인스턴스들이 통신할 네트워크(VPC) 선택.
  • 프로토콜 버전: ELB에서 대상 그룹으로 트래픽을 전달할 때 사용할 HTTP 프로토콜 방식 선택.

Health Check는 주기적으로 사용자가 정의한 트래픽을 발생시켜서 서비스들의 상태를 체크한다고 하였다. 따라서 그 행위를 정의할 수 있다.

 

현재는 그냥 Apache Server HTTP 기본 포트의 index.html 파일에 접근하는 트래픽으로 사용하였지만, REST API의 GET /health 등의 헬스체크 전용 엔드포인트 등을 지정하여 사용하는 방식이 많이 사용된다.

 

 

 

 

Health Check의 간격, 제한 시간, 비정상 판단 임계치 등에 대한 세부 설정도 할 수 있다.

 

 

 


 

대상 등록을 하는 곳인데, 아까 대상 유형을 선택할 때 EC2 인스턴스를 선택했기 때문에 EC2 인스턴스의 목록들이 나올 것이다.

만약 Autoscaling 그룹이 아닌 EC2들을 직접 선택하여 대상 그룹으로 포함시킬 용도였다면 여기서 선택하면 된다.

 

그렇지만 우리는 Auto-scaling 클러스터의 인스턴스를 자동으로 등록할 것이기 때문에 Auto-scaling Group에서 대상그룹과 연동되도록 뒤에서 설정할 것이다. 따라서 체크하지 않고 넘어간다.

 

 

 

 


3. Autoscaling Group과 대상 그룹 연결

 

 

Autoscaling Group에 앞에서 만든 대상 그룹을 설정해서 로드 밸런서의 트래픽 대상으로 설정할 수 있도록 해주자.

 

 

 

 


4. Application Load Balancer (ALB) 생성

 

앞에서 살펴보았던 다양한 ELB의 유형을 선택할 수 있는 곳이다. 우리는 ALB를 선택하고 진행하자.

 

 

 


네트워크 설정 

 

 

로드 밸런서가 분배해 줄 대상 그룹의 서비스들이 속한 VPC 및 가용 영역의 서브넷들을 모두 선택해주자. ALB에서 선택하지 않은 AZ에 속한 대상 그룹의 서비스에는 트래픽을 보내지 않는다.

 

체계 선택은 로드 밸런서가 처리할 트래픽의 접근 범위(인터넷 경계 또는 내부)를 결정하는 설정이다. 우리는 웹 애플리케이션이기 때문에 인터넷 경계를 선택해주었다.

  • 인터넷 경계 : 외부에서 접근하는 트래픽을 라우팅하는 용도의 ALB의 경우 선택한다. 즉 인터넷 사용자(외부 클라이언트)가 직접 접근해야 하는 서비스에 사용한다.
  • 내부 : 내부 시스템 간 통신을 위한 서비스의 로드 밸런싱을 위해서 사용한다. 마이크로서비스간의 통신이 대표적이다.

 

 

 


리스너 및 라우팅 설정

 

 

리스너를 생성하고 기본적인 설정을 정의하는 곳이다. 디폴트 작업을 함께 설정할 수 있다.

여기서는 HTTP 80번 포트로 들어오는 트래픽을 모두 Auto Scaling Group A에게 라우팅하여 넘겨주겠다는 리스너를 추가했다.

 

 

 


5.  결과 확인

 

 

이제 ALB까지 구축이 완료되어 Auto scaling group이 동적으로 EC2 인스턴스를 추가하거나 삭제하더라도, 사용자 요청은 항상 가용 가능한 인스턴스로 분배되도록 구축하였다.

 

 

 

 

 

 

 

 

 

 

 


ALB 리스너 규칙 설정 : 두 개 이상의 서비스 그룹으로 라우팅하기

 

 

이번에는 위의 그림과 같이 HTTP 80번 Listener로 들어오는 트래픽에 대해서 두 종류의 Autoscaling Group으로 라우팅을 해보도록 하겠다.

URL 경로를 기준으로 /serviceA/* 와 /serviceB/*에 따라서 라우팅하도록 Listener의 규칙(Rules)를 설정해보도록 하자.

 

 

 

 


이것을 위해서 위에서 했던 과정과 동일하게 Service A와 Service B의 Auto Scaling group을 생성해주었다.

 

 

 

 


리스너 및 규칙 편집

 

ALB 설정의 하단부의 리스너 및 규칙 탭을 클릭하면 우리가 설정했던 HTTP 80번 포트에 대한 리스너를 확인할 수 있다. 해당 리스너를 편집할 것이다.

 

 

 

리스너 관리를 통해서 세부 정보를 조회해보면 설정되어 있는 리스터의 기본 규칙을 볼 수 있다. 앞에서 기본 규칙으로 모든 트래픽에 대해서 Autoscaling Group service A로 가도록 설정하였었는데, 해당 규칙을 추가하고 편집하여 우리가 원하는 형태로 만들어 줄 것이다.

 

 

 


규칙 추가 

 

새로운 규칙을 만들어 주기 위해서 규칙 추가를 눌러주자. 리스너 80번의 트래픽을 조건에 따라 동적으로 두 개의 Autoscaling Group으로 분배하기 위해서이다.

 

 

 


규칙 조건 설정

 

 

먼저 생성할 규칙의 조건 유형을 설정해야 한다. 즉 어떤 것을 기준으로 트래픽을 구분지어 규칙 작업을 수행하게 할 것인지에 대한 것이다.

  • 호스트 헤더 (Host Header): Host 헤더 값 기준 → ex) example.com의 Host는 대상 그룹 A로 라우팅
  • 경로 (Path): 요청 URL의 경로를 기준, 와일드카드 사용 가능. → ex) /api/로 시작하는 모든 요청은 대상 그룹 B로 라우팅
  • 쿼리 문자열 (Query String): 요청의 쿼리 문자열을 기반으로 라우팅  ex) http://lb?version=2 쿼리 문자열에 따라서 V2 API로 라우팅.
  • 소스 IP (Source IP): 클라이언트의 소스 IP를 기준으로 분배.  ex) 특정 네트워크 IP 범위의 요청은 거부.
  • HTTP 요청 메서드 (HTTP Method): 특정 HTTP 메서드 기반 라우팅.  ex) GET/POST 요청 이외의 트래픽은 Method Not Allowed 405 Error 발생.

 

 

 


우리는 http://LB/serviceA/**의 트래픽을 Auto Scaling Group A로 보낼 것이기 때문에 위와 같이 조건을 지정해주었다.

 

 

 

 

 


규칙 작업 설정

 

우리는 해당 규칙의 조건에 따라서 작업을 정의해야 한다. 작업의 유형으로는 크게 3가지로 구분할 수 있다.

  • Forward : 트래픽을 지정된 대상 그룹으로 전달.
  • Redirect : 클라이언트를 특정 URL로 리디렉션.
  • Fixed-response : 지정된 HTTP 상태 코드와 메시지로 응답.

 

http://LB/serviceA/**의 트래픽 → Auto Scaling Group A 대상 그룹으로 전달하도록 설정해주었다.

 

 


규칙 우선순위 설정

 

 

하나의 리스너에는 여러개의 규칙이 존재할 수 있다. 이 때 동일한 규칙 조건의 라우팅에 대해서 어떤 규칙으로 우선적으로 라우팅할 것인지에 대한 우선순위를 설정한다. 우선순위 숫자가 낮을수록 우선순위가 높다.

 

 

 

 


리스너 규칙 확인

 

위의 과정을 반복하여 Service A 대상 그룹에 대한 규칙과 함께 Service B 대상 그룹에 대한 규칙을 설정해 주었다.

 

규칙 1 : http://LB/serviceA/**의 트래픽→Auto Scaling Group A 대상 그룹으로 전달

규칙 2 : http://LB/serviceB/**의 트래픽→Auto Scaling Group B 대상 그룹으로 전달

else : 404 NOT FOUND 응답 반환

 

 

 

리소스 맵을 확인해보면 우리가 설정해 준 규칙에 따라서 리스너, 규칙, 대상 그룹 간의 매핑 관계를 확인할 수 있다. 해당 그림을 통해 우리가 의도한 매핑 상태와 동일한 것을 확인할 수 있다.

 

 

 

 

 


Path Rewrite

 

우리는 트래픽을 서로 다른 유형의 웹 서버에서 처리하기 위해서 경로에 /serviceA, /serviceB라는 접두사를 기준으로 라우팅을 수행했었다.

 

그렇지만 현재 시스템에서는 Elastic Load Balancer(ELB)가 /serviceA/* 경로로 요청을 전달하지만, 백엔드 서버의 라우팅 테이블에는 해당 경로가 없어 404 Not Found 에러가 발생할 것이다.

  • /serviceA/hello 의 요청은 실제로 백엔드 서버에서는 /hello 라우팅 경로로 매핑되어야 한다.

 

 

 

이것은 로드밸런서가 /serviceA 접두사를 제거하지 않고 그대로 전달하기 때문이다. 따라서 실제 백엔드 서버에 라우팅 할 때에는 해당 접두사를 제거해주어야 한다.

ELB에서는 Path Rewrite의 기능을 제공하지 않기 때문에 ALB 뒷단에서 Path Rewrite를 하도록 구성하는 방법을 사용할 수 있다.

직접 EC2의 프록시 서버에서 요청을 Rewrite하도록 구성하거나 AWS API Gateway 등을 활용하는 방법 등이 있다.

 

 


시작 템플릿 변경 : Path Rewrite 설정 

 

우리는 EC2 서버에서 Apache를 사용하여 웹서버를 운영했었다. 따라서 Apache의 프록시 설정 중 Path Rewrite 기능을 활용해 /serviceA로 들어오는 요청의 접두사를 제거하여 정상적으로 요청을 처리하도록 변경해주었다.

 

Apache 서버 이외에 NginX 등 다른 웹 프록시 서버 역시 해당 Rewrite 기능의 지원을 많이 한다.

 

AWS의 다른 서비스를 활용해 문제해결이 가능하지만 해당 방식은 가장 단순하고 기본적으로 사용해 볼 수 있는 해결책 중 하나이다.

 

 

 

 

 

<변경된 시작 템플릿> : 시작 템플릿 변경 후, Autoscaling Group의 템플릿 또한 수정하고, 수정된 웹 서버로 업데이트해주어야 한다.

#!/bin/bash
# Root 권한 획득
sudo -s

# Apache 설치
dnf install httpd -y

# Apache 서비스 시작 및 부팅 시 자동 실행 설정
service httpd start
chkconfig httpd on

# 메타데이터에서 인스턴스 ID 가져오기
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
INSTANCE_ID=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/instance-id)

# 인스턴스 ID를 기본 index.html에 기록
echo "SERVICE A : $INSTANCE_ID" > /var/www/html/index.html

# httpd.conf 파일에 디렉토리 권한 설정 및 Rewrite 설정 추가
cat <<EOT >> /etc/httpd/conf/httpd.conf

# 루트 디렉토리 접근 허용
<Directory />
    AllowOverride All
    Require all granted
</Directory>

# /var/www/html 디렉토리 접근 허용
<Directory "/var/www/html">
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
</Directory>

# Rewrite 설정
<IfModule mod_rewrite.c>
    RewriteEngine On

    # 요청이 /serviceA/로 시작하면 /serviceA/를 제거하고 내부 처리
    RewriteRule ^/serviceA/?(.*)$ /$1 [L]

</IfModule>
EOT

# Apache 모듈 활성화 확인
if ! apachectl -M | grep -q rewrite_module; then
    echo "mod_rewrite가 활성화되지 않았습니다. mod_rewrite를 활성화합니다."
    sed -i '/#LoadModule rewrite_module/s/^#//' /etc/httpd/conf/httpd.conf
fi

# Apache 서비스 재시작
service httpd restart

 

 

 

 


결과 확인

 

이제 마찬가지로 LB의 도메인 주소로 접속했을 때, 트래픽의 경로 접두사에 따라서 규칙이 적용되어 Service A Autoscaling Group과 Service B Autoscaling Group으로 트래픽이 분산되어 처리되는 모습을 볼 수 있다.

 

 

 

 

 

 

 

 

 


References

 

https://docs.aws.amazon.com/

 

https://docs.aws.amazon.com/

 

docs.aws.amazon.com

 

반응형

BELATED ARTICLES

more