OpenTelemetry Collector 아키텍처
이 회고는 2026년 1월 13일 observability 설계가 Prometheus-first scraping에서 OpenTelemetry collector-first 모델로 이동한 이유를 설명합니다.
원래 기록은 여전히 가치가 있지만, checked-in topology는 이후 바뀌었습니다. 이 문서는 지속되는 아키텍처 결정과 drift된 세부사항을 분리합니다.
소스 경로
todo/incidents/trouble/opentelemetry-collector-architecture-2026-01-13.mdlumie-infra/observability/kustomization.yamllumie-infra/observability/opentelemetry/manifests/collector.yamllumie-infra/observability/opentelemetry/manifests/targetallocator-rbac.yamllumie-infra/observability/opentelemetry-operator/helm-values.yamllumie-infra/observability/prometheus/helm-values.yamllumie-infra/security/kyverno/manifests/policies/remove-cpu-limits.yaml
배경
이전 mental model은 Prometheus를 기본 collector로 봤습니다. Scrape-oriented metric에는 작동했지만 Lumie에는 다음도 필요했습니다.
- application OTLP trace
- application/container log
- monitor resource를 통해 discover되는 Kubernetes metric
- log는 Loki, trace는 Tempo로 보내는 더 명확한 경로
- observability component마다 중복되는 scraping logic 감소
지속되는 결정은 OpenTelemetry를 shared collection layer로 두고, 각 backend가 signal type별 storage/query를 소유하게 하는 것입니다.
지속 설계 결정
1월 아키텍처 기록의 세 결정은 여전히 repo와 맞습니다.
| 결정 | 현재 의미 |
|---|---|
| OpenTelemetry가 shared collection layer입니다 | app OTLP traffic, Kubernetes scrape target, container log가 collector를 통과합니다 |
| Prometheus는 대부분 workload metric의 기본 scraper가 아닙니다 | Prometheus는 metric을 저장하고 제공하지만, collection work의 상당 부분은 collector-managed pipeline이 담당합니다 |
| Storage는 signal-specific으로 남습니다 | metric은 Prometheus, log는 Loki, trace는 Tempo가 맡습니다 |
Repo-level observability kustomization은 이 결정의 중요한 결과를 보존합니다.
# promtail removed - OTel filelog receiver handles log collection
Source: lumie-infra/observability/kustomization.yaml
현재 repo-managed contract
현재 topology는 하나의 OpenTelemetryCollector custom resource로 정의됩니다.
| 구성요소 | 현재 모드 | checked-in 책임 |
|---|---|---|
otel-collector | daemonset | OTLP traffic을 받고, /var/log/pods를 tail하며, Target Allocator가 discover한 target을 scrape합니다 |
| Target Allocator | collector spec 안에서 enabled | ServiceMonitor와 PodMonitor를 읽고 scrape work를 collector pod에 할당합니다 |
| Prometheus | single replica | OTLP receiver를 enable하고 자체 scrape는 scrape-by: prometheus-only target으로 제한합니다 |
| Loki | OTLP HTTP endpoint | collector에서 log를 받습니다 |
| Tempo | OTLP gRPC endpoint | collector에서 trace를 받습니다 |
다음 excerpt가 live contract를 보여줍니다.
spec:
mode: daemonset
targetAllocator:
enabled: true
allocationStrategy: per-node
Source: lumie-infra/observability/opentelemetry/manifests/collector.yaml
enableOTLPReceiver: true
enableRemoteWriteReceiver: false
serviceMonitorSelector:
matchLabels:
scrape-by: prometheus-only
Source: lumie-infra/observability/prometheus/helm-values.yaml
1월 기록에서 달라진 점
몇 가지 원래 세부사항은 더 이상 checked-in contract가 아닙니다.
| 1월 기록 | 현재 repo 상태 |
|---|---|
별도 otel-metrics, otel-logs collector | 하나의 otel-collector DaemonSet이 metrics, logs, traces를 처리합니다 |
| metrics StatefulSet 전반의 Target Allocator consistent hashing | collector manifest는 allocationStrategy: per-node를 설정합니다 |
| Prometheus를 remote-write receiver로 사용 | Prometheus는 native OTLP receiver를 enable하고 remote write receiver를 disable합니다 |
| Thanos가 active query path 일부 | observability kustomization은 thanos/argocd.yaml를 주석 처리하며, 현재 footprint plan은 Thanos를 disable 상태로 둡니다 |
lumie-infra/observability/prometheus/helm-values.yaml에도 작은 comment drift가 있습니다. Comment는 여전히 collector remote write를 언급하지만, collector.yaml의 active exporter는 otlphttp/prometheus이고 enableRemoteWriteReceiver는 false입니다. Active exporter/receiver setting이 기준입니다.
운영상 의미
Collector-first observability는 failure domain을 바꿉니다.
| 의미 | 운영 해석 |
|---|---|
| 하나의 collector DaemonSet이 여러 signal을 처리합니다 | collector rollout 문제가 metrics, logs, traces를 함께 저하시킬 수 있습니다 |
| Target Allocator가 scrape assignment를 소유합니다 | ServiceMonitor만으로 특정 collector pod가 target을 scrape한다고 증명할 수 없습니다 |
| Prometheus scrape role이 좁아집니다 | Prometheus-native scraping이 필요한 target은 scrape-by: prometheus-only로 opt in해야 합니다 |
| CPU throttling이 중요합니다 | collector/operator values는 CPU limit을 생략하고, Kyverno가 remove-cpu-limits로 일반 pod CPU limit을 제거합니다 |
Collector는 sidecar convenience가 아니라 infrastructure dependency가 됐습니다.
검증
현재 계약은 read-only check로 검증합니다.
kubectl get applications.argoproj.io -n argocd opentelemetry opentelemetry-operator prometheus
kubectl get opentelemetrycollectors.opentelemetry.io -n opentelemetry
kubectl get pods -n opentelemetry -o wide
kubectl logs -n opentelemetry daemonset/otel-collector-collector --tail=200
kubectl get clusterpolicy remove-cpu-limits -o yaml
성공 기준은 다음입니다.
- collector와 operator Application이 존재합니다.
OpenTelemetryCollectorcustom resource가 존재합니다.- DaemonSet이 node에서 실행 중입니다.
- collector log가 live pipeline을 보여줍니다.
- CPU-limit removal policy가 설치되어 있습니다.
잘된 점
- Collection과 storage/query backend를 분리했습니다.
- Log, metric, trace가 서로 무관한 세 mechanism이 아니라 하나의 collection plane으로 이동했습니다.
- Prometheus는 명확한 역할을 유지하면서도 모든 scrape path를 책임지지 않게 됐습니다.
- 현재 manifest state와 역사적 note를 구분할 만큼 repo 정보가 문서화됐습니다.
아쉬웠던 점
- 원본 기록과 현재 manifest가 collector 수, target allocation strategy, Prometheus receiver mode, Thanos 상태에서 drift됐습니다.
- Collector-first design은 collector outage의 blast radius를 키웁니다.
- 구현이 바뀐 뒤에도 일부 comment가 stale하게 남았습니다.
- Operator는 일반 Kubernetes monitor resource뿐 아니라 Target Allocator visibility도 봐야 합니다.
액션 아이템
| 작업 | 소유 영역 | 상태 | 증거 |
|---|---|---|---|
Observability topology가 바뀌면 이 문서를 collector.yaml과 Prometheus values에 맞춰 유지합니다. | lumie-document, lumie-infra | 지속 | 이 회고는 1월 기록과의 known drift를 기록합니다. |
| Observability manifest를 수정할 때 stale Prometheus values comment를 고칩니다. | lumie-infra/observability/prometheus/helm-values.yaml | 계획 | Active config는 remote write receiver가 아니라 OTLP receiver를 사용합니다. |
| CPU-limit removal policy를 보존하거나 예외를 명시적으로 문서화합니다. | lumie-infra/security/kyverno | 지속 | remove-cpu-limits는 현재 운영 계약의 일부입니다. |
교훈
- Collector-first design은 collector failure domain을 shared infrastructure로 다룰 때만 이해하기 쉬워집니다.
- Historical architecture note는 manifest가 바뀌면 drift section이 필요합니다.
- Prometheus는 metrics backend로 남을 수 있지만 universal metrics collector로 남을 필요는 없습니다.
- Values file의 comment는 오해를 만들 수 있습니다. Active manifest와 receiver/exporter setting이 기준입니다.
관련 문서
- OpenTelemetry operations reference
- OpenTelemetry Operator operations reference
- Prometheus operations reference