Search

What Is This OpenTelemetry Thing?

Tags
Monitoring
Last edited time
2025/03/04 00:32
2 more properties

1. 관측 가능성의 진화

관측 가능성(Observability)의 역사는 컴퓨팅 시스템의 복잡성 증가와 함께 발전해왔습니다. 초기에는 단순한 시스템에서 서버의 깜빡이는 불빛으로 상태를 확인하는 수준이었습니다.
초기 시스템(~2000년대 초): 서버의 깜빡이는 불빛으로 시스템이 정상 작동하는지 확인했습니다. 빠르게 깜빡이면 돈을 벌고 있다는 의미였고, 느리게 깜빡이면 문제가 있다는 신호였습니다.
2000년대 중반: 메트릭 기반의 생산 시스템을 사용했으며, CI와 MRTG와 같은 도구들이 주로 활용되었습니다. 이 시기에는 고정 크기 데이터베이스에 기반한 도구들이 사용되었습니다.
2012-2013년: 더 세분화된 데이터 저장이 필요해지면서 InfluxDB와 Prometheus와 같은 시계열 데이터베이스가 등장했습니다. 이 도구들은 메트릭 데이터를 라벨과 함께 저장할 수 있게 되었습니다.
2017년: 현대적 관측 가능성의 시작점으로, OpenTracing과 OpenCensus라는 두 가지 도구가 등장했습니다. 이 도구들은 분산 추적을 가능하게 했지만 서로 호환되지 않는 문제가 있었습니다.
2019년: OpenTelemetry가 등장하여 OpenTracing과 OpenCensus의 표준 문제를 해결하고, 단일 표준을 통해 분산 추적과 신호를 처리하게 되었습니다. 두 프로젝트는 자체적으로 폐기(deprecated)되고 OpenTelemetry로 통합되었습니다.

2. OpenTelemetry의 주요 기능

OpenTelemetry는 애플리케이션에서 텔레메트리 신호를 발신하는 데 있어 사실상의 표준으로 자리 잡았으며, 이는 여러 벤더와의 호환성을 가능하게 합니다.
CNCF 최고 프로젝트: OpenTelemetry는 현재 CNCF(Cloud Native Computing Foundation)에서 Kubernetes를 제치고 가장 활발한 프로젝트가 되었습니다.
표준화된 프로토콜: OpenTelemetry의 프로토콜은 데이터 모델과 API 계약을 정의하여, 사용자가 어떤 백엔드를 사용하는지에 대한 걱정을 덜어줍니다.
벤더 독립성: 어떤 코드에서도 재계측을 요구하지 않고 다양한 표준화된 신호 대체 가능성을 제공하여, 사용자가 벤더에 대해 책임을 물을 수 있게 합니다. 이는 벤더 종속성을 줄이고 비용 효율성을 높입니다.
트레이스의 중요성: Trace는 시스템의 복잡성을 파악하고 디버깅하는 데 필수적이며, 인과관계(causality)를 기반으로 성능 문제를 정확히 찾아낼 수 있게 합니다.
스팬(Spans): 고유 ID(SpanId), 시작 및 종료 시간, 그리고 인과 관계 ID(TraceId, ParentSpanId)를 포함하는 기본 데이터 구조로, 서비스 그래프나 트레이스 폭포(waterfall)를 구축할 수 있게 합니다.
다양한 언어 지원: Java, Python, .NET, JavaScript, Rust, Erlang 등 11개 이상의 다양한 언어를 지원합니다.

3. 로그, 메트릭, 그리고 트레이스의 비교

OpenTelemetry는 세 가지 주요 신호 유형을 다룹니다: 로그, 메트릭, 트레이스. 각각은 고유한 특성과 용도를 가지고 있습니다.
로그(Logs):
시간에 따른 특정 데이터를 담고 있으며, 인간이 이해하기 쉽게 설계되어 있습니다.
주로 디버깅 목적으로 사용되며, 의도하지 않은 가시성을 제공합니다.
로그는 기본적으로 시간 순서대로 정렬된 이벤트를 기록하지만, 서버 간 시간 동기화 문제로 인과관계를 정확히 파악하기 어려울 수 있습니다.
메트릭(Metrics):
메트릭은 주로 "Metric"으로 불리는 시계열 집계 데이터를 의미합니다.
라벨이 붙은 메트릭 데이터 포인트를 저장하는 시스템을 포함합니다(예: Prometheus, InfluxDB).
저장 비용이 저렴하고 빠르게 쿼리할 수 있지만, 깊은 컨텍스트가 부족합니다.
트레이스 ID와 같은 고유 식별자를 메트릭에 추가하기 어려운 한계가 있습니다.
트레이스(Traces):
디버깅을 위한 목적으로 설계되었으며, 복잡한 시스템의 상호작용을 이해하는 데 도움을 줍니다.
인과관계에 초점을 맞추어 "이 일이 일어난 이유"를 파악할 수 있게 합니다.
성능 문제를 정확히 찾아내는 데 유용하며, 각 스팬은 시작 및 종료 시간을 포함합니다.
고차원성(high dimensionality)과 고카디널리티(high cardinality)를 제공하여 상세한 분석이 가능합니다.
전파(Propagation):
OpenTelemetry의 핵심 기능으로, 다양한 시스템 간의 연결을 가능하게 합니다.
W3C Trace Context 표준을 기반으로 하며, 요청에 상관 관계를 추가하여 여러 시스템 간의 추적을 용이하게 합니다.
트레이스 ID와 부모 스팬 ID를 포함하는 트레이스 부모(trace parent) 정보를 전달합니다.
배게지(Baggage):
서비스 간 추가 컨텍스트를 전송하는 개념이지만, 잘못 사용될 경우 위험할 수 있습니다.
모든 트레이스의 각 스팬에 배게지 정보가 자동으로 포함되지는 않으므로 주의가 필요합니다.
민감한 정보(예: 사회보장번호)를 배게지에 포함시키면 보안 위험이 발생할 수 있습니다.

4. OpenTelemetry의 강력한 데이터 수집 도구인 Collector

OpenTelemetry Collector는 텔레메트리 데이터 수집과 처리를 위한 핵심 구성 요소입니다.
데이터 프록시 역할: Collector는 애플리케이션이 직접 백엔드에 데이터를 전송하는 것보다 더 효율적인 프록시 역할을 수행합니다.
다양한 소스 지원: Kubernetes와 같은 다양한 소스에서 데이터를 OpenTelemetry 형식으로 수집하여 백엔드로 전달할 수 있습니다.
중앙 집중식 구성 관리: API 키와 같은 민감한 구성 정보를 중앙에서 관리할 수 있어 보안을 강화합니다. 특히 1500개의 마이크로서비스가 있는 환경에서 API 키 교체 시 매우 유용합니다.
데이터 필터링 및 보안: 보안 팀은 Collector의 데이터 필터링 기능을 활용하여 개인 정보나 특정 데이터(예: 신용카드 번호)를 전송하지 않도록 설정할 수 있습니다.
Kubernetes 통합: Kubernetes 환경에서 효율적으로 작동하며, 애플리케이션이 자체적으로 클러스터 정보를 제공할 필요 없이 이를 대신 처리할 수 있습니다.
다중 벤더 지원: 동일한 데이터를 여러 백엔드 벤더에 동시에 전송할 수 있어 벤더 비교 테스트가 용이합니다.
계층적 배포: 일반적으로 2개 계층으로 배포하며(애플리케이션 근처와 공유 네트워크 세그먼트), 최대 7개 계층까지도 가능하지만 권장되지는 않습니다.

4.1. OpenTelemetry의 자동 계측 방식

OpenTelemetry는 여러 방식으로 애플리케이션에 통합될 수 있으며, 자동 계측은 가장 쉬운 시작점입니다.
에이전트 기반 접근법: 자동 계측은 대리 기반(agent-based) 방식으로, 일반적인 APM(Application Performance Monitoring) 에이전트와 유사합니다.
코드 수정 없음: 환경 변수를 통해 데이터를 수집할 수 있어 SRE 팀에 특히 유용합니다. 코드를 변경할 권한이 없는 팀에게 이상적입니다.
기본 데이터 수집: HTTP 정보, 데이터베이스 호출과 같은 높은 수준의 정보를 자동으로 수집합니다.
다양한 언어 지원: Java, JavaScript, Python, .NET, Ruby 등 다양한 언어를 위한 에이전트가 제공되지만, Go 언어에 대한 지원은 상대적으로 제한적입니다.
한계점: 간단하게 시작할 수 있지만, 수집된 데이터에 추가적인 맥락이나 속성을 추가할 수 없는 한계가 있습니다.

4.2. 자체적인 스팬 추가 및 문맥 설정의 중요성

자동 계측의 한계를 넘어 더 풍부한 텔레메트리 데이터를 얻기 위해서는 코드 수준의 계측이 필요합니다.
코드 계측(Coded Instrumentation): 자신만의 스팬을 추가하고 기존 스팬에 문맥을 더하는 방법입니다.
애플리케이션 시작 시점: 일반적으로 애플리케이션 시작 시점에서 구현하며, .NET, JavaScript, Python에서 동일한 방식으로 적용됩니다.
Java의 특수성: Java의 경우 Java agent를 사용하는 것이 기존의 수용된 방법이며, 더 타겟팅된 접근이 가능합니다.
효율성 고려: JavaScript를 사용할 때는 모든 노드 모듈의 파일 시스템 호출을 모니터링하는 것이 비효율적일 수 있으며, 로깅 비용을 초과할 가능성이 있습니다.
조직별 차별화: 각 조직의 고유한 비즈니스 로직은 텔레메트리에서 중요한 차별점이 되며, 이는 소프트웨어 개발자가 애플리케이션을 작성하는 핵심 이유입니다.

4.3. OpenTelemetry Collector의 중요성

Collector는 OpenTelemetry 에코시스템에서 핵심적인 역할을 담당합니다.
데이터 전달 역할: 애플리케이션에서 수집한 텔레메트리 데이터를 백엔드로 전달합니다.
다양한 형식 지원: Kubernetes에서의 클러스터 수준 메트릭과 같은 다양한 형식을 지원합니다.
중앙화된 보안: API 키 관리 및 설정을 중앙화함으로써 보안을 강화하며, 내부 네트워크에서는 인증 없이 요청을 전송할 수 있습니다.
데이터 필터링: 민감한 정보를 안전하게 처리할 수 있는 필터링 및 교정 기능을 제공합니다.
Kubernetes 환경 최적화: 중앙화된 데이터 강화를 통해 애플리케이션이 복잡한 네임스페이스를 관리할 필요가 없어집니다.

4.4. OpenTelemetry 배포 방법

OpenTelemetry를 배포하는 여러 방법이 있지만, Collector를 활용하는 것이 권장됩니다.
직접 백엔드 전송: 텔레메트리 데이터를 직접 백엔드로 전송할 수 있지만, 이는 권장되지 않습니다.
단일 Collector: 시작 단계에서는 단일 Collector를 통해 데이터를 전송하는 것이 좋습니다.
확장 가능한 구성: 텔레메트리 파이프라인이 성장함에 따라 로드 밸런서와 자동 확장 기능을 추가하여 시스템을 확장할 수 있습니다.

5. OpenTelemetry의 수집기와 샘플링 메커니즘

관찰 가능성에는 비용이 수반되며, 샘플링은 이 비용을 관리하는 중요한 방법입니다.
샘플링의 중요성: 관찰 가능성의 비용을 줄이는 데 중요하며, 특히 트레이싱 데이터는 각 요청마다 여러 스팬을 생성하므로 비용이 빠르게 증가할 수 있습니다.
헤드 샘플링(Head Sampling):
요청이 발생하기 전에 샘플링을 결정합니다.
제한된 정보(예: 사용자 에이전트, 페이로드 크기)만 사용할 수 있습니다.
처리 오버헤드를 줄이는 데 효율적이지만, 중요한 이벤트(오류, 느린 요청)를 놓칠 수 있습니다.
데이터를 생성하지 않으므로 메모리 효율성이 높습니다.
테일 샘플링(Tail Sampling):
루트 스팬 수신 후 지연(일반적으로 5초)을 두고 샘플링을 결정합니다.
모든 스팬 데이터를 기반으로 분석하여 오류, 재시도, 성능 지연 등을 감지할 수 있습니다.
일반적으로 Collector에서 실행되며, 모든 데이터에 접근할 수 있습니다.
메모리 사용량이 많고 백엔드로의 데이터 전송이 지연될 수 있습니다.
다중 가용성 영역(AZ) 환경에서는 AZ 간 트래픽 비용을 고려해야 합니다.
지속적인 개선: OpenTelemetry는 지속적인 업데이트와 피드백을 필요로 하며, 사용자의 요구에 맞게 발전해야 합니다.
컨텍스트 추가 및 제거
파이프라인 최적화
샘플링 전략 조정

6. OpenTelemetry의 미래

OpenTelemetry는 지속적으로 발전하고 있으며, 다음과 같은 개선 사항이 예정되어 있습니다:
시맨틱 컨벤션 확장: 메시징 및 데이터베이스 시맨틱 컨벤션이 곧 출시될 예정입니다.
더 많은 라이브러리: 다양한 프로그래밍 언어를 위한 추가 계측 라이브러리가 개발 중입니다.
문서 개선: 더 나은 문서화 작업이 진행 중입니다.
서버리스 지원: AWS Lambda, Google Cloud Functions 등 서버리스 환경에서의 지원이 개선될 예정입니다.
비동기 컨텍스트 관리: 비동기 프로그래밍 모델에서의 컨텍스트 관리가 향상될 것입니다.