본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.
본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 11. 4. · 12 Views
Prometheus 트러블슈팅 완벽 가이드
Prometheus 모니터링 시스템에서 자주 발생하는 문제들과 해결 방법을 다룹니다. 메트릭 수집 실패, 쿼리 성능 문제, 저장소 관리 등 실무에서 겪는 이슈들을 코드로 해결합니다.
들어가며
이 글에서는 Prometheus 트러블슈팅 완벽 가이드에 대해 상세히 알아보겠습니다. 총 12가지 주요 개념을 다루며, 각각의 개념에 대한 설명과 실제 코드 예제를 함께 제공합니다.
목차
- 메트릭_수집_실패_디버깅
- 높은_카디널리티_문제_해결
- 쿼리_성능_최적화
- 디스크_공간_부족_모니터링
- 메트릭_만료_시간_설정
- 스크랩_타임아웃_조정
- 메트릭_이름_충돌_해결
- 레이트_계산_오류_수정
- 메모리_부족_문제_진단
- Alert_규칙_테스트
- 서비스_디스커버리_실패_처리
- 중복_메트릭_제거
1. 메트릭 수집 실패 디버깅
개요
Prometheus가 타겟에서 메트릭을 수집하지 못할 때 상태를 확인하고 재시도 로직을 구현하는 방법입니다.
코드 예제
from prometheus_client import Counter, Gauge
import requests
scrape_errors = Counter('scrape_errors_total', 'Total scrape errors')
target_up = Gauge('target_up', 'Target availability', ['target'])
def check_target(url):
try:
response = requests.get(f"{url}/metrics", timeout=5)
target_up.labels(target=url).set(1)
return response.text
except Exception as e:
scrape_errors.inc()
target_up.labels(target=url).set(0)
print(f"Scrape failed: {e}")
설명
타겟의 메트릭 엔드포인트를 호출하고 성공/실패 여부를 메트릭으로 기록합니다. 타임아웃과 예외 처리로 안정성을 확보합니다.
2. 높은 카디널리티 문제 해결
개요
레이블이 너무 많아 메모리 사용량이 증가하는 문제를 해결하기 위해 레이블을 제한하는 방법입니다.
코드 예제
from prometheus_client import Counter
import hashlib
request_counter = Counter('http_requests_total',
'HTTP requests',
['method', 'status', 'endpoint_hash'])
def record_request(method, status, endpoint):
# 엔드포인트를 해시로 변환하여 카디널리티 감소
endpoint_hash = hashlib.md5(endpoint.encode()).hexdigest()[:8]
request_counter.labels(
method=method,
status=status,
endpoint_hash=endpoint_hash
).inc()
설명
URL 경로를 해시값으로 변환하여 무한히 증가하는 레이블 값을 제한합니다. 이를 통해 메모리 사용량을 크게 줄일 수 있습니다.
3. 쿼리 성능 최적화
개요
PromQL 쿼리가 느릴 때 시간 범위와 스텝을 조정하여 성능을 개선하는 방법입니다.
코드 예제
from prometheus_api_client import PrometheusConnect
prom = PrometheusConnect(url="http://localhost:9090")
# 비효율적인 쿼리
# result = prom.custom_query_range(
# query="rate(http_requests_total[5m])",
# start_time="2025-01-01T00:00:00Z",
# end_time="2025-01-02T00:00:00Z",
# step="1s" # 너무 작은 스텝
# )
# 최적화된 쿼리
result = prom.custom_query_range(
query="rate(http_requests_total[5m])",
start_time="2025-01-01T00:00:00Z",
end_time="2025-01-02T00:00:00Z",
step="60s" # 적절한 스텝
)
설명
쿼리의 스텝 크기를 적절히 조정하면 데이터 포인트 수가 줄어들어 쿼리 성능이 크게 향상됩니다. 1초에서 60초로 변경하면 60배 빨라집니다.
4. 디스크 공간 부족 모니터링
개요
Prometheus 저장소의 디스크 사용량을 모니터링하고 임계치를 초과하면 알림을 보내는 방법입니다.
코드 예제
from prometheus_client import Gauge
import shutil
disk_usage = Gauge('prometheus_disk_usage_bytes',
'Disk usage in bytes',
['path'])
disk_usage_percent = Gauge('prometheus_disk_usage_percent',
'Disk usage percentage',
['path'])
def monitor_disk(path='/var/lib/prometheus'):
total, used, free = shutil.disk_usage(path)
disk_usage.labels(path=path).set(used)
disk_usage_percent.labels(path=path).set((used/total)*100)
if (used/total) > 0.85:
print(f"WARNING: Disk usage above 85% at {path}")
설명
디스크 사용량을 바이트와 퍼센트로 측정하여 메트릭으로 기록합니다. 85% 이상일 때 경고를 출력합니다.
5. 메트릭 만료 시간 설정
개요
오래된 시계열 데이터를 자동으로 삭제하여 저장 공간을 확보하는 retention 설정 방법입니다.
코드 예제
# prometheus.yml 설정
storage_config = """
global:
scrape_interval: 15s
evaluation_interval: 15s
storage:
tsdb:
retention.time: 15d
retention.size: 50GB
scrape_configs:
- job_name: 'my_app'
static_configs:
- targets: ['localhost:8000']
"""
# 설정 검증 함수
def validate_retention(retention_time, retention_size):
assert retention_time.endswith('d') or retention_time.endswith('h')
assert retention_size.endswith('GB') or retention_size.endswith('MB')
print("Retention policy validated")
설명
데이터 보관 기간을 15일 또는 50GB로 제한하여 자동으로 오래된 데이터를 삭제합니다. 두 조건 중 먼저 도달하는 기준이 적용됩니다.
6. 스크랩 타임아웃 조정
개요
타겟 응답이 느릴 때 스크랩 타임아웃을 조정하여 수집 실패를 방지하는 방법입니다.
코드 예제
# prometheus.yml 설정
scrape_config = """
scrape_configs:
- job_name: 'slow_service'
scrape_interval: 30s
scrape_timeout: 25s # interval보다 작아야 함
static_configs:
- targets: ['slow-api:8080']
"""
def validate_scrape_config(interval, timeout):
interval_sec = int(interval.rstrip('s'))
timeout_sec = int(timeout.rstrip('s'))
if timeout_sec >= interval_sec:
raise ValueError("Timeout must be less than interval")
print(f"Valid config: {timeout_sec}s timeout, {interval_sec}s interval")
설명
스크랩 타임아웃은 반드시 스크랩 간격보다 작아야 합니다. 느린 서비스의 경우 둘 다 늘려서 안정적으로 수집합니다.
7. 메트릭 이름 충돌 해결
개요
여러 서비스에서 같은 이름의 메트릭을 사용할 때 레이블로 구분하는 방법입니다.
코드 예제
from prometheus_client import Counter, CollectorRegistry
# 각 서비스마다 별도의 레지스트리 사용
registry_a = CollectorRegistry()
registry_b = CollectorRegistry()
requests_a = Counter('http_requests_total',
'Requests from service A',
['service'],
registry=registry_a)
requests_a.labels(service='api-gateway').inc()
requests_b = Counter('http_requests_total',
'Requests from service B',
['service'],
registry=registry_b)
requests_b.labels(service='user-service').inc()
설명
별도의 레지스트리를 사용하거나 service 레이블로 구분하여 메트릭 이름 충돌을 방지합니다. 각 서비스를 독립적으로 관리할 수 있습니다.
8. 레이트 계산 오류 수정
개요
rate() 함수 사용 시 시간 범위를 잘못 설정하여 부정확한 값이 나오는 문제를 해결하는 방법입니다.
코드 예제
# 잘못된 예: 시간 범위가 너무 짧음
# rate(http_requests_total[30s]) # scrape_interval이 15s일 때
# 올바른 예: 최소 2배 이상의 시간 범위 사용
correct_query = """
rate(http_requests_total[1m]) # scrape_interval이 15s일 때 적절
"""
def validate_rate_range(scrape_interval_sec, rate_range_sec):
min_range = scrape_interval_sec * 2
if rate_range_sec < min_range:
raise ValueError(
f"Rate range should be at least {min_range}s "
f"(2x scrape interval)"
)
print("Rate range validated")
설명
rate() 함수의 시간 범위는 스크랩 간격의 최소 2배 이상이어야 정확한 값을 얻을 수 있습니다. 15초 간격이면 최소 30초 이상 설정합니다.
9. 메모리 부족 문제 진단
개요
Prometheus가 메모리를 과도하게 사용할 때 원인을 파악하고 청크 크기를 조정하는 방법입니다.
코드 예제
from prometheus_client import Gauge
import psutil
memory_usage = Gauge('process_memory_bytes', 'Memory usage')
active_series = Gauge('prometheus_active_series', 'Active time series')
def diagnose_memory():
process = psutil.Process()
mem_bytes = process.memory_info().rss
memory_usage.set(mem_bytes)
# 시계열당 메모리 추정
series_count = 1000000 # API로 조회
active_series.set(series_count)
bytes_per_series = mem_bytes / series_count
print(f"Memory per series: {bytes_per_series:.2f} bytes")
if bytes_per_series > 3000:
print("Consider reducing label cardinality")
설명
프로세스의 메모리 사용량을 시계열 개수로 나눠 시계열당 메모리를 계산합니다. 3KB 이상이면 레이블 수를 줄여야 합니다.
10. Alert 규칙 테스트
개요
Prometheus 알림 규칙이 제대로 작동하는지 테스트하고 검증하는 방법입니다.
코드 예제
import requests
import time
def test_alert_rule(prom_url, alert_name):
# 알림이 발생하도록 메트릭 생성
# (실제로는 애플리케이션에서 메트릭 발생)
time.sleep(65) # evaluation_interval보다 길게 대기
# 알림 상태 확인
response = requests.get(f"{prom_url}/api/v1/alerts")
alerts = response.json()['data']['alerts']
alert_found = any(a['labels']['alertname'] == alert_name
for a in alerts)
assert alert_found, f"Alert {alert_name} not triggered"
print(f"Alert {alert_name} working correctly")
설명
알림을 트리거할 조건을 만들고 evaluation_interval 이후에 알림 API를 확인하여 제대로 작동하는지 검증합니다.
11. 서비스 디스커버리 실패 처리
개요
Kubernetes 서비스 디스커버리가 실패할 때 fallback 타겟을 사용하는 방법입니다.
코드 예제
from kubernetes import client, config
from prometheus_client import Gauge
discovery_errors = Gauge('service_discovery_errors', 'Discovery errors')
def discover_targets_with_fallback():
try:
config.load_incluster_config()
v1 = client.CoreV1Api()
pods = v1.list_pod_for_all_namespaces(watch=False)
targets = [f"{pod.status.pod_ip}:8080"
for pod in pods.items
if pod.status.phase == 'Running']
discovery_errors.set(0)
return targets
except Exception as e:
discovery_errors.set(1)
# Fallback to static targets
return ['fallback-1:8080', 'fallback-2:8080']
설명
Kubernetes API 호출이 실패하면 미리 정의된 정적 타겟 목록을 사용합니다. 서비스 디스커버리 오류를 메트릭으로 기록합니다.
12. 중복 메트릭 제거
개요
같은 메트릭이 여러 번 등록되어 발생하는 오류를 방지하는 방법입니다.
코드 예제
from prometheus_client import Counter, CollectorRegistry, REGISTRY
def get_or_create_counter(name, description, labelnames=None):
# 이미 등록된 메트릭 확인
for collector in list(REGISTRY._collector_to_names.keys()):
if hasattr(collector, '_name') and collector._name == name:
return collector
# 새로 생성
return Counter(
name,
description,
labelnames=labelnames or []
)
# 안전하게 메트릭 생성
requests = get_or_create_counter('http_requests_total',
'Total requests',
['method'])
설명
메트릭을 생성하기 전에 레지스트리를 확인하여 이미 존재하면 재사용하고, 없으면 새로 생성합니다. 중복 등록 오류를 방지합니다.
마치며
이번 글에서는 Prometheus 트러블슈팅 완벽 가이드에 대해 알아보았습니다. 총 12가지 개념을 다루었으며, 각각의 사용법과 예제를 살펴보았습니다.
관련 태그
#Prometheus #Monitoring #Troubleshooting #Metrics #Performance
이 카드뉴스가 포함된 코스
댓글 (0)
함께 보면 좋은 카드 뉴스
Helm 마이크로서비스 패키징 완벽 가이드
Kubernetes 환경에서 마이크로서비스를 효율적으로 패키징하고 배포하는 Helm의 핵심 기능을 실무 중심으로 학습합니다. Chart 생성부터 릴리스 관리까지 체계적으로 다룹니다.
관찰 가능한 마이크로서비스 완벽 가이드
마이크로서비스 환경에서 시스템의 상태를 실시간으로 관찰하고 모니터링하는 방법을 배웁니다. Resilience4j, Zipkin, Prometheus, Grafana, EFK 스택을 활용하여 안정적이고 관찰 가능한 시스템을 구축하는 실전 가이드입니다.
Grafana 대시보드 완벽 가이드
실시간 모니터링의 핵심, Grafana 대시보드를 처음부터 끝까지 배워봅니다. Prometheus 연동부터 알람 설정까지, 초급 개발자도 쉽게 따라할 수 있는 실전 가이드입니다.
Prometheus 메트릭 수집 완벽 가이드
Spring Boot 애플리케이션의 메트릭을 Prometheus로 수집하고 모니터링하는 방법을 배웁니다. Actuator 설정부터 PromQL 쿼리까지 실무에 필요한 모든 내용을 다룹니다.
스프링 관찰 가능성 완벽 가이드
Spring Boot 3.x의 Observation API를 활용한 애플리케이션 모니터링과 추적 방법을 초급 개발자 눈높이에서 쉽게 설명합니다. 실무에서 바로 적용할 수 있는 메트릭 수집과 분산 추적 기법을 다룹니다.