로드 밸런싱과 고가용성 (3) - 고가용성 아키텍처 - soo:bak
작성일 :
어떻게 장애에도 서비스를 유지하는가
Part 1에서 로드 밸런싱의 원리를, Part 2에서 DNS 기반 분산을 살펴보았습니다.
서버를 여러 대로 늘렸지만, 여전히 중요한 질문이 남아 있습니다.
로드 밸런서 자체가 죽으면 어떻게 될까요?
가용성의 정의
가용성(Availability)은 시스템이 정상 동작하는 시간의 비율입니다.
1
가용성 = 정상 운영 시간 / 전체 시간 × 100%
9의 개수
가용성은 흔히 “9의 개수”로 표현됩니다.
1
2
3
4
5
6
7
8
9
┌─────────────┬───────────────┬──────────────────────────┐
│ 가용성 │ 연간 다운타임 │ 의미 │
├─────────────┼───────────────┼──────────────────────────┤
│ 99% │ 3.65일 │ Two Nines │
│ 99.9% │ 8.76시간 │ Three Nines │
│ 99.99% │ 52.56분 │ Four Nines │
│ 99.999% │ 5.26분 │ Five Nines │
│ 99.9999% │ 31.5초 │ Six Nines │
└─────────────┴───────────────┴──────────────────────────┘
99%와 99.99%는 수치상 작은 차이로 보이지만, 실제로는 연간 다운타임이 3.65일에서 52분으로 100배나 차이가 납니다.
SLA (Service Level Agreement)
서비스 제공자와 고객 간의 가용성 약속입니다.
예: AWS EC2 SLA
- 월간 가용성 99.99% 보장
- 미달 시 서비스 크레딧 제공
SLA를 맞추려면 단일 장애점(SPOF: Single Point of Failure)을 제거해야 합니다.
이중화 패턴
Active-Passive (Hot Standby)
하나의 시스템이 활성 상태로 트래픽을 처리하고, 다른 하나는 대기하며 상태를 동기화받습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
정상 상태:
┌─────────────┐ ┌─────────────┐
│ Active │ ←── 트래픽 ── │ Passive │
│ (운영중) │ │ (대기중) │
└─────────────┘ └─────────────┘
↑ │
└────── 상태 동기화 ───────────────┘
장애 발생 시:
┌─────────────┐ ┌─────────────┐
│ Failed │ │ Active │ ←── 트래픽
│ (장애) │ │ (승격됨) │
└─────────────┘ └─────────────┘
특징: 구조가 단순하지만 리소스 절반이 유휴 상태이고, 페일오버 시 짧은 중단이 발생할 수 있습니다.
Active-Active
모든 시스템이 활성 상태로 트래픽을 분산 처리합니다.
1
2
3
4
5
6
7
8
9
10
11
정상 상태:
┌─────────────┐ ┌─────────────┐
│ Active │ ←── 트래픽 ──► │ Active │
│ (50%) │ │ (50%) │
└─────────────┘ └─────────────┘
장애 발생 시:
┌─────────────┐ ┌─────────────┐
│ Failed │ │ Active │ ←── 트래픽
│ (장애) │ │ (100%) │
└─────────────┘ └─────────────┘
특징: 리소스를 효율적으로 사용하고 장애 처리가 자연스럽지만, 상태 동기화가 더 복잡합니다.
두 패턴의 선택 기준
어떤 패턴을 선택해야 할지는 서비스 특성에 따라 달라집니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
┌────────────────────┬──────────────────────┬──────────────────────┐
│ 기준 │ Active-Passive │ Active-Active │
├────────────────────┼──────────────────────┼──────────────────────┤
│ 리소스 효율 │ 낮음 (50% 유휴) │ 높음 (전부 활용) │
├────────────────────┼──────────────────────┼──────────────────────┤
│ 구현 복잡도 │ 단순 │ 복잡 │
├────────────────────┼──────────────────────┼──────────────────────┤
│ 페일오버 시간 │ 수초~수십초 │ 거의 즉각적 │
├────────────────────┼──────────────────────┼──────────────────────┤
│ 상태 동기화 │ 단방향 (A→P) │ 양방향 (A↔A) │
├────────────────────┼──────────────────────┼──────────────────────┤
│ 비용 │ 상대적 저렴 │ 상대적 고비용 │
└────────────────────┴──────────────────────┴──────────────────────┘
Active-Passive 권장 상황:
- 상태 동기화가 복잡한 시스템 (예: 데이터베이스)
- 비용 절감이 중요하고 짧은 다운타임을 허용할 수 있을 때
- 트래픽이 단일 노드로 충분한 경우
Active-Active 권장 상황:
- 다운타임을 최소화해야 하는 미션 크리티컬 서비스
- 트래픽이 많아 분산 처리가 필요한 경우
- 리소스 활용 효율이 중요할 때
N+1, N+N
용량 계획 관점에서는 N+1과 N+N 방식이 있습니다.
N+1은 N대가 필요한 용량에 1대 여분을 두어 1대 장애 시에도 정상 운영합니다. N+N (2N)은 필요 용량의 2배를 구성하여 절반이 죽어도 정상 운영하지만, 비용이 더 높습니다.
VRRP와 HSRP
앞서 설명한 이중화 패턴을 구현하기 위해 가상 IP 주소를 사용한 장애 복구 프로토콜이 필요합니다.
VRRP (Virtual Router Redundancy Protocol)
RFC 5798로 정의된 표준 프로토콜로, 여러 라우터가 하나의 가상 IP를 공유합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
┌───────────────┐
│ 가상 IP │
│ 192.168.1.1 │
└───────┬───────┘
│
┌──────┴──────┐
│ │
▼ ▼
┌─────────────┐ ┌─────────────┐
│ 라우터 A │ │ 라우터 B │
│ .2 Master │ │ .3 Backup │
│ Priority:100│ │ Priority:90 │
└─────────────┘ └─────────────┘
동작 방식은 다음과 같습니다.
- Master 선출: Priority가 높은 라우터가 Master로 선출
- 가상 IP 소유: Master가 가상 IP에 대한 ARP 요청에 응답
- Advertisement: Master가 주기적으로 상태를 광고
- 장애 감지: Backup이 Advertisement를 받지 못하면 Master로 승격
1
2
3
4
5
6
7
정상 동작:
클라이언트 → 192.168.1.1 (가상 IP) → 라우터 A (Master)
라우터 A 장애:
클라이언트 → 192.168.1.1 (가상 IP) → 라우터 B (새 Master)
클라이언트는 변경을 인식하지 못함!
HSRP (Hot Standby Router Protocol)
시스코 전용 프로토콜로, VRRP와 유사하게 동작합니다. VRRP는 표준이고 HSRP는 시스코 전용이라는 점, 타이머와 상태 이름(VRRP는 Master/Backup, HSRP는 Active/Standby) 등에서 세부적인 차이가 있습니다.
LB 자체의 고가용성
지금까지 배운 내용을 로드 밸런서에 적용해 봅시다. 로드 밸런서도 SPOF가 될 수 있기 때문입니다.
문제 상황
1
2
3
4
5
6
7
8
9
10
11
사용자들
│
▼
┌─────────────┐
│ 로드 밸런서 │ ← SPOF!
└──────┬──────┘
│
┌───┼───┐
│ │ │
▼ ▼ ▼
서버A 서버B 서버C (이중화 완료)
서버는 이중화했지만, LB가 죽으면 전체 서비스가 중단됩니다. 따라서 LB 자체도 이중화해야 합니다.
LB 이중화
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
사용자들
│
▼
┌─────────────────────────────────────┐
│ 가상 IP │
│ (VRRP/Keepalived) │
└────────────────┬────────────────────┘
│
┌────────┴────────┐
│ │
▼ ▼
┌─────────────┐ ┌─────────────┐
│ LB Master │ │ LB Backup │
│ │────►│ (대기중) │
│ │상태 │ │
│ │동기화│ │
└──────┬──────┘ └──────┬──────┘
│ │
└─────────┬─────────┘
│
┌──────┼──────┐
│ │ │
▼ ▼ ▼
서버A 서버B 서버C
Floating IP
클라우드 환경에서는 Floating IP라는 가상 IP를 사용합니다. 클라우드 API를 통해 빠르게 IP를 다른 인스턴스로 재할당할 수 있습니다.
1
2
정상: Floating IP → LB 인스턴스 A
장애: Floating IP → LB 인스턴스 B (API로 재할당)
상태 동기화
Active-Active나 Active-Passive 모두 상태 동기화가 필요할 수 있습니다.
세션 복제
로드 밸런서가 연결 상태를 추적할 때:
1
2
3
4
5
6
7
8
9
10
LB Master LB Backup
┌───────────────┐ ┌───────────────┐
│ 세션 테이블 │ ───► │ 세션 테이블 │
│ - 연결 1 │ │ - 연결 1 │
│ - 연결 2 │ 동기화│ - 연결 2 │
│ - 연결 3 │ │ - 연결 3 │
└───────────────┘ └───────────────┘
Master 장애 시:
Backup이 동기화된 세션 정보로 즉시 처리 가능
상태 동기화의 비용
상태 동기화에는 대역폭 사용, 지연 시간, 복잡성 증가라는 비용이 따릅니다. 동기화가 실시간이 아니면 장애 시 일부 세션이 유실될 수 있습니다.
더 좋은 해결책: Stateless 설계
상태 동기화의 복잡성을 피하는 가장 좋은 방법은 애초에 상태를 외부 저장소로 분리하는 것입니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
┌─────────────────────────────────────────────────────────────┐
│ Stateless 아키텍처 │
│ │
│ LB A (상태 없음) LB B (상태 없음) │
│ │ │ │
│ └─────────┬───────────┘ │
│ │ │
│ ┌─────────┴─────────┐ │
│ │ │ │
│ 서버 A (상태 없음) 서버 B (상태 없음) │
│ │ │ │
│ └─────────┬─────────┘ │
│ │ │
│ ┌─────────┴─────────┐ │
│ │ │ │
│ ┌─────┴─────┐ ┌─────┴─────┐ │
│ │ Redis │ │ 데이터베이스│ │
│ │ (세션) │ │ (데이터) │ │
│ └───────────┘ └───────────┘ │
└─────────────────────────────────────────────────────────────┘
이 방식의 장점은 LB와 서버 모두 쉽게 교체할 수 있고, 동기화 복잡성이 제거되며, 수평 확장이 용이하다는 점입니다.
반면 외부 저장소(Redis, DB)에 의존하게 되고, 네트워크 홉이 추가되며, 외부 저장소 자체가 새로운 SPOF가 될 수 있어서 이것 역시 이중화가 필요합니다.
실제 아키텍처 사례
지금까지 배운 개념들이 실제로 어떻게 조합되는지 살펴봅시다.
2-Tier 아키텍처
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
인터넷
│
▼
┌─────────────┐
│ L4/L7 LB │ ← HA 구성
└──────┬──────┘
│
┌───┴───┐
│ │
▼ ▼
웹/앱 웹/앱 ← 오토스케일링
서버 서버
│ │
└───┬───┘
│
▼
┌─────────────┐
│ 데이터베이스 │ ← Primary-Replica
└─────────────┘
3-Tier 아키텍처
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
인터넷
│
▼
┌─────────────┐
│ L4 LB │ ← 고성능, 단순 분산
└──────┬──────┘
│
┌───┴───┐
│ │
▼ ▼
┌─────┐ ┌─────┐
│L7 LB│ │L7 LB│ ← SSL 종료, 내용 기반 라우팅
└──┬──┘ └──┬──┘
│ │
└───┬───┘
│
┌───┼───┐
│ │ │
▼ ▼ ▼
앱 앱 앱 ← 비즈니스 로직
서버 서버 서버
│ │ │
└───┼───┘
│
▼
┌─────────────┐
│ 데이터 계층 │
│(DB, Cache) │
└─────────────┘
글로벌 분산 아키텍처
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
┌─────────────┐
│ GSLB │
│(DNS 기반) │
└──────┬──────┘
│
┌───────────────────┼───────────────────┐
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ 아시아 DC │ │ 유럽 DC │ │ 북미 DC │
│ │ │ │ │ │
│ ┌──────────┐ │ │ ┌──────────┐ │ │ ┌──────────┐ │
│ │ LB │ │ │ │ LB │ │ │ │ LB │ │
│ └────┬─────┘ │ │ └────┬─────┘ │ │ └────┬─────┘ │
│ │ │ │ │ │ │ │ │
│ 서버들 │ │ 서버들 │ │ 서버들 │
│ │ │ │ │ │
│ ┌──────────┐ │ │ ┌──────────┐ │ │ ┌──────────┐ │
│ │ DB │◄├────┼─►│ DB │◄├────┼─►│ DB │ │
│ │ (복제) │ │ │ │ (복제) │ │ │ │ (복제) │ │
│ └──────────┘ │ │ └──────────┘ │ │ └──────────┘ │
└──────────────┘ └──────────────┘ └──────────────┘
정리: 단일 장애점을 제거하라
고가용성을 달성하기 위한 핵심 원칙을 정리하면 다음과 같습니다.
- SPOF 식별: 어디서 장애가 전체 서비스를 중단시키는지 파악
- 이중화: 모든 SPOF를 이중화 (Active-Passive 또는 Active-Active)
- 자동 페일오버: 수동 개입 없이 자동 전환되도록 구성
- Stateless 설계: 가능하면 상태를 외부 저장소로 분리
- 테스트: 장애 복구 과정을 정기적으로 테스트 (Chaos Engineering)
1
2
"시스템은 반드시 장애가 발생한다.
문제는 언제, 어떻게 대응할 것인가."
장애를 예방하는 것만큼 장애에 빠르게 대응하는 체계를 갖추는 것이 중요합니다.
관련 글