- 사이트 / GitHub
- 마이크로서비스 기반 분산 시스템을 위한 오픈소스 분산 추적 시스템(distributed tracing system)
- CNCF Graduated Project
- 단일 모놀리식 애플리케이션과 달리 분산 서비스는 네트워크와 관찰 가능성 문제가 훨씬 복잡
- OpenTelemetry와 통합하여 계측(instrumentation) 구현 권장 (Jaeger 클라이언트 라이브러리 지원 종료)
| 해결 문제 |
설명 |
| 분산 컨텍스트 전파 |
서비스 간 요청에 추적 컨텍스트(TraceID, SpanID) 전달 |
| 분산 트랜잭션 모니터링 |
복잡한 서비스 호출 체인의 전체 흐름 추적 |
| 근본 원인 분석 |
장애·오류 발생 지점 및 원인 파악 |
| 서비스 종속성 분석 |
서비스 간 의존 관계 시각화 |
| 성능/지연 최적화 |
병목 구간 및 느린 요청 탐지 |
| 특징 |
설명 |
| 높은 확장성 |
단일 실패 지점 없이 비즈니스 요구에 맞게 수평 확장 가능 |
| OpenTelemetry 지원 |
OTLP(OpenTelemetry Protocol)로 스팬 수신 — Jaeger 클라이언트 라이브러리는 deprecated |
| 다중 백엔드 스토리지 |
Cassandra, Elasticsearch, Kafka, Badger, Memory, Storage Plugin 지원 |
| 웹 UI |
수만 개 스팬을 포함한 추적 시각화, 서비스 종속성 그래프, 비교 뷰 |
| 클라우드 네이티브 배포 |
Docker 이미지·Kubernetes Operator로 배포 |
| 관찰 가능성 |
모든 컴포넌트가 Prometheus 메트릭 노출. 로그는 zap으로 stdout 출력 |
| Zipkin 하위 호환 |
Zipkin 형식 트래픽을 Jaeger 백엔드로 라우팅 가능 |
| 토폴로지 그래프 |
시스템 아키텍처 그래프 및 심층 종속성 그래프 2종 지원 |
| SPM |
RED(Requests·Errors·Duration) 메트릭 집계·시각화 및 이상 강조 표시 |
| 적응 샘플링 |
트래픽 기반 동적 샘플링 전략 자동 조정 |
스토리지 백엔드
| 스토리지 |
용도 |
비고 |
| Memory |
개발·테스트 (all-in-one 전용) |
재시작 시 데이터 소실 |
| Badger |
임베디드 로컬 스토리지 (all-in-one 전용) |
단일 노드 소규모 환경 |
| Cassandra 3.4+ |
프로덕션 대용량 |
대규모 환경은 Elasticsearch 권장 |
| Elasticsearch 5.x~8.x |
프로덕션 권장 |
검색·필터 성능 우수 |
| Kafka |
콜렉터↔스토리지 중간 버퍼 |
Streaming 전략에서 활용 |
| Storage Plugin (gRPC) |
커스텀 스토리지 연동 |
InfluxDB, Logz.io, ClickHouse 등 |
| Metrics (Prometheus) |
RED 메트릭 쿼리 (읽기 전용) |
Jaeger Query 컴포넌트 전용 |
특징
- 통계적으로 중요한 요청/오류율 또는 대기 시간이 있는 서비스 및 작업을 강조 표시
- 서비스/엔드포인트 별 확률로 일관된 선행 샘플링을 사용
(Uses consistent upfront sampling with individual per service/endpoint probabilities)
- 적응 샘플링(Adaptive sampling)
- 수집 후 데이터 처리 파이프라인
용어 정리
| 용어 |
설명 |
| 스팬(Span) |
논리적 작업 단위. 작업 이름·시작 시간·기간(duration) 포함. 인과 관계를 위해 중첩·정렬 |
| 추적(Trace) |
시스템을 통한 데이터/실행 경로. 스팬의 방향성 비순환 그래프(DAG) |
| 에이전트(Agent) |
UDP로 스팬을 수신해 일괄 처리 후 콜렉터로 전송하는 네트워크 데몬. 모든 호스트에 사이드카/DaemonSet으로 배포 |
| 콜렉터(Collector) |
에이전트에서 추적 수신 → 유효성 검사·색인·변환 후 스토리지에 저장 |
| 쿼리(Query) |
스토리지에서 추적을 검색하고 UI를 호스팅하는 서비스 |
| 인제스터(Ingester) |
Kafka 토픽을 읽어 Cassandra·Elasticsearch 등 스토리지 백엔드에 쓰는 서비스. 후처리 파이프라인 구축에 활용 |
컨텍스트 전파: TraceID·SpanID·Baggage만 요청과 함께 전달되며, 작업 이름·타이밍·태그·로그는 백그라운드에서 Jaeger 백엔드로 비동기 전송
- 헤드 기반(Head-based) 일관 샘플링 구현 —
A → B → C 호출 체인에서 A의 샘플링 결정이 B·C로 전파되어 완전한 추적 보장
- 각 서비스가 독립적으로 샘플링 결정을 내리면 완전한 추적을 거의 얻지 못함
클라이언트 샘플링 유형
| 유형 |
sampler.type |
설명 |
예시 |
| Constant |
const |
모든 추적에 항상 동일한 결정 |
param=1 전체 샘플링, param=0 전체 미샘플링 |
| Probabilistic |
probabilistic |
설정 확률로 무작위 샘플링 |
param=0.1 → 10개 중 약 1개 샘플링 |
| Rate Limiting |
ratelimiting |
누출 버킷으로 일정 속도 샘플링 |
param=2.0 → 초당 2개 추적 |
| Remote (기본값) |
remote |
Jaeger 에이전트에서 적절한 전략 조회. 중앙에서 동적 제어 가능 |
- |
콜렉터 샘플링 구성
- 클라이언트가 Remote 샘플링 사용 시 콜렉터에서 중앙 제어 가능
SAMPLING_CONFIG_TYPE 환경 변수로 방식 결정
file (기본값): JSON 파일에서 주기적으로 로드
adaptive: 트래픽에 따라 동적으로 생성 (적응 샘플링)
설치
- Kubernetes 애플리케이션을 패키징·배포·관리하는 납특 Kubernetes 연산자 패턴
- 특정 네임스페이스 또는 전체 클러스터에서 Jaeger CR을 감시
- 일반적으로 클러스터당 Operator 1개 (멀티테넌트: 네임스페이스당 최대 1개)
jaegertracing.io/operated-by 라벨에 Operator 네임스페이스·이름을 지정하여 소유권 관리
# cert-manager 설치 (미설치 시)
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.8.0/cert-manager.yaml
# Jaeger Operator 설치
kubectl create namespace observability
kubectl create -f https://github.com/jaegertracing/jaeger-operator/releases/download/v1.34.1/jaeger-operator.yaml -n observability
배포 전략
| 전략 |
용도 |
특징 |
| AllInOne |
개발·테스트·데모 |
단일 파드에 북in다(에이전트·콜렉터·쿼리·인제스터·UI). 메모리 스토리지. 확장 불가 |
| Production |
프로덕션 |
컴포넌트 분리 배포. Elasticsearch 등 영구 스토리지 + 수평 확장 |
| Streaming |
고부하 프로덕션 |
Production + Kafka 버퍼. 스토리지 부하 감소 + 실시간 스팬 활용 |
AllInOne 예시
apiVersion: jaegertracing.io/v1
kind: Jaeger
metadata:
name: simple-all-in-one
namespace: observability
spec:
strategy: allInOne
allInOne:
options:
log-level: debug
storage:
type: memory
options:
memory:
max-traces: 100000
kubectl get pod -n observability -w
NAME READY STATUS RESTARTS AGE
jaeger-operator-86cc79547f-j7pvj 2/2 Running 0 3d19h
simple-all-in-one-7fbf766df8-s6f54 1/1 Running 0 104s
Production 예시 (Elasticsearch)
apiVersion: jaegertracing.io/v1
kind: Jaeger
metadata:
name: simple-prod
namespace: observability
spec:
strategy: production
collector:
maxReplicas: 5
resources:
limits:
cpu: 100m
memory: 128Mi
storage:
type: elasticsearch
esIndexCleaner:
enabled: true
numberOfDays: 7
schedule: "00 01 * * *"
esRollover:
conditions: '{"max_age": "1d"}'
readTTL: 168h
schedule: "00 01 * * *"
options:
es:
use-aliases: true
server-urls: http://elasticsearch-master-headless.elastic.svc.cluster.local:9200
kubectl get pod -n observability -w
NAME READY STATUS RESTARTS AGE
jaeger-operator-86cc79547f-j7pvj 2/2 Running 0 3d19h
simple-prod-collector-6d786b5756-tj2t2 1/1 Running 0 65s
simple-prod-es-rollover-create-mapping-4bswl 0/1 Completed 0 79s
simple-prod-query-86bbdfb757-9lnnl 2/2 Running 0 65s
에이전트 사이드카 주입
자동 주입 (Deployment)
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
"sidecar.jaegertracing.io/inject": "true"
...
- 네임스페이스 단위 설정도 가능 (우선순위: Deployment > Namespace)
수동 정의 (StatefulSets, DaemonSets 등)
...
spec:
containers:
- name: example-app
image: jaegertracing/vertx-create-span:operator-e2e-tests
ports:
- containerPort: 8080
protocol: TCP
- name: jaeger-agent
image: jaegertracing/jaeger-agent:1.34.1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 5775
name: zk-compact-trft
protocol: UDP
- containerPort: 5778
name: config-rest
protocol: TCP
...
에이전트 DaemonSet 설치
apiVersion: jaegertracing.io/v1
kind: Jaeger
metadata:
name: my-jaeger
spec:
agent:
strategy: DaemonSet
- 애플리케이션에서
JAEGER_AGENT_HOST 환경변수를 status.hostIP로 지정하여 에이전트에 접속
샘플링 전략 정의
apiVersion: jaegertracing.io/v1
kind: Jaeger
metadata:
name: with-sampling
spec:
strategy: allInOne
sampling:
options:
default_strategy:
type: probabilistic
param: 0.5
업그레이드
# Operator 이미지 변경 → 일괄 인스턴스 업그레이드
kubectl edit deployment jaeger-operator -n observability
# image: quay.io/jaegertracing/jaeger-operator:x.x.x 수정
Operator 업그레이드 후 인스턴스는 즉시 업그레이드되지 않음
삭제
# Jaeger 인스턴스 삭제
kubectl delete -f xxx.yaml
# Jaeger Operator 삭제
kubectl delete -f https://github.com/jaegertracing/jaeger-operator/releases/download/v1.34.1/jaeger-operator.yaml -n observability
샘플 애플리케이션
kubectl apply -f https://github.com/jaegertracing/vertx-create-span/raw/master/deployment-sidecar.yaml
UI
kubectl get ingress -n observability 수행 후 ADDRESS로 접속
| 화면 |
스크린샷 |
| 검색 |
 |
| 추적 (1) |
 |
| 추적 (2) |
 |
| 비교 |
 |
임베디드 모드
- Jaeger UI를 다른 애플리케이션에 통합 가능 — URL에
uiEmbed=v0 쿼리 파라미터 추가
| 화면 |
URL 형식 |
스크린샷 |
| 검색 |
/search?service=...&uiEmbed=v0 |
 |
| 추적 |
/trace/{trace-id}?uiEmbed=v0 |
 |
| 비교 |
/trace/{id}?cohort={id}&uiEmbed=v0 |
 |
구성 방안
- 스팬 데이터를 집계하여 RED(Request·Error·Duration) 메트릭 시각화
- 서비스나 연산 이름을 모른 상태에서도 흥미로운 추적(높은 QPS, 느린 요청)을 식별 가능
- 이상한 요청/오류율·대기 시간이 있는 서비스를 강조 표시 후 해당 추적으로 직접 이동 가능
- Prometheus를 Metrics Storage Backend로 사용하여 RED 데이터 수집
유사 도구 비교
| 항목 |
Jaeger |
Zipkin |
Tempo (Grafana) |
AWS X-Ray |
| 라이선스 |
Apache 2.0 |
Apache 2.0 |
AGPL 3.0 |
상용 |
| CNCF |
Graduated |
- |
- |
- |
| 백엔드 스토리지 |
Cassandra·ES·Kafka |
Cassandra·ES |
S3·GCS (Object Storage) |
클라우드 내장 |
| OTel 지원 |
O (OTLP 수신) |
O |
O |
O |
| UI |
포함 |
포함 |
Grafana 연동 |
AWS Console |
| 확장성 |
높음 |
중간 |
매우 높음 |
AWS 의존 |
| 적합 환경 |
Kubernetes·하이브리드 |
오래된 레거시 |
Grafana 스택 |
AWS 생태계 |
관련 포스트