Prometheus + Alertmanager로 서비스 헬스 모니터링: SLO·경보 규칙·소음 차단(Blackbox/Node/Process Exporter)
로그(LoKI)로 원인 파악은 좋아도, 문제가 생길 조짐을 먼저 울려주는 건 메트릭입니다.
여기서는 Ubuntu 24.04 기준으로 Prometheus 수집기 + Alertmanager 경보 라우팅을 붙이고,
node_exporter·blackbox_exporter·process_exporter를 조합해 SLO 기반 경보,
노이즈 억제(inhibit/group/silence), 운영 체크리스트까지 한 번에 세팅합니다.
1) 설치 구성(단일 노드 시작)
1-1) 디렉터리/사용자
sudo useradd --no-create-home --system --shell /usr/sbin/nologin prometheus
sudo mkdir -p /etc/prometheus /var/lib/prometheus
sudo chown -R prometheus:prometheus /etc/prometheus /var/lib/prometheus
1-2) 바이너리 배치(버전은 환경에 맞게 교체)
sudo mv prometheus promtool /usr/local/bin/
sudo chmod +x /usr/local/bin/prometheus /usr/local/bin/promtool
1-3) 기본 설정
# /etc/prometheus/prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
external_labels:
env: prod
site: dc1
rule_files:
- "rules/*.yml"
scrape_configs:
- job_name: prometheus
static_configs:
- targets: ["127.0.0.1:9090"]
- job_name: node
static_configs:
- targets: ["127.0.0.1:9100"] # node_exporter
- job_name: blackbox_http
metrics_path: /probe
params:
module: [http_2xx]
static_configs:
- targets:
- https://app.example.com/health
- https://api.example.com/actuator/health
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: 127.0.0.1:9115 # blackbox_exporter
- job_name: process
static_configs:
- targets: ["127.0.0.1:9256"] # process_exporter
1-4) 서비스 등록
# /etc/systemd/system/prometheus.service
[Unit]
Description=Prometheus Server
After=network-online.target
Wants=network-online.target
[Service]
User=prometheus
ExecStart=/usr/local/bin/prometheus \
--config.file=/etc/prometheus/prometheus.yml \
--storage.tsdb.path=/var/lib/prometheus \
--web.enable-lifecycle
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now prometheus
2) Exporter 3총사: 노드/서비스/외부헬스
2-1) node_exporter
sudo useradd --system --no-create-home --shell /usr/sbin/nologin nodeexp
sudo mv node_exporter /usr/local/bin/ && sudo chmod +x /usr/local/bin/node_exporter
sudo tee /etc/systemd/system/node_exporter.service >/dev/null <<'S'
[Unit]
Description=Node Exporter
After=network.target
[Service]
User=nodeexp
ExecStart=/usr/local/bin/node_exporter
Restart=always
[Install]
WantedBy=multi-user.target
S
sudo systemctl enable --now node_exporter
2-2) blackbox_exporter(HTTP/TCP/ICMP)
sudo mv blackbox_exporter /usr/local/bin/
sudo mkdir -p /etc/blackbox && sudo chown -R prometheus:prometheus /etc/blackbox
sudo tee /etc/blackbox/blackbox.yml >/dev/null <<'B'
modules:
http_2xx:
prober: http
timeout: 5s
http:
method: GET
headers:
User-Agent: "probe"
preferred_ip_protocol: "ip4"
B
sudo tee /etc/systemd/system/blackbox_exporter.service >/dev/null <<'S'
[Unit]
Description=Blackbox Exporter
After=network-online.target
[Service]
User=prometheus
ExecStart=/usr/local/bin/blackbox_exporter --config.file=/etc/blackbox/blackbox.yml --web.listen-address=:9115
Restart=always
[Install]
WantedBy=multi-user.target
S
sudo systemctl enable --now blackbox_exporter
2-3) process_exporter(특정 프로세스 헬스)
sudo mv process-exporter /usr/local/bin/process-exporter
sudo tee /etc/process-exporter.yml >/dev/null <<'P'
process_names:
- name: "java"
cmdline:
- '.*/java.*-jar.*'
- name: "nginx"
cmdline:
- '.*/nginx: master process.*'
P
sudo tee /etc/systemd/system/process-exporter.service >/dev/null <<'S'
[Unit]
Description=Process Exporter
After=network.target
[Service]
ExecStart=/usr/local/bin/process-exporter --config.path=/etc/process-exporter.yml --web.listen-address=:9256
Restart=always
[Install]
WantedBy=multi-user.target
S
sudo systemctl enable --now process-exporter
3) SLI/SLO를 먼저 정한다(그래야 경보가 유의미)
- 가용성 SLI:
blackbox_http로 /health 200 비율. - 지연 SLI: 백엔드
http_server_requests_seconds_bucketp95. - 오류율 SLI: 5xx/전체 요청 비율.
SLO 예: “가용성 99.9% 월간”. 에러버짓은 43.2분. 경보는 이 버짓을 초과할 추세에서 울려야 합니다.
4) 룰 파일: 가용성/지연/리소스 경보
# /etc/prometheus/rules/slo-alerts.yml
groups:
- name: slo.apdex
rules:
- record: sli:probe_success:ratio_5m
expr: sum(rate(probe_success[5m])) by (instance) / sum(rate(probe_success[5m])) by (instance)
- alert: SLOAvailabilityFastBurn
expr: (1 - sli:probe_success:ratio_5m) > 0.05
for: 10m
labels:
severity: critical
scope: fast-burn
annotations:
summary: "가용성 급격 저하 ({{ $labels.instance }})"
description: "5분 오류율 > 5%. 즉시 조치 필요"
- name: backend.latency
rules:
- record: app:request:p95_5m
expr: histogram_quantile(0.95, sum by (le) (rate(http_server_requests_seconds_bucket{job="myapp"}[5m])))
- alert: BackendLatencyHigh
expr: app:request:p95_5m > 0.8
for: 10m
labels:
severity: warning
annotations:
summary: "백엔드 p95 지연 상승"
description: "최근 10분 p95 > 800ms"
- name: node.resources
rules:
- alert: NodeDiskAlmostFull
expr: (node_filesystem_avail_bytes{fstype=~"ext4|xfs"} / node_filesystem_size_bytes{fstype=~"ext4|xfs"}) < 0.1
for: 15m
labels:
severity: warning
annotations:
summary: "디스크 여유 < 10%"
description: "파티션 {{ $labels.mountpoint }} 용량 부족"
- alert: NodeHighLoad
expr: (node_load1 / count without (cpu,mode) (node_cpu_seconds_total{mode="idle"})) > 1.5
for: 15m
labels:
severity: warning
annotations:
summary: "시스템 Load 평균 과다"
description: "1분 Load가 vCPU 대비 1.5배 초과"
룰 추가 후:
sudo mkdir -p /etc/prometheus/rules
sudo chown -R prometheus:prometheus /etc/prometheus
promtool check rules /etc/prometheus/rules/slo-alerts.yml
curl -X POST http://127.0.0.1:9090/-/reload
5) Alertmanager: 그룹핑/라우팅/억제(inhibit)/침묵(silence)
# /etc/alertmanager/alertmanager.yml
global:
resolve_timeout: 5m
route:
receiver: slack-default
group_by: ['alertname','instance']
group_wait: 30s
group_interval: 5m
repeat_interval: 3h
routes:
- matchers:
- severity="critical"
receiver: slack-critical
group_by: ['alertname']
repeat_interval: 1h
inhibit_rules:
- source_matchers: [ 'alertname="SLOAvailabilityFastBurn"' ]
target_matchers: [ 'alertname="BackendLatencyHigh"' ]
equal: ['instance']
receivers:
- name: slack-default
slack_configs:
- api_url: https://hooks.slack.com/services/XXX/YYY/ZZZ
channel: "#ops"
title: '[{{ .Status | toUpper }}] {{ .CommonAnnotations.summary }}'
text: "{{ range .Alerts }}• {{ .Annotations.description }} ({{ .Labels.instance }}){{ end }}"
- name: slack-critical
slack_configs:
- api_url: https://hooks.slack.com/services/XXX/YYY/ZZZ
channel: "#ops-critical"
title: '[CRIT] {{ .CommonAnnotations.summary }}'
text: "{{ range .Alerts }}• {{ .Annotations.description }}{{ end }}"
5-1) Alertmanager 서비스
sudo useradd --system --no-create-home --shell /usr/sbin/nologin alertman
sudo mv alertmanager amtool /usr/local/bin/
sudo mkdir -p /etc/alertmanager && sudo chown -R alertman:alertman /etc/alertmanager
sudo tee /etc/systemd/system/alertmanager.service >/dev/null <<'S'
[Unit]
Description=Alertmanager
After=network-online.target
[Service]
User=alertman
ExecStart=/usr/local/bin/alertmanager --config.file=/etc/alertmanager/alertmanager.yml --storage.path=/var/lib/alertmanager
Restart=always
[Install]
WantedBy=multi-user.target
S
sudo systemctl daemon-reload
sudo systemctl enable --now alertmanager
5-2) Prometheus에 Alertmanager 연결
# /etc/prometheus/prometheus.yml (하단에 추가)
alerting:
alertmanagers:
- static_configs:
- targets: ["127.0.0.1:9093"]
curl -X POST http://127.0.0.1:9090/-/reload
6) 소음 차단 전략(현업 팁)
- inhibit: 근본 경보(가용성 붕괴)가 떴을 때 파생 경보(지연/에러율)를 자동 억제.
- group_by: 동일 인스턴스/알럿명을 묶어 한 번에 묶음 알림.
- repeat_interval: 해결 전 반복 주기(critical은 짧게, warning은 길게).
- Silence: 점검창에는 라벨 기반 침묵(서비스=api, env=staging, 2h 등).
7) 대시보드/런북 안내 붙이기
Grafana 대시보드 URL과 Runbook(조치 가이드)를 알림에 포함하세요.
# Alert annotations 예시
annotations:
summary: "백엔드 p95 지연 상승"
description: "최근 10분 p95 > 800ms"
runbook: "https://grafana.example.com/d/abc123/backend-latency"
8) 다중 서버 확장(풀링 구조)
- 각 서버에
node_exporter/process_exporter설치, Prometheus 서버에서 풀링. - 원격 리전은 리전별 Prometheus + Thanos/Cortex 도입을 고려(장기 보관/집계).
9) 트러블슈팅 빠른 분기
- 메트릭이 비어 있음 →
/targets페이지에서 스크레이프 에러 확인. - 경보가 안 울림 →
/rules상태/평가 주기 확인, Alertmanager/#/status점검. - 알림 폭주 → group/inhibit/silence 재점검, 임계치에
for:(지속 시간) 추가. - 블랙박스 실패 → 방화벽/리스폰스 코드/리다이렉트 체인 점검, 타임아웃 상향.
10) 체크리스트(복붙용)
- SLI/SLO 문서화(가용성·지연·오류율), 에러버짓 계산
- 룰에
for:지정(일시적 스파이크 무시) - Alertmanager group/inhibit/silence 설계
- 대시보드/Runbook 링크를 알림에 포함
- 점검창 스케줄은 사전 Silence
이 구성을 적용하면 “장애가 난 뒤”가 아니라 “버짓을 갉아먹기 시작한 순간”에 알림이 울립니다. 로그(LoKI)와 메트릭(Prometheus), 알림(Alertmanager)을 연결해 탐지→진단→조치 루프를 짧게 만드세요.