탄력성/고가용성 아키텍처 (1). Auto Scaling
클라우드에서 서버에 가해지는 트래픽이 늘고 줆에 따라
이것을 유동적으로 처리할 수 있는 설계를 탄력성/고가용성 아키텍처라고 한다.
뭐, 자원이 무한대라면 Capacity를 넉넉히 잡아두겠지만
우리의 자원은 유한하니까.
불필요한 리소스 낭비를 최대한 줄이자는 거지.
클라우드는 가상화 특징으로 인해 리소스를 늘리고 줄이는 게 쉽다.
이런 특징에 착안하여 트래픽에 따라 유동적으로 VM을 늘리거나, 로드밸런서를 세팅할 수 있다.
전자를 Auto Scaling, 후자를 Load Balancing이라는 이름으로 배워 보자.
- Auto Scaling 아키텍처
Auto Scaling의기본 원리는 트래픽에 따라 VM을 포함한 리소스를 동적으로 조절하는 것이다.
이를 위해 맨 처음 오토 스케일링 그룹(ASG)을 설정할 때는
Minimum size(최소 VM 수),
Desired Capacity(일반적인 상황의 VM 수),
Maximun size(트래픽이 늘었을 때의 최대 VM 수)를 설정해야 한다.
이에 따라 장애가 발생하거나, 트래픽이 변함에 따라
새 VM을 만들기도, 없애기도 하면서 부하를 감당한다.
여기서 주의할 점, 오토스케일링은 여러 가용 영역을 사용하도록 만들어야 한다.
이렇게 설정하면 하나의 가용 영역에서 장애가 발생해도
다른 가용 영역에서 새 인스턴스를 만들어 대처할 수 있다.
즉, 가용성이나 DR 측면에서 더 유리한 것.
< Health Check >
인스턴스에 장애가 생겼을 때 유동적으로 다른 가용 영역에 생성한단 건,
실시간으로 각 인스턴스의 장애 여부를 모니터링한다는 것이다.
이 역할을 로드밸런서가 하는데,
트래픽을 인스턴스로 분배해서 보내는 과정에서 응답을 체크하여
정상 작동 여부를 판별한다.
이를 Health Check라고 한다.
- Auto Scaling 생성 단계
AWS에서 오토스케일링을 생성할 때,
다음의 요소들을 정의해야 한다.
시작 템플릿 | AWS에서 ASG를 만들 때, AMI, 인스턴스 유형, 키 페어, 네트워크, SG 등을 사전 정의 |
ASG | Min, Desired, Max 설정 |
조정 정책 | Dynamic Scaling, Schduled Scaling, Predictive Scaling |
시작 템플릿은 딱히 볼 거 없고,
ASG는 위에서 봤으니 조정 정책을 살펴보자.
< Auto Scaling 조정 정책 >
Dynamic Scaling : 일반적인 방식. 조건에 따라 스케일링.
Schduled Scaling : 예측가능한 스케줄이 있을때, 시간과 날짜에 따른 스케일링
Predictive Scaling : AI가 패턴을 학습하여 수동 설정 없이 스케일링
탄력성/고가용성 아키텍처 (2). Load Balancing
로드밸런싱이야 트래픽이 있으면 당연히 하는 거고,
지금 배울 건 AWS의 Elastic Load Balancer(ELB)이다.
ELB는 한 리전마다 위치하는데,
가용 영역에 대한 Health Check를 수행하여
장애가 발생한 경우에는 그쪽으로 트래픽을 보내지 않고
다른 가용 영역의 인스턴스로 트래픽을 라우팅한다.
- ELB 아키텍처
ELB를 활용한 EC2 아키텍처를 보자.
ELB는 용도에 따라 외부(EX) ELB와 내부(IN) ELB로 나뉜다.
외부 ELB는 Web 계층 인스턴스들이 퍼블릭 IP를 가지지 않아도
IGW로부터 트래픽을 받을 수 있게 한다.
이게 뭔 소리냐 하면,
원래 IGW로부터 정보를 받는 인스턴스는
Public IP를 설정해야 했지?
하지만 위처럼 중간에 로드밸런서가 있다면,
로드밸런서가 Public IP를 가지고 DNS와 연동된다.
이 경우에는 웹 서버 인스턴스에 퍼블릭 IP가 없어도 된다.
보안성이 강화되는거지.
내부 ELB는 일반적으로 생각하는 로드밸런싱 기능을 한다.
내부적으로도 트래픽 제어는 해 줘야 하니까.
- ELB 구성
ELB의 작동방식을 정의하는 규정을 리스너라고 한다.
들어온 트래픽을 프로토콜/포트 기반으로 판단하고,
리스너에 정의된 바에 따라 대상 그룹(Target group)으로 보낸다.
이때 대상 그룹의 각각에 대한 Health Check를 수행한다.
- ELB의 기능
ELB는 기본적인 로드밸런싱 기능 외에도 다양한 기능을 제공한다.
상태 확인 (Health Check) |
앞에서 살펴본 것. 인스턴스의 정상 작동 여부를 판별 후 라우팅 |
TLS 오프로딩 (TLS termination) |
TLS/SSL는 보안 연결 암호. ELB가 HTTPS 복호화 수행 후, 일반 HTTP 신호를 인스턴스에 전달 인스턴스에 암호화된 트래픽이 그대로 전송되어 발생하는 부하 방지 |
고정 세션 (Sticky session) |
쿠키 정보 기반으로 사용자가 이전에 접속했던 세션으로 재연결해주는 기능 |
등록취소 지연 (Deregistration delay) (Connection draining) |
인스턴스 등록 취소 시, 인스턴스에 진행중인 요청을 처리할 시간을 주는 기능 |
- ELB 유형
ELB는 ALB(Application), NLB(Network), GLB(Gateway)로 나뉜다.
ALB는 L7 계층 로드밸런서다.
그러니까 HTTPS, HTTP 트래픽을 처리한다.
컨텐츠 기반, 가중치 기반 등 다양한 고급 로드밸런싱이 가능한 게 특징이다.
컨텐츠 기반 라우팅 : 리스너에서 컨텐츠에 의해 라우팅이 결정되도록 조건을 명시해 놓음
- 컨텐츠의 URL, 호스트 이름, HTTP요정 메소드, HTTP 헤더, IP 등을 조건으로 달 수 있다.
가중치 기반 라우팅 : 대상 그룹의 가중치에 따라 라우팅하는 트래픽을 차등적으로 배분
NLB는 L4 기반 로드밸런서로,
TCP, UDP기반 요청의 부하를 분산한다.
4계층에서 동작하므로 IP와 포트 기반의 로드밸런싱을 진행한다.
7계층보다 오버헤드가 낮은 데이터를 처리하는 탓에
지연 속도가 매우 짧고 대규모 트래픽 처리에 적합하다.
위와 같이 ALB를 TG로 취급하여 동작하기도 한다.
GLB는 L3 기반으로 동작한다.
네트워크 트래픽을 보안 및 모니터링을 담당하는 부분으로 전달하는데,
로드밸런서이니만큼 보안/모니터링 어플라이언스를 자동 확장하여 부하를 분산한다.
정리하자면 다음과 같다.
특징 | ALB | NLB | GWLB |
OSI 계층 | 7계층 | 4계층 | 3계층 |
트래픽 유형 | HTTP, HTTPS | TCP, UDP | IP 패킷 |
라우팅 기준 | HTTP 헤더 | IP주소, 포트 | - |
용도 | 웹 애플리케이션 트래픽 분산 | 저지연 대용량 트래픽 분산 | 보안 및 모니터링 어플라이언스로 부하 분산 |
- Route 53
Route53은 리전과 리전 사이에서 로드밸런싱을 해 주는 서비스다.
일종의 DNS라고 할 수 있는데,
2개 이상의 리전을 이용해 서비스할 때
글로벌 트래픽을 최적의 리전으로 라우팅해주는 역할을 한다.
로드밸런서와 똑같이 Health Check을 수행하고
필요 시 장애 조치를 수행하기도 한다.
Route53의 라우팅 정책은 다음과 같다.
단순 라우팅(Simple Routing)
하나의 리소스로 라우팅.
가중치 기반 라우팅(Weighted Routing)
가중치 기반으로 트래픽을 여러 리소스에 분할.
지연 시간 기반 라우팅(Latency-Based Routing)
낮은 지연 시간 리전에 우선 라우팅
지리적 라우팅(Geolocation Routing)
사용자의 위치(국가, 대륙 등)에 따라 라우팅.
지리적 근접 라우팅(Geo-Proximity Routing)
사용자와 리소스 간의 거리 기준 라우팅.
장애 조치 라우팅(Failover Routing)
기본 리소스가 비정상이면 대체 리소스로 트래픽 라우팅.
DR 체계
AWS 클라우드 기반의 DR 전략으로는
Pilot Light, Warm stanby, Multi-site active/active가 있다.
점차적으로 복구 속도는 빨라지고 비용은 높아진다.
- Pilot Light
클라우드 상에 온프레미스와 동일한 환경을 구성해 두지만,
비용 절약을 위해 평소에는 중지시켜 놓는 방식이다.
그러다가 장애가 발생하면 인스턴스들을 실행시켜 서비스를 이어 간다.
인스턴스를 새로 실행시켜야 하는 만큼
시간이 상대적으로 오래 걸린다.
- Warm stanby
Pilot Light와 유사하나, 최소한의 인스턴스를 계속 실행시켜 둔다.
장애 발생 시 실행중인 인스턴스가 오토 스케일링을 통해
원래의 사이즈만큼 확장된다.
- Multi-site active/active
처음부터 온프레미스 시스템과 완전히 동일한 클라우드를 구성하여,
50% : 50% 비중으로 평소 트래픽을 처리한다.
그러다가 장애가 발생하면 클라우드가 100% 트래픽을 처리하도록 만든다.
가장 안정적이고 빠르지만 비용이 많이 발생한다.
결합 해제(Loosely Coupled / Decoupled) 아키텍처
서비스 도중 급격한 트래픽 증가로 특정 리소스에 성능 저하나 장애가 발생할 수 있다.
그런데 이게 다른 리소스에도 영향을 주면 안되겠지?
그래서 클라우드 시스템 아키텍처에서는
리소스들이 서로 느슨하게(Loosely) 연결되어 있는 것이 좋다.
위와 같은 결합을 Tightly Coupled라고 한다.
이런 방식은 하나의 에러가 다른 Tier 전반에 영향을 주겠지.
하나 멈추면 다 멈추는거다.
따라서 우리는 이런 식으로 아키텍처를 구성해야 한다....만,
이건 또 인스턴스가 늘어날수록 복잡성이 지극히 높아지는 문제가 있다.
이런 식으로 말이지.
그래서 이걸 정리해 주면서도 느슨한 결합을 보장하기 위해,
우리는 로드밸런서를 쓴다.
- SQS
그런데 만약, 엄청난 규모의 트래픽이 순간적으로 발생 (Traffic Spike) 한다면?
이때는 로드 밸런서가 트래픽에 대한 버퍼 역할도 수행해 줘야 한다.
이걸 누가 해 줄까? 큐(Queue)가 해 준다. 또 당신입니까 정처기
큐를 로드밸런서 대신 배치시킨 아키텍처를 AWS에서 SQS라고 한다.
이렇게 큐를 사용함으로써 두가지 효과를 얻을 수 있는데,
첫째가 아까 말한 트래픽 스파이크를 처리하는 것이고,
둘째는 비동기식 처리를 구현하는 것이다.
< 비동기식 처리 >
요청과 응답이 즉각적으로 연결되지 않는 작업 방식이다.
요청을 즉각 처리하지 않아도 되므로 병목 현상이 발생하지 않으며,
생산자는 메시지를 큐에 저장한 후 즉시 다음 작업을 수행할 수 있어 생산성이 향상된다.
주문 시스템 등에서 종종 쓰인다.
SQS는 대기열 종류에 따라 Standard 방식과 FIFO 방식으로 나뉜다.
Standard는 처리속도가 빠르지만 중복 처리의 위험이 있는 반면,
FIFO는 중복 처리의 위험이 없지만 처리 속도가 느리다.
SQS 구조에서 Web 서버를 Producer, App 서버를 Consumer라고들 한다.
이때 우리는 가시성 제한시간 / 긴 폴링을 고려해야 하는데,
가시성 제한시간은 서로 다른 Consumer가 동일한 데이터를 동시에 처리할 일이 없도록,
한 Consumer가 폴링한 데이터는, 처리 끝나기 전까지 보이지 않게 해 놓는 것이다.
왜 이런게 있냐면,
큐에 들어 있는 데이터는 폴링해 간다고 해서 삭제되는 것이 아니기 때문이다.
긴 폴링은 비용 최적화를 위한 것 중 하나인데,
큐에서 데이터를 폴링한 횟수도 비용에 가산되기 때문에 사용한다.
폴링의 기본 옵션이 짧은 폴링으로 되어 있기 때문에
큐가 비어 있을 때도 폴링해 오는 문제가 발생한다.
이로 인한 비용 낭비를 줄이기 위해 폴링 긴격을 길게 잡는 것이
긴 폴링(long polling)이다.
- SNS
이름 비슷한 김에 잡고 가자.
SQS는 송신 - 수신자간의 1:1 풀링 기반 통신 서비스라면,
SNS는 게시 - 구독자간의 1:多 푸시 기반 통신 서비스이다.
SQS의 구현 목적은 느슨한 결합을 구현하기 위해서이고,
SNS의 구현 목적은 Fan Out(병렬 처리)를 구현하기 위해서이다.
따라서 아키텍처를 만들 때, SNS의 하단부에 Queue 여러 개를 동시에 두어
병렬적 SQS 구조를 만든다.
메시지가 보존되지 않는 SNS의 특성상,
바로 인스턴스로 Push하지 않고 Queue를 두는 것이다.
Serverless
또 나왔다. 서버리스.
그만큼 중요하고 트렌디한 주제라고 한다.
인프라 구축 / 확장을 전혀 신경쓰지 않고
개발에만 집중하고자 하는 고객을 위한 서비스이다.
리소스가 늘 구동되고 있는 것이 아니라 요청이 있을 때에만 구동되기 때문에
비용적으로도 유리하며,
오토스케일링이 지원되어 급격한 트래픽 변화에도
민첩성과 유연성을 확보할 수 있다.
따라서 유지관리, 용량 관리, 배포, 배치, 로깅 등을 신경 쓸 필요가 전혀 없다.
이런 장점으로 인해 배민, 당근마켓 등 다양한 업체가 서버리스 기반의 서비스를 구축하고 있다.
AWS에서 제공하는 서버리스 서비스들은 아주 많은데,
그중에서도 Lambda, API Gateway, Step Functions 이 세 가지를 배워 보자.
- Lambda
Lambda는 서버를 직접 구현(프로비저닝)하지 않고도 코드를 실행시켜준다.
즉, 서버 구축 전반에 대한 조작 없이 코드를 통한 이벤트를 발생시킬 수 있는 것이다.
기본적으로 Lambda API를 호출하여 코드를 실행하며,
선행 이벤트에 대한 응답으로 실행되기도 한다.
설명이 참 단순하지만, 사실 게임 체인저라고 할 수 있을 정도로 강력한 기능이다.
- AWS Step Functions
Lambda는 어디까지나 하나의 과정이다.
이 과정들을 적절하게 배치하여 워크플로우를 생성해야 하는데,
이를 지원하는 서비스가 Step Functions이다.
워크플로우의 각 단계를 상태(State)라는 이름의 객체로 구현하여,
시각적 편집기를 통해 워크플로우를 구축할 수 있게 해 준다.
- AWS API Gateway
서버리스 아키텍처는 마이크로 서비스 기반이다.
마이크로 서비스는 객체가 세분화되어 있는 만큼,
액세스가 다채롭고 그에 따라 API가 아주 많이 필요하다.
이거 번거롭지? 또 누군가 관리해 주겠지?
그게 API Gateway의 역할이다.
이녀석은 API로 들어가는 관문 역할을 하면서 전반적인 요소들을 관리할 수 있다.
AWS의 API Gateway활용 아키텍처 예시.
API Gateway가 다양한 역할을 하는 Lambda에 각각의 API 요청을 보낸다.
물론 Lambda뿐 아니라 EC2, S3등의 백엔드 인스턴스에도 API 요청을 보낼 수 있다.
단일 엔드포인트로 여러 인스턴스와 통신할 수 있다는 점에서 상당히 편리한데,
이를 온전히 누리기 위해서는 CORS(Cross Origin Resource Sharing) 설정이 필요하다.
이는 웹 브라우저의 동일 출처 정책에 기인하는데,
동일 출처 정책이란 민감한 정보(주로 javascript 기반)에 한해
웹 브라우저가 자기 자신과 프로토콜, 포트, 호스트명이 같지 않은 대상과는
통신하지 않는 것을 의미한다.
이는 보안적인 문제로 불가결한 일이지만,
서비스 제공자 측면에서는 마이크로서비스를 구현할 때 걸림돌이 되기도 한다.
이떄 API Gateway에서 CORS설정을 해 줌으로써 이 규제를 완화할 수 있다.