본문으로 건너뛰기

OpenTelemetry

OpenTelemetry는 Lumie 인프라의 통합 관찰 가능성 플랫폼으로, 메트릭, 로그, 트레이스를 단일 파이프라인을 통해 수집, 처리, 전송하는 역할을 담당합니다.

아키텍처

배포 구성

  • Operator 네임스페이스: opentelemetry-operator
  • Collector 네임스페이스: opentelemetry
  • 배포 모드: DaemonSet (각 노드에 하나씩)
  • 이미지: zot.lumie-infra.com/open-telemetry/opentelemetry-collector-releases/opentelemetry-collector-contrib:0.144.0

구성 요소

OpenTelemetry Operator

설치 및 설정

Operator는 OpenTelemetryCollector 커스텀 리소스를 관리합니다:

# Operator 설정
manager:
image:
repository: zot.lumie-infra.com/open-telemetry/opentelemetry-operator/opentelemetry-operator
tag: "0.141.0"

# 기본 이미지 설정
collectorImage:
repository: zot.lumie-infra.com/open-telemetry/opentelemetry-collector-releases/opentelemetry-collector-contrib
tag: "0.144.0"

targetAllocatorImage:
repository: zot.lumie-infra.com/open-telemetry/opentelemetry-operator/target-allocator
tag: "0.141.0"

웹훅 설정

admissionWebhooks:
certManager:
enabled: false # 자체 서명 인증서 사용
namespaceSelector:
matchLabels:
opentelemetry-auto-instrumentation: "enabled" # 자동 계측 비활성화

OpenTelemetry Collector

DaemonSet 배포

각 노드에서 실행되어 해당 노드의 모든 텔레메트리 데이터를 수집합니다:

spec:
mode: daemonset

# 호스트 포트 노출
ports:
- name: otlp
port: 4317
protocol: TCP
hostPort: 4317 # gRPC
- name: otlp-http
port: 4318
protocol: TCP
hostPort: 4318 # HTTP

볼륨 마운트

컨테이너 로그 수집을 위한 호스트 볼륨 마운트:

volumeMounts:
- name: varlogpods
mountPath: /var/log/pods
readOnly: true
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true

volumes:
- name: varlogpods
hostPath:
path: /var/log/pods
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers

Target Allocator

개요

Target Allocator는 ServiceMonitor를 읽어 Prometheus 스크래핑 대상을 여러 Collector 인스턴스에 분산 할당합니다.

설정

targetAllocator:
enabled: true
allocationStrategy: per-node
serviceAccount: otel-collector-targetallocator

# ServiceMonitor 자동 발견
prometheusCR:
enabled: true
serviceMonitorSelector: {}
podMonitorSelector: {}

resources:
requests:
cpu: 15m
memory: 175Mi
limits:
memory: 237Mi

RBAC 권한

# Target Allocator 권한
rules:
- apiGroups: ["monitoring.coreos.com"]
resources:
- servicemonitors
- podmonitors
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources:
- namespaces
- nodes
- services
- endpoints
- pods
verbs: ["get", "list", "watch"]

수신기 (Receivers)

OTLP 수신기

애플리케이션에서 직접 전송되는 텔레메트리 데이터를 수신합니다:

receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318

Filelog 수신기

컨테이너 로그를 수집하여 Loki로 전송합니다:

filelog:
include:
- /var/log/pods/*/*/*.log
exclude:
- /var/log/pods/opentelemetry_otel-collector*/*/*.log
start_at: end
include_file_path: true

operators:
# Docker/containerd 로그 형식 파싱
- type: router
routes:
- output: parser-docker
expr: 'body matches "^\\{"'
- output: parser-containerd
expr: 'body matches "^[^ Z]+Z"'

# 메타데이터 추출
- type: regex_parser
id: extract-metadata-from-filepath
regex: '^.*\/(?P<namespace>[^_]+)_(?P<pod_name>[^_]+)_(?P<uid>[a-f0-9-]+)\/(?P<container_name>[^\/]+)\/.*$'
parse_from: attributes["log.file.path"]

Prometheus 수신기

Target Allocator를 통해 ServiceMonitor 기반 메트릭을 수집합니다:

prometheus:
config:
scrape_configs: [] # Target Allocator가 동적 생성
target_allocator:
endpoint: http://otel-collector-targetallocator:80
interval: 30s
collector_id: ${env:K8S_POD_NAME}

처리기 (Processors)

배치 처리기

효율적인 데이터 전송을 위한 배치 처리:

processors:
batch:
timeout: 10s
send_batch_size: 1024
send_batch_max_size: 2048

메모리 제한기

메모리 사용량 제한:

memory_limiter:
check_interval: 5s
limit_mib: 400
spike_limit_mib: 100

Kubernetes 속성 추가

Kubernetes 메타데이터를 텔레메트리 데이터에 추가:

k8sattributes:
extract:
metadata:
- k8s.namespace.name
- k8s.deployment.name
- k8s.pod.name
- k8s.node.name
passthrough: false
pod_association:
- sources:
- from: resource_attribute
name: k8s.pod.ip
- sources:
- from: resource_attribute
name: k8s.pod.uid

리소스 감지

시스템 및 환경 정보 추가:

resourcedetection:
detectors: [env, system]
timeout: 5s
override: false

내보내기 (Exporters)

Prometheus (OTLP HTTP)

Prometheus 3.0+의 네이티브 OTLP 수신기로 메트릭 전송:

otlphttp/prometheus:
endpoint: http://prometheus-kube-prometheus-prometheus.prometheus.svc:9090/api/v1/otlp
tls:
insecure: true

Loki (OTLP HTTP)

로그 데이터를 Loki로 전송:

otlphttp/loki:
endpoint: http://loki.loki.svc.cluster.local:3100/otlp
tls:
insecure: true

Tempo (OTLP gRPC)

트레이스 데이터를 Tempo로 전송:

otlp/tempo:
endpoint: tempo.tempo.svc.cluster.local:4317
tls:
insecure: true

파이프라인 구성

메트릭 파이프라인

service:
pipelines:
metrics:
receivers: [otlp, prometheus]
processors: [memory_limiter, k8sattributes, resourcedetection, batch]
exporters: [otlphttp/prometheus]

로그 파이프라인

logs:
receivers: [otlp, filelog]
processors: [memory_limiter, k8sattributes, resourcedetection, batch]
exporters: [otlphttp/loki]

트레이스 파이프라인

traces:
receivers: [otlp]
processors: [memory_limiter, k8sattributes, resourcedetection, batch]
exporters: [otlp/tempo]

리소스 설정

Collector

피크 관측 메모리를 기준으로 설정된 값입니다. VPA 대상에서 제외된 Operator 관리 DaemonSet이므로 수동 사이징을 적용합니다:

resources:
requests:
cpu: 15m
memory: 256Mi
limits:
memory: 512Mi # CPU 제한 없음

Target Allocator

resources:
requests:
cpu: 15m
memory: 175Mi
limits:
memory: 237Mi

애플리케이션 계측

환경 변수 설정

애플리케이션에서 OpenTelemetry를 사용하기 위한 환경 변수:

env:
- name: OTEL_EXPORTER_OTLP_ENDPOINT
value: "http://localhost:4317" # 호스트 포트 사용
- name: OTEL_SERVICE_NAME
value: "my-service"
- name: OTEL_RESOURCE_ATTRIBUTES
value: "service.version=1.0.0,deployment.environment=production"

Java 애플리케이션

// OpenTelemetry 자동 계측 에이전트 사용
// JVM 옵션에 추가:
-javaagent:opentelemetry-javaagent.jar
-Dotel.exporter.otlp.endpoint=http://localhost:4317
-Dotel.service.name=my-java-service

Node.js 애플리케이션

// package.json
{
"dependencies": {
"@opentelemetry/api": "^1.7.0",
"@opentelemetry/sdk-node": "^0.45.0",
"@opentelemetry/exporter-otlp-grpc": "^0.45.0"
}
}

// app.js
const { NodeSDK } = require('@opentelemetry/sdk-node');
const { OTLPTraceExporter } = require('@opentelemetry/exporter-otlp-grpc');

const sdk = new NodeSDK({
traceExporter: new OTLPTraceExporter({
url: 'http://localhost:4317',
}),
serviceName: 'my-node-service',
});

sdk.start();

모니터링 및 문제 해결

Collector 상태 확인

# OpenTelemetryCollector 리소스 확인
kubectl get otelcol -n opentelemetry

# Collector 파드 상태
kubectl get pods -n opentelemetry

# Collector 로그 확인
kubectl logs -n opentelemetry daemonset/otel-collector-collector

Target Allocator 상태 확인

# Target Allocator 로그
kubectl logs -n opentelemetry deployment/otel-collector-targetallocator

# 할당된 타겟 확인
kubectl port-forward -n opentelemetry svc/otel-collector-targetallocator 8080:80
curl -s http://localhost:8080/jobs | jq

메트릭 확인

# Collector 자체 메트릭
kubectl port-forward -n opentelemetry daemonset/otel-collector-collector 8888:8888
curl -s http://localhost:8888/metrics

일반적인 문제

데이터가 수집되지 않는 경우

# 수신기 상태 확인
kubectl logs -n opentelemetry daemonset/otel-collector-collector | grep -i receiver

# 네트워크 연결 확인
kubectl exec -n opentelemetry daemonset/otel-collector-collector -- \
netstat -tlnp | grep -E "(4317|4318)"

높은 메모리 사용량

# 메모리 사용량 확인
kubectl top pods -n opentelemetry

# 배치 크기 조정 (설정 수정 필요)
# batch processor의 send_batch_size 값 감소

ServiceMonitor 발견 문제

# ServiceMonitor 목록 확인
kubectl get servicemonitors -A

# Target Allocator가 발견한 타겟 확인
curl -s http://otel-collector-targetallocator.opentelemetry.svc.cluster.local/targets

성능 최적화

배치 처리 최적화

processors:
batch:
timeout: 5s # 더 짧은 타임아웃
send_batch_size: 512 # 더 작은 배치 크기
send_batch_max_size: 1024

메모리 제한 조정

memory_limiter:
check_interval: 1s
limit_mib: 300 # 더 낮은 제한
spike_limit_mib: 50

샘플링 설정

processors:
probabilistic_sampler:
sampling_percentage: 10 # 10% 샘플링

보안 고려사항

네트워크 보안

  • 호스트 포트 사용으로 인한 보안 고려
  • 클러스터 내부 통신만 허용
  • TLS 설정 (필요시)

RBAC 최소 권한

각 구성 요소에 필요한 최소 권한만 부여:

# Collector RBAC
rules:
- apiGroups: [""]
resources: ["nodes", "pods", "services", "endpoints"]
verbs: ["get", "list", "watch"]

관련 문서