현대의 분산 시스템과 마이크로서비스 환경에서 시스템 모니터링은 더 이상 선택이 아닌 필수가 되었습니다.
서비스의 안정성과 성능을 보장하기 위해서는 실시간 메트릭 수집과 효과적인 시각화가 반드시 필요합니다.
이 글에서는 업계 표준으로 자리잡은 Prometheus와 Grafana를 활용하여 완전한 시스템 모니터링 환경을 구축하는 방법을 단계별로 알아보겠습니다.
Prometheus와 Grafana 모니터링 스택 개요
Prometheus는 SoundCloud에서 개발된 오픈소스 모니터링 시스템으로, 시계열 데이터베이스와 메트릭 수집 기능을 제공합니다.
풀(Pull) 방식으로 메트릭을 수집하며, 강력한 쿼리 언어인 PromQL을 통해 데이터를 조회할 수 있습니다.
Grafana는 다양한 데이터소스를 지원하는 시각화 플랫폼으로, Prometheus와 완벽하게 연동되어 아름다운 대시보드를 제공합니다.
이 두 도구를 조합하면 메트릭 수집부터 시각화, 알림까지 완전한 모니터링 파이프라인을 구축할 수 있습니다.
특히 Kubernetes 환경에서의 컨테이너 모니터링과 마이크로서비스 관찰성(Observability) 확보에 매우 효과적입니다.
Prometheus 설치 및 기본 설정
Prometheus 설치는 여러 방법으로 가능하지만, Docker를 활용한 방법이 가장 간편합니다.
먼저 Prometheus 설정 파일을 작성해보겠습니다.
# prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- "alert_rules.yml"
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node-exporter'
static_configs:
- targets: ['localhost:9100']
- job_name: 'application'
static_configs:
- targets: ['localhost:8080']
metrics_path: '/actuator/prometheus'
scrape_interval: 5s
Docker를 사용하여 Prometheus를 실행하는 명령어는 다음과 같습니다:
docker run -d \
--name prometheus \
-p 9090:9090 \
-v $(pwd)/prometheus.yml:/etc/prometheus/prometheus.yml \
prom/prometheus:latest \
--config.file=/etc/prometheus/prometheus.yml \
--storage.tsdb.path=/prometheus \
--web.console.libraries=/etc/prometheus/console_libraries \
--web.console.templates=/etc/prometheus/consoles \
--web.enable-lifecycle
설치가 완료되면 http://localhost:9090
에서 Prometheus 웹 인터페이스에 접근할 수 있습니다.
Status > Targets 메뉴에서 설정된 타겟들의 상태를 확인할 수 있으며, 모든 타겟이 "UP" 상태여야 정상적으로 메트릭을 수집하고 있다는 의미입니다.
Node Exporter를 통한 시스템 메트릭 수집
시스템 레벨의 메트릭을 수집하기 위해서는 Node Exporter가 필요합니다.
Node Exporter는 CPU, 메모리, 디스크, 네트워크 등 하드웨어와 OS 관련 메트릭을 제공합니다.
# 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
cd node_exporter-1.6.1.linux-amd64
./node_exporter
Docker를 사용하는 경우 더욱 간단하게 실행할 수 있습니다:
docker run -d \
--name node-exporter \
-p 9100:9100 \
-v "/proc:/host/proc:ro" \
-v "/sys:/host/sys:ro" \
-v "/:/rootfs:ro" \
--pid="host" \
prom/node-exporter:latest \
--path.procfs=/host/proc \
--path.rootfs=/rootfs \
--path.sysfs=/host/sys \
--collector.filesystem.mount-points-exclude="^/(sys|proc|dev|host|etc)($$|/)"
Node Exporter가 정상적으로 실행되면 http://localhost:9100/metrics
에서 수집되는 메트릭을 확인할 수 있습니다.
주요 메트릭으로는 node_cpu_seconds_total
, node_memory_MemTotal_bytes
, node_filesystem_size_bytes
등이 있습니다.
애플리케이션 메트릭 노출 설정
실제 서비스 모니터링을 위해서는 애플리케이션 레벨의 메트릭이 중요합니다.
Spring Boot 애플리케이션을 예로 들어 Prometheus 메트릭 노출 설정을 살펴보겠습니다.
<!-- pom.xml -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
application.yml 설정:
management:
endpoints:
web:
exposure:
include: prometheus,health,info,metrics
endpoint:
prometheus:
enabled: true
metrics:
export:
prometheus:
enabled: true
커스텀 메트릭을 추가하는 Java 코드 예시:
@RestController
@Component
public class MetricsController {
private final Counter requestCounter;
private final Timer requestTimer;
private final Gauge activeUsers;
public MetricsController(MeterRegistry meterRegistry) {
this.requestCounter = Counter.builder("api_requests_total")
.description("Total API requests")
.tag("endpoint", "all")
.register(meterRegistry);
this.requestTimer = Timer.builder("api_request_duration")
.description("API request duration")
.register(meterRegistry);
this.activeUsers = Gauge.builder("active_users")
.description("Current active users")
.register(meterRegistry, this, MetricsController::getActiveUserCount);
}
@GetMapping("/api/data")
public ResponseEntity<String> getData() {
return Timer.Sample.start()
.stop(requestTimer)
.recordCallable(() -> {
requestCounter.increment();
return ResponseEntity.ok("Data response");
});
}
private double getActiveUserCount() {
// 실제 활성 사용자 수 계산 로직
return 150.0;
}
}
이렇게 설정하면 /actuator/prometheus
엔드포인트에서 애플리케이션 메트릭을 확인할 수 있습니다.
비즈니스 로직과 관련된 메트릭들을 통해 더욱 의미있는 모니터링이 가능해집니다.
Grafana 설치 및 Prometheus 데이터소스 연동
Grafana 설치도 Docker를 활용하면 매우 간편합니다:
docker run -d \
--name grafana \
-p 3000:3000 \
-e "GF_SECURITY_ADMIN_PASSWORD=admin123" \
-v grafana-storage:/var/lib/grafana \
grafana/grafana:latest
Grafana가 시작되면 http://localhost:3000
에 접속하여 admin/admin123 계정으로 로그인할 수 있습니다.
Prometheus 데이터소스를 추가하는 단계는 다음과 같습니다:
- Configuration > Data Sources 메뉴 선택
- "Add data source" 클릭
- Prometheus 선택
- URL에
http://localhost:9090
입력 (Docker 네트워크 사용시 컨테이너명 사용) - "Save & Test" 클릭하여 연결 확인
데이터소스 연동이 완료되면 Explore 메뉴에서 PromQL 쿼리를 테스트해볼 수 있습니다.
기본적인 쿼리 예시로는 up
, node_cpu_seconds_total
, prometheus_tsdb_head_samples
등을 사용할 수 있습니다.
효과적인 대시보드 구성과 시각화
시스템 모니터링을 위한 대시보드는 계층적으로 구성하는 것이 효과적입니다.
인프라스트럭처 레벨, 애플리케이션 레벨, 비즈니스 레벨로 나누어 각각의 관점에서 중요한 메트릭을 시각화해야 합니다.
시스템 개요 대시보드의 주요 패널 구성:
{
"dashboard": {
"title": "System Overview",
"panels": [
{
"title": "CPU Usage",
"type": "stat",
"targets": [
{
"expr": "100 - (avg(rate(node_cpu_seconds_total{mode=\"idle\"}[5m])) * 100)"
}
]
},
{
"title": "Memory Usage",
"type": "stat",
"targets": [
{
"expr": "(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100"
}
]
},
{
"title": "Disk Usage",
"type": "bargauge",
"targets": [
{
"expr": "100 - ((node_filesystem_avail_bytes * 100) / node_filesystem_size_bytes)"
}
]
}
]
}
}
애플리케이션 모니터링을 위한 중요한 메트릭들:
- 처리량(Throughput):
rate(http_requests_total[5m])
- 응답시간(Response Time):
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))
- 에러율(Error Rate):
rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m])
- 동시 접속자(Concurrent Users):
active_users
비즈니스 메트릭을 포함한 대시보드는 경영진과 개발팀 모두에게 유용한 정보를 제공합니다.
일일 활성 사용자, 매출, 주요 기능 사용률 등을 시각화하여 기술적 메트릭과 비즈니스 성과를 연결할 수 있습니다.
PromQL 쿼리 최적화 및 활용법
PromQL(Prometheus Query Language)은 강력한 시계열 데이터 쿼리 언어입니다.
효과적인 모니터링을 위해서는 적절한 PromQL 쿼리 작성이 필수적입니다.
기본적인 PromQL 함수들과 활용 예시:
# Rate 함수 - 초당 증가율 계산
rate(http_requests_total[5m])
# Increase 함수 - 특정 기간 동안의 증가량
increase(http_requests_total[1h])
# Histogram_quantile - 분위수 계산
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))
# Avg_over_time - 시간 범위의 평균값
avg_over_time(cpu_usage_percent[1h])
# Delta - 시작과 끝의 차이
delta(node_memory_MemFree_bytes[1h])
복잡한 쿼리 최적화 예시:
# 비효율적인 쿼리
sum(rate(http_requests_total[5m])) by (instance)
# 최적화된 쿼리 (레이블 필터링 먼저 적용)
sum(rate(http_requests_total{job="web-server"}[5m])) by (instance)
# 서비스별 에러율 계산
sum(rate(http_requests_total{status=~"5.."}[5m])) by (service) /
sum(rate(http_requests_total[5m])) by (service) * 100
성능 최적화를 위한 PromQL 모범 사례:
- 레이블 필터를 가능한 한 앞쪽에 배치
- 불필요한 메트릭은 recording rule로 미리 계산
- 긴 시간 범위 쿼리는 subquery 활용
- 정규표현식보다는 정확한 레이블 매칭 사용
알림 규칙 설정과 Alertmanager 연동
효과적인 모니터링을 위해서는 적절한 알림 설정이 필수입니다.
Prometheus의 알림 규칙을 통해 임계값 기반 알림을 설정할 수 있습니다.
알림 규칙 파일 예시 (alert_rules.yml):
groups:
- name: system_alerts
rules:
- alert: HighCPUUsage
expr: 100 - (avg(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
for: 5m
labels:
severity: warning
team: infrastructure
annotations:
summary: "High CPU usage detected"
description: "CPU usage is above 80% for more than 5 minutes"
- alert: HighMemoryUsage
expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 > 90
for: 2m
labels:
severity: critical
team: infrastructure
annotations:
summary: "High memory usage detected"
description: "Memory usage is above 90% for more than 2 minutes"
- alert: ServiceDown
expr: up == 0
for: 1m
labels:
severity: critical
team: platform
annotations:
summary: "Service is down"
description: "Service {{ $labels.instance }} has been down for more than 1 minute"
Alertmanager 설정 파일 (alertmanager.yml):
global:
smtp_smarthost: 'smtp.gmail.com:587'
smtp_from: 'alerts@yourcompany.com'
smtp_auth_username: 'alerts@yourcompany.com'
smtp_auth_password: 'your-app-password'
route:
group_by: ['alertname', 'team']
group_wait: 10s
group_interval: 10s
repeat_interval: 1h
receiver: 'default'
routes:
- match:
severity: critical
receiver: 'critical-alerts'
- match:
team: infrastructure
receiver: 'infra-team'
receivers:
- name: 'default'
email_configs:
- to: 'devops@yourcompany.com'
subject: '[Alert] {{ .GroupLabels.alertname }}'
body: |
{{ range .Alerts }}
Alert: {{ .Annotations.summary }}
Description: {{ .Annotations.description }}
{{ end }}
- name: 'critical-alerts'
email_configs:
- to: 'oncall@yourcompany.com'
subject: '[CRITICAL] {{ .GroupLabels.alertname }}'
slack_configs:
- api_url: 'YOUR_SLACK_WEBHOOK_URL'
channel: '#alerts'
title: 'Critical Alert'
text: '{{ range .Alerts }}{{ .Annotations.summary }}{{ end }}'
Docker Compose를 활용한 전체 스택 배포:
version: '3.8'
services:
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- ./alert_rules.yml:/etc/prometheus/alert_rules.yml
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.enable-lifecycle'
- '--alertmanager.url=http://alertmanager:9093'
alertmanager:
image: prom/alertmanager:latest
ports:
- "9093:9093"
volumes:
- ./alertmanager.yml:/etc/alertmanager/alertmanager.yml
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin123
volumes:
- grafana-storage:/var/lib/grafana
node-exporter:
image: prom/node-exporter:latest
ports:
- "9100:9100"
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.rootfs=/rootfs'
- '--path.sysfs=/host/sys'
volumes:
grafana-storage:
Kubernetes 환경에서의 모니터링 구축
Kubernetes 환경에서는 Prometheus Operator를 활용하여 더욱 효과적인 모니터링 환경을 구축할 수 있습니다.
Helm을 사용한 kube-prometheus-stack 설치:
# Helm repository 추가
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
# kube-prometheus-stack 설치
helm install monitoring prometheus-community/kube-prometheus-stack \
--namespace monitoring \
--create-namespace \
--set prometheus.prometheusSpec.serviceMonitorSelectorNilUsesHelmValues=false \
--set prometheus.prometheusSpec.podMonitorSelectorNilUsesHelmValues=false
애플리케이션 모니터링을 위한 ServiceMonitor 설정:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: app-monitor
namespace: monitoring
labels:
app: my-application
spec:
selector:
matchLabels:
app: my-application
endpoints:
- port: metrics
path: /actuator/prometheus
interval: 30s
Pod 레벨 메트릭을 위한 PodMonitor 설정:
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
name: pod-monitor
namespace: monitoring
spec:
selector:
matchLabels:
app: my-application
podMetricsEndpoints:
- port: metrics
path: /metrics
Kubernetes 환경에서는 다음과 같은 핵심 메트릭들을 모니터링해야 합니다:
- 클러스터 리소스: CPU, 메모리, 스토리지 사용률
- Pod 상태: Ready, Running, Failed Pod 수
- 네트워크 트래픽: 인그레스/이그레스 트래픽량
- 애플리케이션 메트릭: 비즈니스 로직 관련 메트릭
성능 최적화 및 스케일링 전략
대규모 환경에서 Prometheus와 Grafana를 운영할 때는 성능 최적화가 중요합니다.
Prometheus 성능 최적화 방법:
# prometheus.yml 최적화 설정
global:
scrape_interval: 30s # 수집 간격 조정
evaluation_interval: 30s
external_labels:
cluster: 'production'
region: 'us-west-2'
# 스토리지 최적화
storage:
tsdb:
retention.time: 15d
retention.size: 10GB
wal-compression: true
# 쿼리 성능 최적화
query:
max-concurrency: 20
timeout: 2m
Recording Rules를 통한 쿼리 사전 계산:
groups:
- name: performance_rules
interval: 30s
rules:
- record: instance:node_cpu_utilization:rate5m
expr: 100 - (avg(rate(node_cpu_seconds_total{mode="idle"}[5m])) by (instance) * 100)
- record: instance:node_memory_utilization:ratio
expr: 1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)
- record: service:http_request_rate:rate5m
expr: sum(rate(http_requests_total[5m])) by (service)
Grafana 성능 최적화 설정:
# grafana.ini
[database]
# 데이터베이스 최적화
max_open_conn = 300
max_idle_conn = 300
conn_max_lifetime = 14400
[dataproxy]
# 프록시 타임아웃 설정
timeout = 30
keep_alive_seconds = 30
[alerting]
# 알림 성능 최적화
execute_alerts = true
max_attempts = 3
대용량 환경을 위한 연합(Federation) 설정:
# 글로벌 Prometheus 설정
scrape_configs:
- job_name: 'federate'
scrape_interval: 15s
honor_labels: true
metrics_path: '/federate'
params:
'match[]':
- '{job=~"prometheus"}'
- '{__name__=~"job:.*"}'
- '{__name__=~"instance:.*"}'
static_configs:
- targets:
- 'prometheus-us-west:9090'
- 'prometheus-eu-west:9090'
- 'prometheus-ap-northeast:9090'
보안 고려사항 및 베스트 프랙티스
프로덕션 환경에서 모니터링 시스템을 안전하게 운영하기 위한 보안 설정이 필요합니다.
Prometheus 보안 설정:
# prometheus.yml
global:
external_labels:
cluster: 'production'
# Basic Authentication 설정
basic_auth_users:
admin: $2b$12$hNf2lSsxfm0.i4a.1kVpSOVyBCfIB51VRjgBUyv6kdnyTlgWj81Ay
# TLS 설정
tls_server_config:
cert_file: /etc/prometheus/prometheus.crt
key_file: /etc/prometheus/prometheus.key
Grafana 보안 강화:
# grafana.ini
[security]
admin_user = admin
admin_password = $__env{GF_SECURITY_ADMIN_PASSWORD}
secret_key = $__env{GF_SECURITY_SECRET_KEY}
disable_gravatar = true
cookie_secure = true
cookie_samesite = strict
[auth]
disable_login_form = false
disable_signout_menu = false
[auth.ldap]
enabled = true
config_file = /etc/grafana/ldap.toml
네트워크 보안을 위한 방화벽 설정:
# Prometheus 포트 제한
sudo ufw allow from 10.0.0.0/8 to any port 9090
sudo ufw allow from 172.16.0.0/12 to any port 9090
# Grafana 포트 제한
sudo ufw allow from 10.0.0.0/8 to any port 3000
sudo ufw deny 3000
데이터 백업 및 복구 전략:
#!/bin/bash
# Prometheus 데이터 백업 스크립트
BACKUP_DIR="/backup/prometheus"
PROMETHEUS_DATA="/var/lib/prometheus"
DATE=$(date +%Y%m%d_%H%M%S)
# 스냅샷 생성
curl -XPOST http://localhost:9090/api/v1/admin/tsdb/snapshot
# 데이터 압축 및 백업
tar -czf ${BACKUP_DIR}/prometheus_${DATE}.tar.gz ${PROMETHEUS_DATA}
# 7일 이상 된 백업 파일 삭제
find ${BACKUP_DIR} -name "prometheus_*.tar.gz" -mtime +7 -delete
트러블슈팅 및 문제 해결 가이드
모니터링 시스템 운영 중 발생할 수 있는 일반적인 문제들과 해결 방법을 정리했습니다.
Prometheus 메트릭 수집 문제:
# 타겟 상태 확인
curl http://localhost:9090/api/v1/targets
# 설정 파일 유효성 검사
promtool check config prometheus.yml
# 알림 규칙 검증
promtool check rules alert_rules.yml
일반적인 PromQL 쿼리 오류와 해결책:
# 잘못된 쿼리 - 시간 범위 없음
rate(http_requests_total)
# 올바른 쿼리 - 시간 범위 포함
rate(http_requests_total[5m])
# 잘못된 쿼리 - 존재하지 않는 레이블
http_requests_total{invalid_label="value"}
# 올바른 쿼리 - 유효한 레이블만 사용
http_requests_total{method="GET",status="200"}
Grafana 성능 문제 해결:
-- 느린 쿼리 식별
SELECT * FROM grafana.log
WHERE level = 'error'
AND message LIKE '%timeout%'
ORDER BY time DESC;
메모리 사용량 최적화:
# Prometheus 메모리 사용량 확인
curl http://localhost:9090/api/v1/status/tsdb
# 불필요한 메트릭 제거
retention_policies:
- metric_name: "high_cardinality_metric"
retention: "1h"
마무리 및 추가 학습 자료
Prometheus와 Grafana를 활용한 시스템 모니터링 구축은 현대적인 DevOps 환경에서 필수적인 역량입니다.
이 글에서 다룬 내용을 바탕으로 여러분의 인프라스트럭처에 맞는 모니터링 솔루션을 구축할 수 있을 것입니다.
성공적인 모니터링 시스템 구축을 위한 핵심 포인트를 요약하면 다음과 같습니다:
1. 계층적 메트릭 설계: 인프라스트럭처, 애플리케이션, 비즈니스 레벨로 나누어 체계적인 메트릭 수집 전략을 수립해야 합니다.
2. 적절한 알림 정책: 노이즈를 최소화하면서도 중요한 이벤트를 놓치지 않는 균형잡힌 알림 규칙 설정이 중요합니다.
3. 성능 최적화: 대용량 환경에서는 Recording Rules, Federation, 적절한 Retention 정책을 통해 시스템 성능을 최적화해야 합니다.
4. 보안 고려: 프로덕션 환경에서는 인증, 암호화, 네트워크 접근 제어 등 보안 요소를 반드시 고려해야 합니다.
모니터링은 단순히 도구를 설치하는 것이 아니라, 조직의 운영 문화와 프로세스를 개선하는 중요한 요소입니다.
지속적인 개선과 팀 간의 협업을 통해 더욱 효과적인 모니터링 환경을 구축할 수 있습니다.
추가 학습 자료 및 커뮤니티
더 깊이 있는 학습을 위한 추천 자료들:
공식 문서 및 가이드:
- Prometheus 공식 문서: https://prometheus.io/docs/
- Grafana 공식 문서: https://grafana.com/docs/
- PromQL 튜토리얼: https://prometheus.io/docs/prometheus/latest/querying/basics/
실습 환경 및 예제:
- Prometheus Demo 사이트에서 실제 환경 체험
- Grafana Play 환경에서 대시보드 구성 연습
- GitHub의 오픈소스 모니터링 프로젝트 참여
커뮤니티 및 지원:
- CNCF Slack의 #prometheus, #grafana 채널
- Stack Overflow의 prometheus, grafana 태그
- 국내 DevOps 커뮤니티 모임 참여
모니터링 시스템은 한 번 구축하고 끝나는 것이 아니라, 지속적으로 개선하고 발전시켜야 하는 살아있는 시스템입니다.
여러분의 조직과 서비스에 맞는 최적의 모니터링 환경을 구축하시기 바랍니다.
'DevOps' 카테고리의 다른 글
Nginx 리버스 프록시 완벽 가이드 - 로드밸런싱부터 마이크로서비스 아키텍처까지 (0) | 2025.06.01 |
---|---|
Argo CD를 활용한 GitOps 구현: 쿠버네티스 자동 배포의 완벽 가이드 (0) | 2025.05.28 |
Helm과 Istio의 역할과 차이점: 쿠버네티스 환경에서의 필수 도구 완벽 가이드 (0) | 2025.05.28 |
Kubernetes 입문 가이드: 컨테이너 오케스트레이션의 모든 것 (0) | 2025.05.28 |
서버리스 아키텍처로 비용 효율적인 서비스 구축하기: 완벽한 가이드 (0) | 2025.05.25 |