728x90
반응형

- Tempo: 100% 샘플링을 실현한 분산 트레이싱과 MSA 병목 추적
메트릭(Mimir)을 통해 장애의 '발생'을 인지하고, 로그(Loki)를 통해 에러의 '원인'을 파악하는 과정까지 살펴보았습니다. 이제 관측성의 마지막 퍼즐이자, 거대한 마이크로서비스 아키텍처(MSA) 환경에서 가장 까다로운 질문인 "도대체 수많은 서비스 중 어디서 병목이 발생했는가?"를 해결할 차례입니다.
이번 포스팅에서는 LGTM 스택의 'T'를 담당하며 분산 트레이싱 백엔드의 새로운 패러다임을 제시한 Tempo(템포)에 대해 깊이 파헤쳐 보겠습니다.
1. 분산 트레이싱의 딜레마: '샘플링(Sampling)의 저주'
하나의 사용자 요청이 API 게이트웨이를 거쳐 Auth, Payment, Inventory, Database 등 수십 개의 마이크로서비스를 통과하는 환경을 상상해 보십시오. 특정 요청이 지연될 때, 어느 구간에서 병목이 발생했는지 추적하기 위해 기존에는 Jaeger나 Zipkin 같은 분산 추적 시스템을 사용해 왔습니다.
하지만 기존 시스템들은 데이터를 저장할 때 Cassandra나 Elasticsearch 같은 무겁고 값비싼 스토리지를 백엔드로 사용했습니다. 트레이스 데이터는 메트릭이나 로그보다 훨씬 방대하기 때문에, 쏟아지는 트레이스를 모두 저장하다가는 인프라 비용이 파산 수준에 이르게 됩니다. 그래서 엔지니어들은 어쩔 수 없이 샘플링(Sampling)이라는 타협안을 선택했습니다. "전체 트래픽의 1% 또는 5%만 랜덤하게 수집하자."
이로 인해 치명적인 문제가 발생합니다. 간헐적으로 발생하는 심각한 장애나 특정 결제 실패 건을 추적하려고 할 때, 정작 내가 찾고자 하는 그 요청의 트레이스 데이터는 샘플링에 걸러져 유실되어 버리는 현상입니다. 바늘을 찾기 위해 건초더미의 95%를 태워버리는 격이었습니다.

2. Tempo의 파괴적 혁신: "버리지 말고 다 저장해라"
Grafana Labs는 Tempo를 설계하며 앞서 살펴본 Mimir, Loki와 완벽하게 동일한 철학을 적용했습니다. 바로 비용 효율적인 오브젝트 스토리지(S3, GCS)의 적극적인 활용과 인덱스 최소화(Index-free)입니다.
Tempo는 복잡한 검색을 위한 인덱스를 거의 만들지 않습니다. 오직 고유한 식별자인 TraceID만으로 데이터를 찾을 수 있도록 아키텍처를 극단적으로 단순화했습니다. 인덱싱 오버헤드가 사라지고 스토리지가 저렴해지자, 마침내 타협할 필요가 없어졌습니다.
Tempo는 100% 샘플링을 지향합니다. 버려지는 데이터 없이 모든 사용자 요청의 라이프사이클을 기록합니다. 언제 어떤 에러가 발생하든 해당 TraceID만 알고 있다면, 그 요청이 수십 개의 컨테이너와 비동기 메시지 큐(Kafka 등)를 어떻게 관통했는지 폭포수(Waterfall) 차트로 완벽하게 복원해 냅니다.
3. Tempo 아키텍처와 W3C Trace Context
분산 트레이싱이 성립하려면 여러 서비스가 동일한 맥락을 공유해야 합니다. Tempo는 CNCF의 관측성 표준인 OpenTelemetry(OTel)를 네이티브로 지원하며, W3C Trace Context 규격을 통해 서비스 간 컨텍스트를 전파합니다. 시스템 내부적인 동작 구조는 다음과 같습니다.

기술적 동작 원리:
- Context Propagation: 첫 요청 시 생성된 고유 식별자(TraceID)가 traceparent 등의 HTTP 헤더나 이벤트 브로커(Kafka 등)의 메타데이터에 담겨 마이크로서비스의 호출 체인을 따라 전파됩니다.
- Span 수집 (OTLP): 각 서비스는 자신의 작업 구간(Span)을 OpenTelemetry 포맷(OTLP)으로 수집 에이전트인 Grafana Alloy에 비동기로 전송합니다.
- 수신 및 저장 (Distributor & Ingester): Tempo의 Distributor가 트래픽을 받아 Ingester로 분배하며, Ingester는 스팬들을 메모리에 버퍼링 후 압축하여 S3 객체 스토리지에 블록 형태로 저장합니다.
- O(1) 수준의 단일 조회: Grafana에서 TraceID를 입력하면, Querier는 무거운 검색을 수행하는 대신 블록 내 블룸 필터를 활용하여 해당 트레이스가 위치한 S3 오프셋을 찾아내 데이터를 가져옵니다.
4. 완성된 통합: 점과 점을 잇다
Tempo의 진정한 위력은 단독으로 쓰일 때보다 메트릭, 로그와 결합할 때 발휘됩니다. Tempo는 앞선 포스팅에서 보았던 '단일 장애 추적 파이프라인'의 핵심 연결 고리입니다.
- Mimir(메트릭) -> Tempo: CPU 사용량 급증 알람을 보고 대시보드에 들어가면, 메트릭 그래프 위의 점에 TraceID가 매핑되어 있습니다. 클릭 한 번으로 장애 당시의 정확한 트레이스 뷰로 넘어갑니다.
- Tempo -> Loki(로그): 트레이스 폭포수 차트에서 유독 오래 걸린 특정 서비스의 구간을 발견합니다. 해당 Span을 클릭하면, 그 Span 내에서 발생한 애플리케이션 로그(Loki)만 정확하게 필터링되어 나타납니다.
이러한 유기적인 연결은 이벤트 기반 아키텍처나 비동기 통신이 잦은 복잡한 시스템에서 엔지니어의 디버깅 시간을 혁신적으로 단축해 줍니다.
5. 마무리하며
파편화되어 있던 데이터들을 하나의 문맥으로 엮어내는 LGTM 스택의 컴포넌트들을 모두 살펴보았습니다. 오브젝트 스토리지를 백엔드로 삼아 무한한 확장성과 가성비를 달성한 이 관측성 파이프라인은 단순히 장애 처리를 빠르게 하는 것을 넘어섭니다. 이렇게 100% 샘플링되어 정형화된 고품질의 텔레메트리 데이터(Metrics, Logs, Traces)는, 향후 머신러닝 알고리즘이 시스템의 이상 징후를 스스로 탐지하고 근본 원인을 추론하는 AIOps(Artificial Intelligence for IT Operations) 플랫폼으로 진화하기 위한 가장 강력한 기반 데이터 셋이 됩니다.
728x90
반응형