웹/애플리케이션 서버 고가용성 구성
📘 SyncMon
웹/애플리케이션 서버 고가용성 구성
1. 배경
SyncMon은 실시간 모니터링 서비스이기 때문에, 웹 또는 애플리케이션 서버가 중단되면 단순한 서비스 접속 실패를 넘어 모니터링 공백으로 이어질 수 있습니다. 운영 관점에서 이는 단순 장애가 아니라 이상 징후를 제때 인지하지 못하는 문제로 연결될 수 있으므로, 단일 서버 장애가 전체 서비스 중단으로 이어지지 않도록 고가용성 구성이 필요했습니다.
이번 구성의 목적은 단순히 서버를 두 대 두는 데 있지 않습니다. 핵심은 클라이언트가 접속하는 진입점과 애플리케이션 실행 환경을 분리된 두 노드에 동일하게 준비해두고, 장애 발생 시 서비스 역할을 신속하게 다른 노드로 넘길 수 있도록 하는 것입니다.
2. 이번 구성의 범위
이번에 다루는 고가용성 구성은 웹 서버와 애플리케이션 서버 영역을 대상으로 합니다.
즉, SyncMon의 프런트엔드 진입점과 애플리케이션 실행 환경을 이중화하는 것이 목적이며, DB까지 포함한 전체 시스템 HA를 구성하는 문서는 아닙니다.
이 범위를 먼저 분리한 이유는 명확합니다.
실무에서 HA를 이야기할 때 가장 흔한 오해 중 하나는, 웹 서버 이중화만 해놓고 전체 서비스가 고가용성을 확보했다고 판단하는 것입니다. 하지만 실제로는 웹/애플리케이션 서버와 DB는 장애 특성도 다르고, 대응 방식도 다릅니다. 이번 구성은 클라이언트 요청 수용과 애플리케이션 실행 지속성 확보에 초점을 맞춘 것이고, DB 고가용성은 별도 설계 항목으로 분리해 다뤄야 합니다.
정리하면 이번 구성의 범위는 다음과 같습니다.
- 클라이언트 접속 진입점의 지속성 확보
- SyncMon 웹/애플리케이션 서버의 Active-Standby 구성
- 장애 발생 시 대기 노드로의 서비스 역할 전환
- 역할 전환 시 애플리케이션 및 Agent 실행 연계
반대로 이번 문서의 범위에 포함되지 않는 것은 다음과 같습니다.
- DB 이중화 또는 DB failover
- 데이터 복제 정책
- 다중 리전 또는 다중 AZ 수준의 재해복구 설계
- 메시지 브로커, 파일 스토리지 등 외부 의존성의 고가용성
3. 대안 검토
웹/애플리케이션 서버 고가용성을 구성하는 방식은 여러 가지가 있습니다. SyncMon 환경에서 검토 가능한 대표적인 선택지는 다음 세 가지였습니다.
3.1 Nginx + Keepalived
Nginx는 클라이언트 요청을 처리하는 웹 계층의 진입점 역할을 하고, Keepalived는 VRRP 기반으로 VIP(Virtual IP) 를 관리하여 장애 발생 시 서비스 IP를 정상 노드로 이전시키는 역할을 합니다.
이 방식의 장점은 비교적 단순한 구조로 Active-Standby 형태의 failover를 구현할 수 있다는 점입니다. 별도의 외부 로드밸런서 없이도 내부망 또는 온프레미스 환경에서 빠르게 구성할 수 있고, 애플리케이션 진입점을 VIP 하나로 고정할 수 있어 운영 복잡도를 낮추기 좋습니다.
다만 이 방식은 본질적으로 부하 분산보다는 역할 전환 중심의 구조에 가깝습니다. 즉, Active-Active로 트래픽을 분산하는 모델이라기보다, 장애 시 대기 노드가 서비스를 넘겨받는 구조에 적합합니다.
3.2 AWS Load Balancer
AWS 환경이라면 ALB 또는 NLB를 통해 헬스 체크와 트래픽 전환을 관리하는 방식이 보다 자연스럽습니다. 인스턴스 상태를 기준으로 비정상 노드를 자동 제외할 수 있고, 필요하다면 Auto Scaling과도 연계할 수 있습니다.
다만 이 방식은 AWS 네이티브 환경에서 강점이 큰 반면, 현재처럼 서버가 고정되어 있고 Active-Standby 운영 모델이 더 적합한 환경에서는 상대적으로 과한 선택이 될 수 있습니다. 또한 이번 요구사항의 핵심은 스케일 아웃보다 역할 전환이었기 때문에, 운영 환경과 요구사항 측면에서 우선순위가 낮았습니다.
3.3 L4 로드밸런서
L4 로드밸런서는 TCP/UDP 레벨에서 트래픽을 분산합니다. 애플리케이션 프로토콜에 대한 이해 없이도 빠르게 트래픽을 처리할 수 있고, 특정 환경에서는 매우 안정적인 선택이 될 수 있습니다.
다만 SyncMon의 경우 웹 계층과 애플리케이션 실행 연계, 그리고 장애 시 애플리케이션/Agent 전환 시점까지 함께 관리해야 했기 때문에, 단순 패킷 분산만으로는 요구사항을 충분히 설명하기 어려웠습니다.
4. 선택한 방식과 선택 이유
현재 환경에서는 Nginx + Keepalived 기반의 Active-Standby 구성을 선택했습니다.
이 선택의 이유는 단순합니다. 이번 문제는 대규모 트래픽 분산보다는, 단일 장애점 제거와 빠른 서비스 인계가 더 중요했기 때문입니다. 두 대의 서버에 동일한 실행 환경을 준비해두고, 정상 노드가 VIP를 보유하다가 장애 발생 시 다른 노드가 VIP와 서비스 역할을 넘겨받는 구조가 현재 운영 모델과 가장 잘 맞았습니다.
여기서 중요한 점은, 이번 구성이 “로드밸런싱 중심 설계”가 아니라 failover 중심 설계라는 것입니다. 즉, 평상시에는 한 노드가 서비스를 담당하고 다른 노드는 즉시 승격 가능한 상태로 대기합니다. 이는 리소스 활용률만 보면 비효율적으로 보일 수 있지만, 운영 측면에서는 장애 시나리오를 단순하게 가져갈 수 있고, 역할 전환 흐름을 명확하게 통제할 수 있다는 장점이 있습니다.
5. 아키텍처 개요
구성은 다음과 같습니다.
- 203 서버: Active(MASTER)
- 204 서버: Standby(BACKUP)
두 서버 모두 동일한 Nginx 설정과 동일한 SyncMon 애플리케이션 실행 환경을 가집니다.
클라이언트는 개별 서버 IP가 아니라 VIP 로 접속합니다. 평상시에는 203 서버가 VIP를 보유하고 요청을 처리합니다. 203 서버에 장애가 발생하면 Keepalived가 VIP를 204 서버로 이전하고, 204 서버가 서비스 역할을 인계받습니다.
이 구조에서 핵심은 “서버가 두 대다”가 아니라, 클라이언트가 어느 서버가 살아 있는지 몰라도 되게 만드는 것입니다. 클라이언트 입장에서는 언제나 동일한 VIP로 접속하고, 내부에서는 서비스 역할만 정상 노드로 이동합니다.
6. 설계 전제
이번 구성이 정상적으로 동작하려면 몇 가지 전제가 필요합니다.
6.1 두 노드는 동일한 실행 환경을 가져야 합니다
203과 204는 단순히 패키지만 설치된 상태가 아니라, 실제로 동일한 서비스 역할을 즉시 수행할 수 있는 수준으로 맞춰져 있어야 합니다.
즉 다음 항목들이 일관되게 유지되어야 합니다.
- Nginx 설정
- SyncMon 애플리케이션 바이너리 및 설정 파일
- 의존 라이브러리 및 런타임
- 로그 디렉터리 및 권한 구조
- 프로세스 기동 방식(systemd 등)
이 전제가 깨지면 VIP 전환은 되어도 실제 서비스는 정상 인계되지 않을 수 있습니다. 실무에서는 VIP failover보다 환경 불일치로 인한 애플리케이션 기동 실패가 더 흔한 문제이기도 합니다.
6.2 DB는 외부에 별도로 존재해야 합니다
이번 문서는 웹/애플리케이션 서버 HA를 다룹니다.
따라서 애플리케이션이 참조하는 DB는 외부의 안정적인 엔드포인트로 분리되어 있어야 하며, 최소한 노드 전환과 무관하게 동일하게 접근 가능해야 합니다.
만약 DB가 특정 웹 서버 로컬에 종속되어 있다면, 애플리케이션 노드 failover만으로는 서비스 연속성을 확보할 수 없습니다. 이 경우 DB가 새로운 단일 장애점이 되기 때문입니다.
6.3 Agent 전환 정책이 명확해야 합니다
SyncMon은 단순 웹 서비스가 아니라 Agent 실행까지 함께 고려해야 하는 구조입니다. 따라서 VIP만 넘기는 것으로 충분하지 않고, MASTER 승격 시 Agent를 언제, 어떤 조건에서 기동할 것인지가 분명해야 합니다.
즉, 역할 전환은 네트워크 레벨의 VIP 승계에서 끝나지 않고, 서비스 프로세스와 Agent 실행 상태까지 포함한 애플리케이션 레벨 전환으로 이어져야 합니다.
7. 구성 방식
7.1 Nginx 및 Keepalived 설치
두 서버 모두 Nginx와 Keepalived를 설치합니다.
- Nginx: 클라이언트 요청을 수용하는 웹 진입점
- Keepalived: VIP 보유 노드를 결정하고 장애 시 VIP를 이전하는 역할
이 단계에서 중요한 것은 설치 자체보다, 두 노드가 동일한 역할을 수행할 수 있도록 환경을 맞추는 것입니다. 설치 이후 설정 차이, 배포 경로 차이, 인증서 차이, 포트 차이 같은 작은 불일치가 실제 failover 시 큰 장애로 이어질 수 있습니다.
7.2 Keepalived 설정
Keepalived는 두 노드 중 어느 쪽이 VIP를 보유할지를 결정합니다.
예를 들어 203 서버는 MASTER, 204 서버는 BACKUP으로 두고, 203에 더 높은 priority를 부여합니다. 평상시에는 203이 VIP를 보유하고, 장애 발생 시 204가 이를 승계합니다.
대표 설정 예시는 아래와 같습니다.
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass your_password
}
virtual_ipaddress {
192.168.0.100
}
}
204 서버는 state BACKUP, 더 낮은 priority로 설정합니다.
다만 실제 운영에서는 단순히 MASTER/BACKUP만 설정하는 수준에서 끝내지 않고, 무엇을 기준으로 장애를 판단할 것인지가 중요합니다. 단순히 서버가 살아 있는지만 볼 것인지, Nginx 프로세스 상태를 볼 것인지, 애플리케이션 헬스 체크까지 반영할 것인지에 따라 failover의 품질이 달라집니다.
즉, HA 구성의 핵심은 VIP를 넘기는 기술 자체보다, 잘못 살아 있는 상태를 얼마나 정확하게 비정상으로 판별하느냐에 가깝습니다.
7.3 Nginx 구성
두 서버의 Nginx 설정은 동일하게 유지해야 합니다.
프런트엔드 정적 리소스 제공 방식, 리버스 프록시 설정, 포트, 인증서, 캐시 정책 등이 다르면 VIP가 넘어가더라도 사용자 입장에서는 동일한 서비스로 보이지 않을 수 있습니다.
결국 이 단계의 목적은 “두 서버가 같은 요청을 같은 방식으로 처리하게 만드는 것”입니다.
Failover는 서버를 바꾸는 작업이 아니라, 역할을 복제된 다른 노드로 옮기는 작업이어야 합니다.
7.4 SyncMon 애플리케이션 및 Agent 실행 구성
두 노드는 모두 SyncMon 애플리케이션을 실행할 수 있어야 하며, 역할 전환 시 Agent 기동까지 연결되어야 합니다.
여기서 중요한 포인트는 Agent를 단순히 상시 실행해두는 것이 아니라, 현재 서비스 역할을 가진 노드에서만 책임 있게 동작하도록 제어하는 것입니다. 그렇지 않으면 Active/Standby 양쪽에서 중복 실행되거나, 반대로 전환 직후 필요한 작업이 수행되지 않는 문제가 생길 수 있습니다.
따라서 BACKUP 노드가 MASTER로 승격될 때 다음 흐름이 연계되어야 합니다.
- VIP 승계
- 웹 진입점 활성화 확인
- SyncMon 애플리케이션 상태 확인
- Agent 기동 또는 역할 활성화
이 과정은 Keepalived 상태 변경 이벤트와 연계된 스크립트나 서비스 트리거로 구성할 수 있습니다.
핵심은 “VIP가 넘어갔다”에서 끝내지 않고, 실제로 운영 역할이 완전히 넘어갔는지까지 확인 가능해야 한다는 점입니다.
8. 동작 시나리오
8.1 정상 상태
- 203 서버가 MASTER로 동작하며 VIP를 보유합니다.
- 클라이언트 요청은 VIP를 통해 203 서버로 유입됩니다.
- 203 서버에서 Nginx, SyncMon 애플리케이션, Agent가 운영 역할을 수행합니다.
- 204 서버는 BACKUP 상태로 대기하며, 즉시 승격 가능한 환경을 유지합니다.
8.2 장애 발생 시
- Keepalived가 MASTER 노드 상태를 감시합니다.
- 설정한 헬스 체크 기준에 따라 203 서버가 비정상으로 판단되면 VIP를 204 서버로 이전합니다.
- 204 서버는 MASTER 역할을 인계받고 Nginx를 통해 요청을 수용합니다.
- 연계된 전환 절차에 따라 SyncMon 애플리케이션 및 Agent를 운영 역할로 활성화합니다.
이때 중요한 것은 전환 속도 자체보다 전환 후 일관성입니다.
VIP는 빠르게 넘어갔지만 애플리케이션이 아직 준비되지 않았거나 Agent가 중복 실행되면, 표면적으로는 failover가 성공한 것처럼 보여도 실제 서비스는 불안정해질 수 있습니다.
8.3 복구 이후
기존 MASTER였던 203 서버가 복구되더라도 즉시 다시 역할을 가져오게 할지, 일정 기간 BACKUP으로 유지할지는 운영 정책에 따라 달라집니다.
실무에서는 무조건 자동 failback을 허용하기보다, 복구 노드 안정성 확인 후 수동 또는 조건부 재편입을 선택하는 경우가 많습니다. 장애 직후 복구된 노드를 즉시 다시 MASTER로 올리면, 짧은 시간 내 역할이 반복 전환되는 문제가 생길 수 있기 때문입니다.
즉, HA 구성에서는 failover만큼이나 failback 정책도 중요합니다.
9. 이 구성의 한계와 주의할 점
이번 구성은 웹/애플리케이션 서버 수준의 단일 장애점을 줄이는 데에는 효과적이지만, 모든 장애를 해결하는 구조는 아닙니다.
첫째, DB가 별도 HA를 갖추지 못하면 전체 서비스는 여전히 DB 장애에 취약합니다.
둘째, 두 노드의 설정과 배포 상태가 어긋나면 failover 이후 장애가 더 커질 수 있습니다.
셋째, Agent가 상태를 내부에 가지는 구조라면 역할 전환 시 상태 일관성을 어떻게 보장할지도 별도로 검토해야 합니다.
넷째, 헬스 체크 기준이 부정확하면 실제 장애를 놓치거나, 반대로 정상 노드를 비정상으로 판단해 불필요한 전환이 발생할 수 있습니다.
즉, HA는 서버를 두 대 두는 것으로 끝나는 작업이 아니라, 장애 판단 기준, 역할 전환 절차, 복구 정책, 운영 검증까지 포함해야 비로소 의미가 있습니다.
10. 결론
이번 SyncMon 고가용성 구성은 웹/애플리케이션 서버 영역의 단일 장애점을 제거하고, 장애 발생 시 서비스 진입점과 실행 역할을 다른 노드로 인계할 수 있도록 만든 Active-Standby 설계입니다.
이를 위해 203과 204 두 노드에 동일한 실행 환경을 준비하고, Keepalived로 VIP를 관리하며, Nginx와 SyncMon 애플리케이션 그리고 Agent 실행을 역할 전환 흐름에 맞춰 연계했습니다. 그 결과, 단일 노드 장애가 곧바로 전체 서비스 중단으로 이어지는 위험을 줄일 수 있게 되었습니다.
다만 이번 구성은 어디까지나 웹/애플리케이션 서버 HA에 대한 설계입니다.
실제 서비스 수준의 고가용성을 확보하려면 DB, 외부 연동, 상태 저장 방식, 운영 자동화까지 포함한 전체 아키텍처 차원의 검토가 뒤따라야 합니다.
결국 이번 구성의 핵심은 “서버를 한 대 더 두었다”가 아니라, 장애가 발생해도 서비스 역할을 잃지 않는 구조로 운영 모델을 재정의했다는 데 있습니다.