## 왜 Watchdog 시스템이 필요한가?
프로덕션 환경에서 서비스가 예기치 않게 중단되는 것을 방지하기 위해서는 능동적인 모니터링과 자동 복구 메커니즘이 필수입니다. 특히 여러 대의 워커 서버가 분산되어 있을 때, 각 서버의 상태를 실시간으로 감지하고 장애 발생 시 즉각 대응하는 시스템이 필요합니다.
이 글에서는 Heartbeat 방식의 Watchdog 시스템을 구축하면서 겪은 실전 노하우를 공유합니다.
## 시스템 아키텍처
### 기본 구조
```
[워커 서버들] --heartbeat (30초 간격)--> [중앙 모니터링 서버]
|
v
상태 체크 & 알림/복구 액션
```
### 핵심 컴포넌트
1. **중앙 모니터링 서버**: systemd로 관리되는 메인 서버
2. **Heartbeat 클라이언트**: 각 워커 서버에서 30초마다 상태 전송
3. **자동 복구 로직**: 장애 감지 시 단계별 대응
## 구현 과정에서 마주한 과제들
### 1. Windows 환경에서 CMD 창 팝업 문제
Heartbeat 클라이언트를 백그라운드로 실행할 때 subprocess 호출 시마다 CMD 창이 계속 나타나는 문제가 발생했습니다.
**해결책**: Python subprocess에 `CREATE_NO_WINDOW` 플래그 추가
```python
import subprocess
# Windows에서 창 없이 프로세스 실행
subprocess.Popen(
cmd,
creationflags=subprocess.CREATE_NO_WINDOW
)
```
### 2. PM2 경로 이슈 (Windows)
Windows 환경에서 PM2를 호출할 때 `.cmd` 확장자를 명시하지 않으면 실행이 실패합니다.
```python
# Linux/Mac
pm2_cmd = ['pm2', 'restart', 'app']
# Windows
pm2_cmd = ['pm2.cmd', 'restart', 'app']
```
### 3. 방화벽 및 보안 그룹 설정
Heartbeat 통신을 위해 모니터링 서버의 특정 포트(예: 51062)에 대한 TCP Inbound 규칙을 열어야 합니다.
### 4. 프록시 서버를 통한 간접 연결
일부 워커 서버가 내부 네트워크에 있을 경우, Nginx TCP Stream Proxy를 활용하여 연결을 중계할 수 있습니다.
```nginx
stream {
upstream heartbeat_backend {
server internal_server:port;
}
server {
listen 51062;
proxy_pass heartbeat_backend;
}
}
```
## 장애 대응 단계 설계
효과적인 Watchdog 시스템은 단계별 에스컬레이션 로직을 갖추어야 합니다.
### 권장 에스컬레이션 정책
1. **2분 무응답**: 자동 재시작 시도 (PM2/systemd 활용)
2. **3회 연속 실패**: 관리자에게 Telegram/Slack 알림
3. **10분 이상 장애**: 긴급 전화 알림
```python
class WatchdogPolicy:
NO_HEARTBEAT_THRESHOLD = 120 # 2분
MAX_RETRY = 3
CRITICAL_THRESHOLD = 600 # 10분
def check_and_respond(self, last_heartbeat):
elapsed = time.time() - last_heartbeat
if elapsed > self.CRITICAL_THRESHOLD:
self.send_phone_alert()
elif self.retry_count >= self.MAX_RETRY:
self.send_critical_message()
elif elapsed > self.NO_HEARTBEAT_THRESHOLD:
self.attempt_restart()
```
## 자동화된 복구를 위한 인증 설정
무인 복구 시스템을 구축하려면 비밀번호 없이 원격 서버에 접속할 수 있어야 합니다.
### 추천 방법: SSH Key 기반 인증
```bash
# 패스프레이즈 없는 SSH 키 생성
ssh-keygen -t ed25519 -f ~/.ssh/watchdog_key -N ""
# 대상 서버에 공개키 복사
ssh-copy-id -i ~/.ssh/watchdog_key.pub user@target_server
```
**보안 권장사항**:
- 전용 서비스 계정 사용
- 최소 권한 원칙 적용 (PM2 재시작만 가능하도록)
- IP 화이트리스트 설정
## 모니터링 및 검증
시스템 배포 후에는 각 워커의 상태를 대시보드나 API로 확인할 수 있어야 합니다.
```json
{
"workers": [
{
"id": "worker_01",
"status": "healthy",
"last_heartbeat": "2026-02-27T10:30:45Z"
},
{
"id": "worker_02",
"status": "healthy",
"last_heartbeat": "2026-02-27T10:30:52Z"
}
]
}
```
## 알려진 제약사항 및 대안
일부 SSH 라이브러리(예: ssh2)에서는 특정 환경의 원격 서버 접속이 실패할 수 있습니다. 이 경우 네이티브 SSH 클라이언트를 subprocess로 호출하는 것이 더 안정적입니다.
```python
# 라이브러리 대신 네이티브 SSH 사용
subprocess.run(['ssh', '-i', key_path, 'user@host', 'pm2 restart app'])
```
## 결론 및 다음 단계
Heartbeat 기반 Watchdog 시스템은 다음과 같은 이점을 제공합니다:
- **능동적 장애 감지**: 2분 이내 문제 인지
- **자동 복구**: 사람 개입 없이 서비스 재시작
- **단계별 알림**: 심각도에 따른 적절한 대응
추가로 고려할 사항:
- 메트릭 수집 (CPU, 메모리 등 Heartbeat에 포함)
- 장애 이력 대시보드 구축
- 다중 리전 지원
- Health check 엔드포인트와 연동
이러한 시스템은 Prometheus + Alertmanager, Grafana OnCall 등 오픈소스 도구와도 결합하여 더욱 강력한 운영 체계를 만들 수 있습니다.