핵심 요약
Observability는 더 이상 옵션이 아니다. 클라우드 네이티브 환경에서 디버깅·SLO·incident response의 baseline. 2026년 표준은 OpenTelemetry로 수집 + LGTM 스택으로 저장.
- Collector: OpenTelemetry Collector (단일 표준)
- Logs: Loki (cardinality 친화)
- Traces: Tempo (cost 친화)
- Metrics: Mimir 또는 Prometheus
- UI: Grafana
1. OpenTelemetry Collector — 중앙 수집
# otel-collector-config.yaml
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
prometheus:
config:
scrape_configs:
- job_name: kubernetes-pods
kubernetes_sd_configs:
- role: pod
processors:
memory_limiter:
check_interval: 1s
limit_mib: 1500
batch:
send_batch_size: 8192
timeout: 1s
transform:
metric_statements:
- context: datapoint
statements:
- replace_pattern(attributes["http.target"], "/api/users/\\d+", "/api/users/:id")
exporters:
loki:
endpoint: http://loki:3100/loki/api/v1/push
otlp/tempo:
endpoint: tempo:4317
prometheusremotewrite:
endpoint: http://mimir:9009/api/v1/push
service:
pipelines:
traces:
receivers: [otlp]
processors: [memory_limiter, batch]
exporters: [otlp/tempo]
logs:
receivers: [otlp]
processors: [memory_limiter, batch]
exporters: [loki]
metrics:
receivers: [otlp, prometheus]
processors: [memory_limiter, transform, batch]
exporters: [prometheusremotewrite]2. Loki — 로그
Loki는 인덱스를 라벨에만 (전문 인덱싱 없음). 비용 90% 저렴.
# loki-config.yaml
auth_enabled: false
server:
http_listen_port: 3100
schema_config:
configs:
- from: 2024-01-01
store: tsdb
object_store: s3
schema: v13
index:
prefix: index_
period: 24h
storage_config:
aws:
bucketnames: my-loki-storage
region: ap-northeast-2
limits_config:
retention_period: 90d
ingestion_rate_mb: 10로그 쿼리 (LogQL)
# 에러 로그만
{app="api"} |= "error"
# 5xx 응답
{app="api"} | json | status_code >= 500
# 요청 비율
rate({app="api"}[5m])3. Tempo — Trace
Tempo는 trace ID 기반 lookup만. 인덱스 비용 0. trace 정보 자체를 object storage(S3)에 저장.
# tempo-config.yaml
distributor:
receivers:
otlp:
protocols:
grpc: { endpoint: 0.0.0.0:4317 }
storage:
trace:
backend: s3
s3:
bucket: my-tempo
endpoint: s3.ap-northeast-2.amazonaws.com
compactor:
compaction:
compaction_window: 1h
block_retention: 720h # 30일4. Mimir — Metrics
Prometheus 호환 + 멀티 테넌트 + 거의 무한 cardinality.
# mimir-config.yaml
target: all
multitenancy_enabled: false
blocks_storage:
backend: s3
s3:
bucket_name: my-mimir
limits:
ingestion_rate: 10000
max_global_series_per_user: 10_000_000
out_of_order_time_window: 1h5. 애플리케이션 측 Instrumentation
Node.js
const { NodeSDK } = require('@opentelemetry/sdk-node')
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node')
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-grpc')
const sdk = new NodeSDK({
serviceName: 'my-api',
traceExporter: new OTLPTraceExporter({ url: 'http://otel-collector:4317' }),
instrumentations: [getNodeAutoInstrumentations()],
})
sdk.start()Python
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
provider = TracerProvider()
provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter(endpoint="otel-collector:4317")))
trace.set_tracer_provider(provider)
FastAPIInstrumentor.instrument_app(app)6. SLO 정의
# Latency SLO
histogram_quantile(0.99,
rate(http_request_duration_seconds_bucket[5m])
) < 0.5 # p99 < 500ms
# Error budget
sum(rate(http_requests_total{status=~"5.."}[1h]))
/ sum(rate(http_requests_total[1h]))
< 0.01 # 99% availability7. 알람 — Alertmanager
groups:
- name: api_slo
rules:
- alert: HighErrorRate
expr: |
sum(rate(http_requests_total{status=~"5.."}[5m]))
/ sum(rate(http_requests_total[5m])) > 0.01
for: 10m
labels: { severity: critical }
annotations:
summary: "Error rate > 1% for 10m"8. cardinality 관리
관측성 운영의 가장 큰 함정. 라벨에 user_id·request_id 넣으면 series 폭발.
- http.path를 그대로 라벨로 ❌ → /api/users/:id 로 normalize ✅
- error message 라벨 ❌ → error.code 라벨 ✅
- cardinality 폭발 시 비용 100배·메모리 고갈
9. 비용 비교 (월 1억 events)
| 스택 | 월 비용 |
|---|---|
| Datadog | ~$15,000 |
| New Relic | ~$10,000 |
| Grafana Cloud | ~$3,000 |
| self-hosted (S3 + EC2) | ~$800 |
10. 도입 단계
- Collector 배포
- 한 서비스에 trace instrumentation
- Loki + Tempo + Grafana
- SLO 정의 + 알림
- 전체 서비스로 확장
- cardinality 정책 표준화
자주 묻는 질문
Datadog 대비 self-hosted 단점?
운영 부담. 2~3명의 SRE 시간이 필요. 단 비용은 1/10. 100명 이상 회사는 self-hosted, 작으면 Datadog/Grafana Cloud.
Grafana 대시보드를 직접 만들어야 하나?
대부분 자동 dashboards 가능. https://grafana.com/grafana/dashboards 검색.

댓글 0