개요
기존 모니터링 앱에 SMS / Email / 전화 알람 서비스를 추가하고 AWS에 배포했다.
운영 서버에 대한 야간 모니터링을 통해 긴급 상황 발생 시 담당자에게 즉시 알림을 전달하는 것이 목적이다.
동작 방식
2분마다 대상 서버 포트 확인
↓
응답 코드 200 아닌 경우
또는 5초 이상 응답 없음
또는 5초 이상 연결 실패
↓
SMS / Email / 전화 알람 발송
알람 트리거 조건
| 조건 | 설명 |
|---|---|
| HTTP 응답 코드 != 200 | 서버 오류 응답 |
| 응답 시간 > 5초 | 서버 과부하 또는 지연 |
| 연결 실패 (5초 이상) | 서버 다운 또는 네트워크 단절 |
수행 주기
- 기본: 24시간 상시 운영
- 옵션: 저녁 시간대에만 동작하도록 스케줄 변경 가능
모니터링 대상
설정 파일을 통해 대상을 유동적으로 추가/삭제할 수 있다.
# monitoring_targets.yaml
targets:
- name: "[SERVICE-A] AP1"
url: "http://[internal-ip-1]:[port-1]"
- name: "[SERVICE-A] AP2"
url: "http://[internal-ip-2]:[port-1]"
- name: "[SERVICE-B] AP1"
url: "http://[internal-ip-1]:[port-2]"
- name: "[SERVICE-B] AP2"
url: "http://[internal-ip-2]:[port-2]"
- name: "[SERVICE-B] AP1 Health"
url: "http://[internal-ip-1]:[port-3]/hello"
- name: "[SERVICE-B] AP2 Health"
url: "http://[internal-ip-2]:[port-3]/hello"알람 수단
SMS, Email, 전화 중 다중 선택 가능하며, 수신 대상은 설정 파일로 유동적으로 관리한다.
SMS
def send_sms(recipients: list, message: str):
sns = boto3.client('sns')
for phone in recipients:
sns.publish(
PhoneNumber=phone,
Message=message,
)
# 사용 예시
send_sms(
recipients=['[phone-1]', '[phone-2]', '[phone-3]'],
message="운영 서버 포트 접속 에러입니다. 대응 부탁드립니다."
)Email (SES)
def send_email(subject: str, body: str):
ses = boto3.client('ses')
ses.send_email(
Source='[sender-email]',
Destination={'ToAddresses': ['[team-email]']},
Message={
'Subject': {'Data': subject},
'Body': {'Text': {'Data': body}}
}
)
# 사용 예시
send_email(
subject='[긴급][운영 APP] Connection Timeout',
body='운영 서버 포트 접속 에러입니다.'
)전화 (Amazon Connect / Twilio)
def make_call(recipients: list, message: str):
# 순차적으로 전화 발신
for phone in recipients:
client.calls.create(
to=phone,
from_='[caller-number]',
tts_message=message
)
# 순차 발신: 담당자1 → 담당자2 → 담당자3 → ...포트 확인 핵심 로직
import requests
import time
TIMEOUT = 5 # 5초
def check_port(name: str, url: str) -> dict:
try:
start = time.time()
response = requests.get(url, timeout=TIMEOUT)
elapsed = time.time() - start
if response.status_code != 200:
return {
'name': name,
'status': 'ERROR',
'reason': f'HTTP {response.status_code}',
'elapsed': elapsed
}
if elapsed > TIMEOUT:
return {
'name': name,
'status': 'SLOW',
'reason': f'응답 지연 {elapsed:.1f}초',
'elapsed': elapsed
}
return {'name': name, 'status': 'OK', 'elapsed': elapsed}
except requests.exceptions.ConnectTimeout:
return {'name': name, 'status': 'TIMEOUT', 'reason': '연결 시간 초과'}
except requests.exceptions.ConnectionError:
return {'name': name, 'status': 'DOWN', 'reason': '연결 실패'}설정 파일 기반 수신자 관리
알람 수신 대상을 코드 변경 없이 설정 파일로 관리한다.
# alarm_config.yaml
sms:
enabled: true
recipients:
- "[phone-1]"
- "[phone-2]"
- "[phone-3]"
email:
enabled: true
from: "[sender-email]"
to:
- "[team-email]"
call:
enabled: true
recipients:
- "[phone-1]" # 1순위
- "[phone-2]" # 2순위
- "[phone-3]" # 3순위배포 구성
Docker Container (Port Monitor)
├── 2분 간격 배치 실행
├── monitoring_logs.json 기록
└── 이상 감지 시 알람 발송
├── AWS SNS (SMS)
├── AWS SES (Email)
└── 전화 발신 서비스
운영 서버 내 Docker 컨테이너로 배포하여 별도 인프라 없이 운영한다.
로그 확인
# 특정 환경 모니터링 로그 확인
docker exec -it [container-id] grep -c "[SERVICE-NAME] Prod" monitoring_logs.json설계 포인트
설정 파일 기반 유연성 수신자 목록, 모니터링 대상, 알람 수단을 모두 설정 파일로 관리해 코드 변경 없이 운영 중 수정 가능하다.
다중 알람 채널 SMS, Email, 전화를 독립적으로 활성화/비활성화할 수 있어 상황에 맞는 알람 전략을 유연하게 구성할 수 있다.
순차 전화 발신 전화 알람은 담당자 우선순위에 따라 순차적으로 발신해 책임자가 반드시 인지하도록 설계했다.
정리
- 운영 서버 포트 상태 2분 간격 상시 모니터링 구축
- HTTP 오류 / 응답 지연 / 연결 실패 3가지 조건 감지
- SMS / Email / 전화 다중 알람 채널 구성
- 설정 파일 기반으로 수신자 및 대상 유동적 관리
- Docker 컨테이너로 경량 배포
배운 점
이 시스템을 만들고 나서 알게 된 건 감지보다 전달이 어렵다는 점이다. 포트가 죽었는지 확인하는 코드는 몇 줄이면 끝난다. 정작 오래 고민한 부분은 "이 알림을 새벽 세 시에 누구 휴대폰으로 울리게 할 것인가"였다. 모니터링은 기술 문제로 시작해서 운영 정책 문제로 끝난다.
설정 파일로 대상과 수신자를 빼둔 선택은 시간이 지날수록 값을 했다. 담당자가 바뀌거나 서버가 늘어날 때마다 코드를 고치고 다시 배포했다면 이 시스템은 오래 못 갔을 것이다. 운영 도구에서 바뀌는 건 로직이 아니라 대상이다.
다만 이때는 감지 조건이 단순했다. 응답이 없으면 알린다, 그뿐이었다. 뒤에 CloudWatch 알람 기반 EC2/ECS 통합 모니터링 구축에서 심각도를 나누게 되는데, 그 필요를 느끼게 된 계기가 바로 이 단계에서 쌓인 알림 피로였다.
이어 읽기
- CloudWatch 알람 기반 EC2/ECS 통합 모니터링 구축: 심각도에 따라 알림 채널을 나눈 다음 단계
- 통합 모니터링 시스템 구축: 이 포트 모니터가 통합 체계 안에서 맡은 자리