분산 추적
마이크로서비스 간 요청 흐름을 추적하고 성능을 분석하는 방법
마이크로서비스 간 요청 흐름을 추적하고 성능을 분석하는 방법
목표: 분산 시스템의 병목 현상을 식별하고 최적화할 수 있는 수준
🎯 분산 추적 개요
개념
graph LR
subgraph "분산 추적"
CLIENT["👤 Client"] -->|"Trace ID: abc123"| GW["🌐 Gateway"]
GW -->|"Trace ID: abc123"| SVC1["📦 Service A"]
SVC1 -->|"Trace ID: abc123"| SVC2["📦 Service B"]
SVC2 -->|"Trace ID: abc123"| DB["🗄️ Database"]
SVC1 -->|"Span: 50ms"| JAEGER["🎯 Jaeger"]
SVC2 -->|"Span: 100ms"| JAEGER
DB -->|"Span: 200ms"| JAEGER
end
핵심 개념:
- Trace: 전체 요청 흐름
- Span: 개별 작업 단위
- Trace ID: 전체 요청 식별자
- Span ID: 개별 작업 식별자
- Parent Span ID: 부모 작업 식별자
📊 OpenTelemetry
개요
관측성 데이터(메트릭, 로그, 추적)의 표준.
graph TB
subgraph "OpenTelemetry 아키텍처"
APP["📦 Application"] -->|"OTel SDK"| COLLECTOR["🌐 OTel Collector"]
COLLECTOR -->|"Trace"| JAEGER["🎯 Jaeger"]
COLLECTOR -->|"Metric"| PROM["📊 Prometheus"]
COLLECTOR -->|"Log"| ES["🗄️ Elasticsearch"]
end
애플리케이션 계측
# Python 예시
from opentelemetry import trace
from opentelemetry.exporter.jaeger.thrift import JaegerExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.instrumentation.flask import FlaskInstrumentor
from opentelemetry.instrumentation.requests import RequestsInstrumentor
# 트레이서 설정
trace.set_tracer_provider(TracerProvider())
tracer = trace.get_tracer(__name__)
# Jaeger 내부 출력
jaeger_exporter = JaegerExporter(
agent_host_name="jaeger-agent",
agent_port=6831,
)
span_processor = BatchSpanProcessor(jaeger_exporter)
trace.get_tracer_provider().add_span_processor(span_processor)
# 자동 계측
FlaskInstrumentor().instrument_app(app)
RequestsInstrumentor().instrument()
# 수동 계측
with tracer.start_as_current_span("process_order") as span:
span.set_attribute("order.id", "12345")
span.set_attribute("order.amount", 100.00)
with tracer.start_as_current_span("validate_payment"):
validate_payment()
with tracer.start_as_current_span("update_inventory"):
update_inventory()
🎯 Jaeger
설치
# Jaeger Operator 설치
kubectl create namespace observability
kubectl apply -f https://github.com/jaegertracing/jaeger-operator/releases/latest/download/jaeger-operator.yaml -n observability
# Jaeger 인스턴스 생성
kubectl apply -f - <<EOF
apiVersion: jaegertracing.io/v1
kind: Jaeger
metadata:
name: simplest
EOF
# 또는 Helm
helm repo add jaegertracing https://jaegertracing.github.io/helm-charts
helm install jaeger jaegertracing/jaeger
접근
# 포트 포워딩
kubectl port-forward svc/simplest-query 16686:16686
# 브라우저에서 접속
http://localhost:16686
🔍 추적 분석
Jaeger UI
# 1. 서비스 선택
# 2. 작업 선택
# 3. 태그 필터
# 4. 시간 범위
# 5. 검색
주요 기능
| 기능 | 설명 |
|---|---|
| Trace 검색 | 서비스, 작업, 태그로 검색 |
| Trace 뷰 | 전체 요청 흐름 시각화 |
| Span 상세 | 개별 작업의 태그, 로그 |
| 의존성 그래프 | 서비스 간 호출 관계 |
| 비교 | 여러 Trace 비교 |
📋 추적 모범 사례
계측 가이드
# 좋은 예시
with tracer.start_as_current_span("process_payment") as span:
span.set_attribute("payment.method", "credit_card")
span.set_attribute("payment.amount", 100.00)
span.set_attribute("payment.currency", "USD")
try:
result = process_payment()
span.set_attribute("payment.status", "success")
span.set_attribute("payment.transaction_id", result.id)
except PaymentError as e:
span.set_attribute("payment.status", "failed")
span.set_attribute("error.message", str(e))
span.set_status(StatusCode.ERROR, str(e))
raise
# 나쁜 예시
with tracer.start_as_current_span("do_stuff"):
do_stuff() # 태그 없음, 의미 없는 이름
샘플링
# OpenTelemetry Collector 설정
apiVersion: v1
kind: ConfigMap
metadata:
name: otel-collector-config
data:
otel-collector-config.yaml: |
receivers:
otlp:
protocols:
grpc:
http:
processors:
batch:
tail_sampling:
decision_wait: 10s
num_traces: 100
expected_new_traces_per_sec: 10
policies:
- name: errors
type: status_code
status_code: {status_codes: [ERROR]}
- name: slow_requests
type: latency
latency: {threshold_ms: 1000}
exporters:
jaeger:
endpoint: jaeger-collector:14250
tls:
insecure: true
service:
pipelines:
traces:
receivers: [otlp]
processors: [batch, tail_sampling]
exporters: [jaeger]
📋 체크리스트
- OpenTelemetry SDK 설치
- 애플리케이션 계측
- Jaeger 설치
- 추적 데이터 확인
- 샘플링 정책 설정
- 의존성 그래프 분석
- 성능 병목 식별
- 알림 설정
🔗 관련 노트
- 03-05-모니터링-Prometheus-Grafana — 메트릭 모니터링
- 03-06-로깅-EFK-스택 — 로그 수집
- 03-10-서비스메시-Istio — 자동 추적
마지막 업데이트: 2026-06-01