5 분 소요

개요

  • 사이트 / 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: 트래픽에 따라 동적으로 생성 (적응 샘플링)


설치

Operator

  • 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


구성 방안

방식 설명 비고
Jaeger 단독 OpenTelemetry SDK로 애플리케이션 직접 계측 OTel 도교 활용
Istio 애플리케이션 수정 없이 수집 가능 완전한 추적을 위해 W3C Trace Context 헤더 전달 필요
Linkerd OpenTelemetry 클라이언트로 애플리케이션 수정 필요 Distributed tracing with Linkerd


Service Performance Monitoring (SPM)

  • 스팬 데이터를 집계하여 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 생태계


관련 포스트