모니터링 스택
Prometheus + Grafana + Alertmanager로 구성하는 완전한 모니터링 시스템
Prometheus + Grafana + Alertmanager로 구성하는 완전한 모니터링 시스템
목표: 프로덕션 환경의 메트릭을 수집, 시각화, 알림할 수 있는 수준
📊 모니터링 스택 개요
아키텍처
graph TB
subgraph "모니터링 스택"
APP["📦 Application"] -->|"/metrics"| PROM["🎯 Prometheus"]
NODE["💻 Node"] -->|"node_exporter"| PROM
K8S["☸️ Kubernetes"] -->|"kube-state-metrics"| PROM
PROM -->|"질의"| GRAFANA["📊 Grafana"]
PROM -->|"알림"| ALERT["🚨 Alertmanager"]
ALERT -->|"알림"| SLACK["💬 Slack"]
ALERT -->|"알림"| PAGERDUTY["📟 PagerDuty"]
end
🎯 Prometheus
설치
# Docker
docker run -d \
--name prometheus \
-p 9090:9090 \
-v /path/to/prometheus.yml:/etc/prometheus/prometheus.yml \
prom/prometheus
# Kubernetes
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install prometheus prometheus-community/prometheus
설정
# prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
alerting:
alertmanagers:
- static_configs:
- targets: ['alertmanager:9093']
rule_files:
- /etc/prometheus/rules/*.yml
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node-exporter'
static_configs:
- targets: ['node-exporter:9100']
- job_name: 'application'
static_configs:
- targets: ['app:8080']
metrics_path: '/metrics'
scrape_interval: 5s
📈 메트릭 수집
애플리케이션 메트릭
# Python (prometheus_client)
from prometheus_client import Counter, Histogram, Gauge, start_http_server
import time
# 카운터
requests_total = Counter(
'http_requests_total',
'Total HTTP requests',
['method', 'endpoint', 'status']
)
# 히스토그램
request_duration = Histogram(
'http_request_duration_seconds',
'HTTP request duration',
['method', 'endpoint']
)
# 게이지
active_connections = Gauge(
'active_connections',
'Number of active connections'
)
# 사용
@request_duration.time()
def handle_request(method, endpoint):
active_connections.inc()
try:
# 처리
requests_total.labels(method=method, endpoint=endpoint, status='200').inc()
except Exception:
requests_total.labels(method=method, endpoint=endpoint, status='500').inc()
finally:
active_connections.dec()
# 메트릭 서버
start_http_server(8000)
Node Exporter
# 설치
wget https://github.com/prometheus/node_exporter/releases/download/v1.6.1/node_exporter-1.6.1.linux-amd64.tar.gz
tar xvfz node_exporter-1.6.1.linux-amd64.tar.gz
sudo cp node_exporter-1.6.1.linux-amd64/node_exporter /usr/local/bin/
# 서비스 등록
sudo tee /etc/systemd/system/node_exporter.service > /dev/null <<EOF
[Unit]
Description=Node Exporter
[Service]
ExecStart=/usr/local/bin/node_exporter
Restart=always
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable node_exporter
sudo systemctl start node_exporter
🚨 Alertmanager
설정
# alertmanager.yml
global:
slack_api_url: 'https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK'
route:
group_by: ['alertname', 'severity']
group_wait: 30s
group_interval: 5m
repeat_interval: 12h
receiver: 'default'
routes:
- match:
severity: critical
receiver: 'pagerduty'
continue: true
- match:
severity: warning
receiver: 'slack'
receivers:
- name: 'default'
slack_configs:
- channel: '#alerts'
title: '{{ .GroupLabels.alertname }}'
text: '{{ .CommonAnnotations.description }}'
- name: 'slack'
slack_configs:
- channel: '#warnings'
send_resolved: true
- name: 'pagerduty'
pagerduty_configs:
- service_key: 'YOUR_PAGERDUTY_KEY'
severity: critical
inhibit_rules:
- source_match:
severity: 'critical'
target_match:
severity: 'warning'
equal: ['alertname', 'instance']
알림 규칙
# rules.yml
groups:
- name: node_alerts
rules:
- alert: HighCPUUsage
expr: 100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
for: 5m
labels:
severity: warning
annotations:
summary: "High CPU usage detected"
description: "CPU usage is above 80% for 5 minutes"
- alert: HighMemoryUsage
expr: (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100 > 90
for: 5m
labels:
severity: critical
annotations:
summary: "High memory usage detected"
description: "Memory usage is above 90% for 5 minutes"
- alert: DiskSpaceLow
expr: (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) * 100 < 10
for: 5m
labels:
severity: warning
annotations:
summary: "Low disk space"
description: "Disk space is below 10%"
- alert: InstanceDown
expr: up == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Instance is down"
description: "{{ $labels.instance }} has been down for more than 1 minute"
📊 Grafana
설치
# Docker
docker run -d \
--name grafana \
-p 3000:3000 \
-e GF_SECURITY_ADMIN_PASSWORD=admin \
-v grafana-storage:/var/lib/grafana \
grafana/grafana
# Kubernetes
helm install grafana grafana/grafana
데이터소스 설정
# datasources.yml
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
url: http://prometheus:9090
access: proxy
isDefault: true
- name: Loki
type: loki
url: http://loki:3100
access: proxy
대시보드
{
"dashboard": {
"title": "Node Exporter Full",
"panels": [
{
"title": "CPU Usage",
"type": "graph",
"targets": [
{
"expr": "100 - (avg by(instance) (irate(node_cpu_seconds_total{mode=\"idle\"}[5m])) * 100)",
"legendFormat": "{{instance}}"
}
]
},
{
"title": "Memory Usage",
"type": "graph",
"targets": [
{
"expr": "(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100",
"legendFormat": "{{instance}}"
}
]
}
]
}
}
📋 체크리스트
- Prometheus 설치
- 메트릭 수집 설정
- 알림 규칙 작성
- Alertmanager 설정
- Grafana 설치
- 데이터소스 연결
- 대시보드 생성
- 알림 채널 설정
- SLA 모니터링
- 장기 저장 설정
🔗 관련 노트
- 03-05-모니터링-Prometheus-Grafana — Kubernetes 모니터링
- 02-05-로그-집계 — 로그 수집
- 03-03-SRE-원칙 — SLO/SLI
마지막 업데이트: 2026-06-01