개요
- EKS 에서 서빙 앱의 메트릭을 수집하고 Grafana 대시보드로 모니터링하는 구조를 정리
- 앱에서 Prometheus 메트릭 노출 → ServiceMonitor 로 수집 → Grafana 에서 시각화
- kubectl 로그 조회 실전 명령어
메트릭 수집 흐름
App (/metrics) → Prometheus (ServiceMonitor 로 scrape) → Grafana (PromQL 쿼리)
- 앱에서
/metrics 엔드포인트를 노출
- ServiceMonitor 가 Prometheus 에 scrape 대상 등록
- Grafana 에서 PromQL 로 대시보드 구성
앱에서 메트릭 노출 (Python)
prometheus_client 설치
pip install prometheus_client
메트릭 클래스 작성
- Counter (호출 수) 와 Histogram (레이턴시) 두 가지 기본 메트릭
import time
from prometheus_client import Counter, Histogram
class RequestMetrics:
def __init__(self, namespace: str = "app"):
self.request_total = Counter(
name=f"{namespace}_requests_total",
documentation="Total number of requests",
labelnames=["api_name", "status"],
)
self.request_latency = Histogram(
name=f"{namespace}_request_latency_seconds",
documentation="Request latency in seconds",
labelnames=["api_name"],
buckets=[0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0],
)
def start_timer(self) -> float:
return time.time()
def observe_request(self, api_name: str, start_time: float, status: str = "success"):
elapsed = time.time() - start_time
self.request_latency.labels(api_name=api_name).observe(elapsed)
self.request_total.labels(api_name=api_name, status=status).inc()
def observe_error(self, api_name: str, start_time: float):
self.observe_request(api_name=api_name, start_time=start_time, status="error")
/metrics 엔드포인트 등록 (FastAPI)
from fastapi import FastAPI
from prometheus_client import make_asgi_app
from metrics import RequestMetrics
app = FastAPI()
metrics = RequestMetrics(namespace="app")
metrics_app = make_asgi_app()
app.mount("/metrics", metrics_app)
사용 예시
@app.post("/search")
async def search(query: str):
start = metrics.start_timer()
try:
result = await do_search(query)
metrics.observe_request("search", start, "success")
return result
except Exception as e:
metrics.observe_error("search", start)
raise e
ServiceMonitor 등록
- Prometheus 가 앱의
/metrics 를 수집하도록 ServiceMonitor 리소스 생성
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: <app_name>
namespace: monitoring
labels:
release: prometheus-stack
spec:
namespaceSelector:
matchNames:
- <app_namespace>
selector:
matchLabels:
app: <app_name>-svc
endpoints:
- port: http
path: /metrics
interval: 30s
release: prometheus-stack : Prometheus 가 이 ServiceMonitor 를 인식하기 위한 label
- kube-prometheus-stack Helm release 이름과 매칭
- deployment repo 의 kustomization.yaml patches 에 추가하여 관리
Grafana 대시보드
- Import Dashboard 로 JSON 을 붙여넣어 생성
- 기본 패널 구성
| 패널 | PromQL | 단위 |
|---|
| Total QPS | sum(rate(app_requests_total{service="<svc>"}[5m])) | req/s |
| Requests/sec by API | sum(rate(app_requests_total{service="<svc>"}[5m])) by (api_name) | req/s |
| Error Rate (%) | 100 * sum(rate(..{status="error"}[5m])) by (api_name) / sum(rate(..[5m])) by (api_name) | percent |
| Latency p50/p90/p99 | histogram_quantile(0.9, sum(rate(..bucket[5m])) by (le)) | seconds |
| p90 by API | histogram_quantile(0.9, sum(rate(..bucket[5m])) by (le, api_name)) | seconds |
histogram_quantile(0.9,
sum(rate(app_request_latency_seconds_bucket{service="<app_name>-svc"}[5m])) by (le)
)
PushGateway (배치 메트릭)
- pull 방식이 어려운 배치 작업에서 push 로 메트릭 전송
from prometheus_client import CollectorRegistry, Counter, push_to_gateway
registry = CollectorRegistry()
counter = Counter(
"batch_processed_total",
"Total processed items",
registry=registry,
)
counter.inc(100)
push_to_gateway(
gateway="<pushgateway_endpoint>:9091",
job="batch_job_name",
registry=registry,
)
kubectl 로그 조회
기본 조회
kubectl get pods -n <namespace>
kubectl logs <pod_name> -n <namespace>
kubectl logs -f <pod_name> -n <namespace>
kubectl logs -l app=<app_name> -n <namespace>
유용한 옵션
kubectl logs <pod_name> -n <namespace> --tail=100
kubectl logs <pod_name> -n <namespace> --since=1h
kubectl logs <pod_name> -n <namespace> -p
kubectl logs <pod_name> -n <namespace> --timestamps=true
kubectl logs <pod_name> -n <namespace> -c <container_name>
에러 필터링
kubectl logs <pod_name> -n <namespace> --since=1h | grep -i error
트러블슈팅 순서
- Pod 상태 확인:
kubectl get pods -n <namespace>
- Pod 이벤트 확인:
kubectl describe pod <pod_name> -n <namespace>
- 현재 로그 확인:
kubectl logs <pod_name> --tail=100
- 이전 로그 확인 (재시작):
kubectl logs <pod_name> -p
- Pod 삭제 시 로그도 삭제됨 → 장기 보관 필요 시 Fluent-bit → CloudWatch Logs 사용
reference