개요 — 무엇을 하나
Infrastructure ▸ Alerts(/infra/alert)는 경보 그룹(정책) 콘솔입니다. 운영자가 하나의 정책(infr_alert_policy)에 4개 영역(시스템·웹·DB·보안) 조건을 켜고 임계 factor 를 화면에서 조절하면, 위반이 발생했을 때 그룹의 담당자(infr_alert_recipient)에게 SMS/메일로 자동 통지합니다.
구 "Capacity & Alerts"(/infra/capacity)를 이 네임스페이스로 대체했습니다(구 경로는 자동 리다이렉트).
핵심 특징:
- 정책 = 하나의 감시 묶음: 심각도·재알림 억제(쿨다운)·영역·조건·채널·담당자를 한 카드에 모읍니다. 팀·시간대(예: "인프라 야간 당직", "보안 관제")별로 정책을 여러 개 만들 수 있습니다.
- 평가/발송 분리: 조건 평가는
AlertEvaluator, 발화·발송은AlertDispatcher가 담당합니다. 이 두 서비스는 콘솔의 [지금 검사] 버튼과 스케줄 커맨드infr:eval-alerts가 공유합니다. - 디둡·쿨다운·배치·자동 해소: 같은 위반은 한 경보로 집계하고, 쿨다운 동안 재발송을 억제하며, 한 정책의 알림을 한 통으로 묶어 보내고(SMS 폭주 방지), 위반이 사라지면 경보를 자동으로 닫습니다.
- 읽기 전용 실데이터: 시스템은
server_status, DB는infr_db_metric, 보안은legacy_glory탐지 테이블, 웹은 라이브 HTTP 프로브를 사용합니다. 웹 인증서 임박은infr_web_cert를 전역 스캔합니다.
이 화면은 정책·경보·발송 이력만 관리합니다. 개별 서버 그래프는 Servers, 웹 가동율은 Service ▸ Web, DB 부하는 Service ▸ Database 를 보세요. 임계 기본값은 운영 정책에서 규정합니다.
언제 쓰나
- 특정 서버의 로드에버리지·디스크 여유가 위험선을 넘으면 즉시 통지받고 싶을 때.
- 랜딩 URL 이 다운(상태코드 이상·응답 없음) 되거나 응답이 느려질 때 당직자에게 알리고 싶을 때.
- 등록 웹서비스의 TLS 인증서 자동 갱신이 실패해 만료가 임박했는지 상시 감시하고 싶을 때.
- 등록 DB의 대기 큐가 쌓이거나 시간당 slow query 가 급증할 때.
- IDS 경보 폭주·AI 이상탐지 차단 급증·신규 차단 IP 급증 같은 침해 신호를 팀에 broadcast 하고 싶을 때.
화면 구성
정책 카드 그리드
각 정책이 카드 하나로 표시됩니다. 카드는 활성 토글, 심각도 배지, 켜진 영역, 담당자 수를 요약하고 다음 액션을 제공합니다.
| 액션 | 설명 | 권한 |
|---|---|---|
| 활성/중지 토글 | is_active — 스케줄 평가 대상 여부 |
level≥2 |
| 편집 | 영역·조건·채널·담당자 편집 모달 | level≥2 |
| 지금 검사 | 이 정책만 즉시 평가·발송(run) |
level≥2 |
| 테스트 | 담당자에게 지금 테스트 메일/SMS(test) |
level≥2 |
| 삭제 | 정책 + 담당자 삭제 | level≥2 |
| 드래그 정렬 | 표시·평가 순서(seq, reorder) |
level≥2 |
편집 모달 (영역·조건·채널·담당자)
- 기본: 이름, 심각도(info/warn/crit), 재알림 억제(분), 활성, 메모.
- 경보 영역: 시스템·웹·DB·보안 중 감시할 영역을 켭니다(시스템 기본 활성).
- 조건: 켜진 영역별로 on/off + 임계 factor 를 조절합니다(아래 조건 카탈로그).
- 알림 채널: SMS·메일. 실제 발송은 메일 어댑터/SMS 어댑터의 provider 설정이 있어야 동작합니다. provider 미설정이면 카드에 경고를 띄웁니다.
- 담당자(repeater): 이름·이메일·전화 +
via_mail/via_sms체크. 채널은 정책 channels ∩ 담당자 via_* 의 교집합으로 결정됩니다.
최근 경보 피드
infr_alert 를 last_seen 내림차순 60건 표시(30초 폴링). 각 행은 관측 값·임계·집계 count·발송 성공/전체(infr_alert_delivery 집계)를 보여주고 [확인(ack)]·[해소(close)] 상태 전이를 제공합니다.
사용법
1) 정책 만들기
- [새 경보 그룹] → 이름·심각도·쿨다운 입력.
- 경보 영역에서 감시할 영역을 켭니다.
- 각 영역의 조건을 켜고 임계 factor 를 조절합니다. 기본값은 운영 정책의
alertDefaults()로 프리필됩니다. - 알림 채널(SMS/메일)을 선택하고 담당자를 추가합니다.
- 저장.
2) 조건 카탈로그
시스템 (server_status · seq 창)
| 조건 | 토글 | factor | 기본값 | 발화 metric |
|---|---|---|---|---|
| 로드에버리지 초과 | sys_load_on |
sys_load_max |
20 | load_avg (>20, 서버별) |
| 디스크 여유 이하 | sys_disk_on |
sys_disk_free_mb |
500 | disk_free (<500MB) |
- 대상은 전체 서버(
targets.system.all=true)가 기본이며, 개별 alias 를 선택 목록으로 좁힐 수 있습니다(최대 200). - 스냅샷은 최신 seq 창(
distinct seq desc limit 3)만 읽어 slow query 를 피합니다(HealthService 계승). 오프라인/무데이터 서버는 판정하지 않습니다(최신 2 사이클에loadavg가 있어야 online). - 디스크 여유는 파티션(
df-,df-data,df-home) 중 가장 빠듯한 여유를 씁니다(DfParse::availableGb).
웹 (라이브 HTTP 프로브 · infr_web_cert)
| 조건 | 토글 | factor | 기본값 | 발화 metric |
|---|---|---|---|---|
| 서비스 OFF(상태코드 ≠ 기대) | web_code_on |
web_expect_code |
200 | http_status |
| 웹 지연 초과 | web_latency_on |
web_latency_ms |
5000 | latency |
| 인증서 임박 | web_cert_on |
web_cert_hours |
48 | cert_expiry |
- 대상 URL 은 정책의
targets.web.urls[](라벨 포함, 정책당 최대 30). 매 평가 주기마다Http::connectTimeout(4)->withoutVerifying()->get()로 직접 요청합니다. 상태코드가 기대와 다르거나 연결 실패/타임아웃이면 서비스 OFF 로 취급합니다(코드 조건이 켜진 경우). - 인증서 임박은 단일 토글이지만 스캔은 전역입니다: 정책의 대상 URL 과 무관하게 등록된 모든 웹서비스의 도메인 인증서(
infr_web_cert)를 훑어, 만료가 임계(web_cert_hours, 기본 48h) 이내인 도메인마다 위반을 만듭니다(한 평가당 최대 50건). 인증서는 WebProbeService가 6시간 주기로 순환 적재합니다. 자동 갱신 실패로 만료가 임박했는데 아무도 모르는 상황을 막습니다.
"인증서 임박 [v]" 하나만 켜면 모든 사이트의 인증서를 감시합니다. 특정 사이트만 감시하는 게 아니라 전 도메인 전역 스캔입니다.
데이터베이스 (infr_db_metric 최신 샘플)
| 조건 | 토글 | factor | 기본값 | 발화 metric |
|---|---|---|---|---|
| 대기(pending) 큐 증가 | db_waiting_on |
db_waiting_max |
5 | db_waiting (>=5) |
| 시간당 slow query | db_slow_on |
db_slow_per_hour |
60 | db_slow (slow_qps×3600 >= 60) |
- 대상은
targets.database.collectors[](access=database 수집기 key). 대상을 하나도 고르지 않으면 평가하지 않습니다. DbCollectorService::latest($collector)최신 샘플을 읽되,ok이고 10분 이내 샘플만 판정합니다(오래된 샘플 오탐 방지). 수집기 등록·수집은 DB 수집기 참조.
보안 (legacy_glory 탐지 테이블 · 복합)
평가 창은 sec_window_min(기본 10분). 아래 신호 중 하나라도 임계를 넘으면 침해사고로 발화합니다.
| 조건 | 토글 | factor | 기본값 | 원천 |
|---|---|---|---|---|
| IDS 심각도 + 건수 | sec_ids_on |
sec_ids_severity, sec_ids_count |
2, 20 | suricata_alert_ct (severity≥S, 창 내 count≥N) |
| AI 이상탐지 차단 급증 | sec_kitsune_on |
sec_kitsune_count |
5 | kitsune_detail_log (is_blocked=1, count≥N) |
| 신규 차단 IP 급증 | sec_blacklist_on |
sec_blacklist_count |
10 | blacklist_info (창 내 신규 created_at, count≥N) |
관련: Threats · Detections · Blocklist.
3) 지금 검사 / 테스트
- [지금 검사](
run): 이 정책 하나만 즉시evaluate()→handle()실행하고 위반·발송 요약(위반 :b건 · 발송 :s건)과 갱신된 피드를 반환합니다. 스케줄을 기다리지 않고 조건이 실제로 걸리는지 확인할 때 씁니다. - [테스트](
test): 활성 담당자에게 지금 테스트 메일/SMS 를 보내 채널이 정상인지 확인합니다(경보 발화와 무관, provider 정상성 확인용).
4) 자동 평가 (스케줄)
활성 정책은 매분 스케줄로 자동 평가·발송됩니다.
Schedule::command('infr:eval-alerts --quiet-if-ok')
->everyMinute()
->withoutOverlapping(2)
->onOneServer()
->when($is_leader);
수동 실행:
# 활성 정책 전체 평가(단발 실행 후 종료 — 데몬 아님)
php artisan infr:eval-alerts
# 특정 정책만
php artisan infr:eval-alerts --policy=12
# 위반 없으면 출력 억제(스케줄 기본)
php artisan infr:eval-alerts --quiet-if-ok
infr:eval-alerts는 단발 실행 후 종료하는 커맨드입니다(정책 순회 후 exit). 절대 무한 루프 데몬으로 만들지 마세요 — 종료되지 않는 데몬을 스케줄러로 spawn 하면 공유 DB 연결이 고갈됩니다(§pulse:check 연결 누수 교훈). 스케줄러가 매분 안전하게 새로 띄웁니다.
데이터 소스
쓰기 테이블 (신규 infr_)
| 테이블 | 마이그레이션 | 역할 |
|---|---|---|
infr_alert_policy |
000700 | 경보 그룹(정책). scopes/targets/conditions/channels JSON + severity·cooldown_min·seq |
infr_alert_recipient |
000701 | 정책별 담당자(인라인). email/phone + via_mail/via_sms/is_active/seq |
infr_alert |
000702 | 경보 인스턴스(발화 로그·트리아지 큐). 디둡 키 (policy_id, metric, entity_key, status='open'), notified_at 쿨다운 |
infr_alert_delivery |
000703 | 발송 이력. channel/address/ok/provider_code/message_id/error/latency_ms |
읽기 소스 (레거시·신규, 읽기 전용)
- 시스템:
server_status(legacy커넥션, part=loadavg/df-*). - 웹: 라이브 HTTP GET(대상 URL) +
infr_web_cert(인증서 만료). - DB:
infr_db_metric(access=database 수집기가 적재). - 보안:
legacy_glory의suricata_alert_ct·kitsune_detail_log·blacklist_info.
디둡·쿨다운·자동 해소 흐름
AlertEvaluator::evaluate($policy)→ 활성 영역별 위반 후보 배열. 영역 예외는 격리(한 영역 실패가 전체를 막지 않음).AlertDispatcher::handle($policy, $breaches):- 각 위반을
(policy_id, metric, entity_key, status=open)로 조회 → 있으면 갱신+count++, 없으면 신규 insert(first_seen, count=1, notified_at=null). - 알림 대상 = 신규 OR
notified_at없음 ORnotified_at <= now - cooldown_min. - 자동 해소: 이번 위반 목록에 없는 이 정책의 open 경보 →
status='closed'. - 배치 발송: 알림 대상 경보들을 한 통으로 묶어 담당자×채널당 1회 발송(본문 최대 8줄, 초과는 "외 N건"; SMS 140자 상한). 발송 후 각 대상의
notified_at=now. infr_alert_delivery에 (담당자,채널)당 1행 기록.
- 각 위반을
권한
| 작업 | 최소 레벨 | 감사 |
|---|---|---|
| 화면·목록·피드 조회(index/list/feed) | 1 (read) | — |
| 정책 저장·삭제·정렬(save/delete/reorder) | 2 (write) | alert_policy.create / .update / .delete |
| 경보 ack/close | 2 | alert.ack / alert.closed |
| 지금 검사(run) | 2 | 발송 시 alert.fire |
| 테스트 발송(test) | 2 | alert.test |
| 스케줄 자동 발송 | (시스템) | alert.fire |
레벨 기준: demo=1 · staff=5 · admin=10. 읽기는 level≥1, 쓰기·발송은 level≥2. 파괴·발송 작업은 전부 infr_audit_log 에 기록됩니다(감사 로그). 발송 채널 provider 는 관리자(level≥10)가 설정합니다.
문제해결 · FAQ
Q. 조건을 켰는데 알림이 안 옵니다.
- 정책이 활성인지, 스케줄러(
schedule:work/ prod supervisor)가 도는지 확인. - 채널 provider 미설정 — 카드 경고를 확인하고 메일 어댑터/SMS 어댑터에서 기본 provider 를 설정하세요.
- 담당자의
via_mail/via_sms와 정책 채널의 교집합이 비어 있지 않은지, 이메일/전화가 채워졌는지 확인. - 쿨다운 중이면 재발송이 억제됩니다(
cooldown_min, 기본 30분). [지금 검사]로 즉시 확인하되, 이미 알림된 경보는 쿨다운이 지나야 재발송됩니다.
Q. DB/시스템 조건이 조용합니다.
- 시스템: 대상 서버가 online(최신 2 seq 사이클에 loadavg)이어야 판정합니다. 오프라인/무데이터는 skip.
- DB:
infr_db_metric최신 샘플이 ok 이고 10분 이내여야 합니다. 수집기가 도는지 DB 수집기에서 확인.
Q. 인증서 임박이 특정 사이트만 감시하나요?
- 아니요.
web_cert_on은 전역 스캔입니다 — 등록 웹서비스 전 도메인의infr_web_cert를 훑습니다. 정책의 대상 URL 과 무관합니다.
Q. 같은 위반이 계속 쌓이나요?
- 아니요.
(policy_id, metric, entity_key)로 열린 경보 하나에 집계(count++)됩니다. 위반이 사라지면 다음 평가에서 자동으로closed됩니다.
Q. 웹 프로브가 정책 평가를 느리게 만들까요?
- URL 은 정책당 최대 30개, connectTimeout 4초 + 지연 임계 기반 짧은 timeout 으로 제한합니다. 시스템 스냅샷은 seq 창만 읽어 slow query 를 피합니다.
관련 항목
- 운영 정책 — 임계 기본값(
alertDefaults()) 규정 - 메일 어댑터 · SMS 어댑터 — 발송 채널 provider
- Service ▸ Web — 인증서·가동율 원천(
infr_web_cert) - DB 수집기 — DB 조건 원천(
infr_db_metric) - Servers · Health — 시스템 조건 원천(
server_status) - Threats · Blocklist — 보안 조건 원천
