OpenTelemetry Collector는 단일 바이너리로 구성되어 있으며, 배포 방식에 따라 Agent Mode와 Gateway Mode로 나뉩니다.
두 모드는 동일한 바이너리를 사용하지만 배포 위치와 역할이 다릅니다.
이번 포스팅에서는 각 배포 방식별 장단점, 그리고 두 방식을 함께 사용하는 아키텍처와 고려사항에 대해 다루겠습니다.
Agent Mode
Agent Mode는 애플리케이션과 동일한 호스트에서 Collector를 실행하는 패턴입니다. Kubernetes 환경에서는 DaemonSet 또는 Sidecar로 배포합니다. (Agent Deployment - OpenTelemetry)
동작 방식
[애플리케이션] → (OTLP) → [같은 호스트의 Collector] → [백엔드]
애플리케이션의 SDK에서 OTLP로 텔레메트리 데이터를 전송하면, 같은 호스트에 있는 Collector가 이를 수신하여 백엔드로 내보냅니다.
핵심 역할
빠른 오프로딩 (Fast Offloading)
애플리케이션이 전송한 텔레메트리 데이터를 같은 호스트에서 즉시 수신합니다. 애플리케이션은 로컬 Collector에 데이터를 넘기는 즉시 본래 작업으로 돌아갈 수 있으므로, 모니터링 데이터 전송으로 인한 애플리케이션 성능 저하를 방지합니다.
Kubernetes 메타데이터 추가 (Enrichment)
Agent의 가장 중요한 역할입니다. k8sattributesprocessor를 사용하여 텔레메트리 데이터에 Kubernetes 인프라 정보를 자동으로 태깅합니다. 이 프로세서는 Kubernetes API를 통해 클러스터의 Pod를 탐색하고, 수신 요청의 IP 주소를 기반으로 데이터를 해당 Pod와 매칭하여 메타데이터를 추가합니다. (Kubernetes Attributes Processor - OpenTelemetry)
기본으로 추가되는 속성:
k8s.namespace.namek8s.pod.namek8s.pod.uidk8s.pod.start_timek8s.deployment.namek8s.node.name
설정에 따라 k8s.pod.ip, k8s.replicaset.name, k8s.daemonset.name, k8s.statefulset.name, container.image.name 등 추가 속성도 추출할 수 있습니다. Pod의 labels와 annotations에서 커스텀 속성을 추출하는 것도 가능합니다.
설정 예시
SDK에서 Collector 주소를 지정합니다:
export OTEL_EXPORTER_OTLP_ENDPOINT=http://collector.example.com:4318
Collector 설정:
receivers:
otlp:
protocols:
http:
endpoint: 0.0.0.0:4318
exporters:
otlp/jaeger:
endpoint: https://jaeger.example.com:4317
sending_queue:
batch:
service:
pipelines:
traces:
receivers: [otlp]
exporters: [otlp/jaeger]
Agent Mode에 적합한 컴포넌트
다음 컴포넌트들은 호스트 로컬 정보에 의존하므로 반드시 Agent에서 실행해야 합니다:
hostmetricsreceiver: 호스트 메트릭 수집 (CPU, 메모리, 디스크 등)filelogreceiver: 로컬 파일 로그 수집resourcedetectionprocessor: 호스트 환경 정보를 리소스 속성으로 추가
이 컴포넌트들을 별도 머신의 Collector에서 실행하면 중복 데이터가 발생하거나 잘못된 호스트 정보가 기록됩니다.
장단점
| 장점 | 단점 |
|---|---|
| 구성이 단순하고 시작이 쉬움 | 팀/인프라 규모가 커지면 에이전트 설정을 일관되게 관리하고 배포하는 운영 비용이 증가함 |
| 앱과 Collector 간 1:1 매핑이 명확 | 복잡한 배포 환경에 유연하지 않음 |
Gateway Mode
Gateway Mode는 Collector를 독립된 서비스로 실행하는 패턴입니다. 클러스터, 데이터센터, 리전 단위로 중앙 집중식 OTLP 엔드포인트를 제공합니다. Kubernetes 환경에서는 Deployment로 배포합니다. (Gateway Deployment - OpenTelemetry)
동작 방식
[여러 앱/Agent] → (OTLP) → [로드밸런서] → [Gateway Collector 인스턴스들] → [백엔드]
여러 애플리케이션이나 Agent Collector에서 전송한 데이터를 중앙의 Gateway Collector가 수신하여 처리 후 백엔드로 내보냅니다. 앞단에 NGINX 같은 로드밸런서를 두어 여러 Gateway 인스턴스로 트래픽을 분산할 수 있습니다.
핵심 역할
인증 및 보안 (Authentication)
Datadog, AWS, Splunk 등 외부 백엔드로 데이터를 전송할 때 필요한 API Key(Secret)를 Gateway에서만 관리합니다. 수백 개의 Agent에 개별적으로 키를 배포할 필요가 없으므로 보안 관리가 간소화됩니다. 공식 문서에서도 Gateway의 장점으로 "centrally managed credentials"를 명시하고 있습니다.
데이터 가공 및 제어
- Tail-based Sampling: 트레이스의 모든 스팬이 수집된 후 전체를 보고 샘플링 여부를 결정하는 고급 샘플링입니다. 에이전트는 분산된 트레이스의 일부 조각(로컬 스팬)만 볼 수 있어 전체 문맥을 파악할 수 없으므로, loadbalancing exporter를 통해 동일한 Trace ID를 가진 스팬을 한곳으로 모아주는 Gateway 환경에서 수행해야 합니다.
- Batching:
batchprocessor로 데이터를 묶어서 전송하여 백엔드 API 호출 횟수를 줄이고 네트워크 효율을 높입니다.
네트워크 관리
사내망(Private Network)에서 외부망(Public Network)으로 나가는 접점을 Gateway 하나로 통일할 수 있습니다. 방화벽에서 허용해야 할 outbound 엔드포인트가 Gateway의 IP만으로 한정되므로 네트워크 보안 관리가 쉬워집니다.
설정 예시: Load Balancing Exporter
tail sampling처럼 같은 trace의 스팬이 동일한 Collector에 모여야 하는 경우, loadbalancingexporter를 사용하여 2-tier 구조를 구성합니다.
1차 티어 (로드밸런싱 Collector):
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
exporters:
loadbalancing:
routing_key: traceID
protocol:
otlp:
tls:
insecure: true
resolver:
dns:
hostname: collectors.example.com
service:
pipelines:
traces:
receivers: [otlp]
exporters: [loadbalancing]
routing_key 옵션:
traceID: 같은 trace ID를 가진 스팬을 동일한 Collector로 라우팅합니다. tail sampling에 필수입니다.service: 같은 서비스의 스팬을 동일한 Collector로 라우팅합니다. span metrics connector 사용 시 정확한 집계를 보장합니다.
장단점
| 장점 | 단점 |
|---|---|
| 인증/정책을 중앙에서 관리 가능 | 추가 인프라 운영 필요 |
| 독립적으로 스케일링 가능 | 단일 장애점(SPOF) 가능성 |
| tail sampling 등 고급 처리 가능 | Agent 대비 구성 복잡도 증가 |
Agent + Gateway 조합 패턴
실무에서는 Agent와 Gateway를 함께 사용하는 것이 일반적입니다. 공식 문서에서도 이 조합 패턴을 설명하고 있습니다.
[앱] → [Agent Collector (DaemonSet)] → [Gateway Collector (Deployment)] → [백엔드]
| 역할 | Agent | Gateway |
|---|---|---|
| 배포 방식 | DaemonSet / Sidecar | Deployment |
| 위치 | 앱과 같은 호스트 | 독립된 서비스 |
| 주요 역할 | 호스트 메트릭/로그 수집, resource detection, 초기 배치 처리 | 필터링, tail sampling, 백엔드 export, 인증 관리 |
| 스케일링 | 호스트 수에 비례 | 트래픽 양에 따라 독립적 |
이 구조를 사용하면 호스트 종속 정보는 Agent에서 정확하게 수집하고, 리소스 집약적인 처리는 Gateway에서 중앙 관리할 수 있습니다.
FAQ ) Agent 없이 Gateway만 쓰면 안 되나요?
가능은 하지만, Kubernetes 인프라 정보(Pod Name, Host IP, Namespace 등)를 자동으로 태깅하기 어렵습니다.
k8sattributesprocessor는 수신 요청의 IP 주소를 기반으로 데이터를 보낸 Pod를 식별하는데, Gateway는 애플리케이션과 다른 호스트에서 실행되므로 원본 Pod의 IP를 정확히 매칭하기 어렵습니다.
또한 hostmetricsreceiver나 resourcedetectionprocessor 같은 호스트 종속 컴포넌트는 Gateway에서 실행하면 애플리케이션이 아닌 Gateway 호스트의 정보를 수집하게 되어 잘못된 데이터가 기록됩니다.
주의사항: Single-Writer Principle (단일 기록자 원칙)
Collector를 배포할 때 반드시 지켜야 하는 원칙입니다. OpenTelemetry 메트릭 데이터 모델 스펙에서는 모든 메트릭 데이터 스트림이 단 하나의 논리적 작성자(Single Writer)만 가져야 한다고 명시하고 있습니다. 즉, 동일한 데이터 소스를 여러 Collector가 동시에 수집하면 안 됩니다. (OpenTelemetry Metrics Data Model - Single-Writer)
위반 시 발생하는 문제
만약 host-A의 CPU 메트릭을 Collector-1과 Collector-2가 동시에 수집해서 보낸다면 다음과 같은 문제가 발생합니다.
데이터 품질 저하
리소스 식별자가 고유하지 않으면 백엔드에서 데이터가 서로 덮어씌워지거나 충돌합니다. 그래프가 끊기거나(Gaps), 값이 갑자기 튀는(Jumps) 현상이 발생합니다.
백엔드 에러 (예: Prometheus)
Error on ingesting out-of-order samples
타임스탬프 순서가 꼬이면서 발생하는 에러입니다. 예를 들어:
- Collector-1이
13:56:04의 데이터(값 100)를 전송 - Collector-1이
13:56:24의 데이터(값 120)를 전송 - Collector-2가
13:56:04의 데이터(값 110)를 전송
3번 시점에서 Prometheus는 이미 13:56:24까지의 데이터를 수신한 상태이므로, 과거 타임스탬프(13:56:04)의 데이터가 도착하면 out-of-order로 판단하여 에러를 발생시키고 해당 데이터를 버립니다.
해결 방법
스펙에서 제시하는 해결 방법은 두 가지입니다:
- 각 Collector가 service.instance.id와 같은 고유 식별자(Resource 속성)를 서로 다르게 설정하여, 백엔드가 이를 서로 다른 메트릭 스트림으로 인식하게 구분
- 동일한
Resource와Attribute조합의 스트림이 시간적으로 겹치지 않도록 보장
Agent를 DaemonSet으로 배포하여 호스트당 하나의 Collector만 메트릭을 수집하도록 구성하면 이 원칙을 자연스럽게 지킬 수 있습니다.
'SRE' 카테고리의 다른 글
| [번역] 구글 SRE, 20년 경험으로 얻은 교훈들 (4) | 2025.08.01 |
|---|