Opentelemetry로 멀티클러스터 Observablity 시스템 구성하기
목차
참고 자료
Opentelemetry 소개
Opentelemetry이란 무엇인가?
OpenTelemetry는 분산된 시스템에서 성능 데이터를 수집, 처리, 내보내는 것을 표준화한 오픈소스 Observability 프레임워크입니다. 주로 애플리케이션의 메트릭, 로그, 트레이스를 수집하고 이를 분석 도구나 관측 플랫폼으로 전송하는 데 사용됩니다.
Opentelemetry의 기본 구성
OpenTelemetry의 주요 개념
OpenTelemetry는 분산시시템에 대한 상태 및 성능 대한 정보를 가지고 있는 데이터를 다룹니다.
-
Metric: CPU 사용량, 메모리 사용량, 요청 처리 시간 등과 같은 정량적인 성능 데이터를 수집합니다. 이를 통해 시스템 성능 상태를 모니터링하고 알림을 설정할 수 있습니다.
-
Log: 애플리케이션의 이벤트, 오류 메시지 등을 기록하는 방식입니다. 로그는 발생한 문제나 이슈를 디버깅하는 데 매우 유용합니다.
-
Trace: 분산 시스템에서 각 서비스나 컴포넌트 간의 요청 흐름을 추적하는 기능입니다. 이를 통해 애플리케이션의 성능을 분석하고, 문제가 발생한 지점을 식별할 수 있습니다.
OpenTelemetry의 구성
- SDK: 애플리케이션에서 OpenTelemetry를 사용하여 데이터를 생성하고 수집하는 라이브러리입니다.
- Collector: 여러 서비스로부터 메트릭, 로그, 트레이스를 수집하여 이를 다양한 백엔드 시스템(예: Prometheus, Jaeger, Loki 등)에 전송할 수 있는 구성 요소입니다.
- Exporter: 데이터를 원하는 백엔드로 내보내는 모듈입니다. 예를 들어, 로그를 Loki로 보내거나 트레이스를 Jaeger로 보낼 수 있습니다.
Opentelemetry 설치 및 설정
Opentelemetry 설치하기
OpenTelemetry를 쿠버네티스(Kubernetes) 환경에 설치하는 방법은 여러 가지가 있습니다. 그중에서 쿠버네티스에서는 일반적으로는 OpenTelemetry Collector를 Operator로 설치하여 데이터를 수집하고 처리하는 방식이 적합합니다.
OpenTelemetry Operator는 쿠버네티스에서 OpenTelemetry Collector를 자동으로 관리하는 Kubernetes Operator입니다. 이를 통해 클러스터에서 Collector를 더 쉽게 배포하고 관리할 수 있습니다.
설치 단계: OpenTelemetry Operator 설치: 먼저 OpenTelemetry Operator를 설치합니다.
kubectl apply -f https://github.com/open-telemetry/opentelemetry-operator/releases/download/v0.65.0/opentelemetry-operator.yaml
Collector 리소스 생성: OpenTelemetryCollector CRD(Custom Resource Definition)를 사용하여 Collector 인스턴스를 정의할 수 있습니다. 예를 들어:
apiVersion: opentelemetry.io/v1alpha1
kind: OpenTelemetryCollector
metadata:
name: simplest
spec:
config: |
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
exporters:
# NOTE: Prior to v0.86.0 use `logging` instead of `debug`.
debug:
service:
pipelines:
traces:
receivers: [otlp]
processors: []
exporters: [debug]
Collector 배포: 위에서 작성한 CRD를 적용하여 OpenTelemetry Collector를 배포합니다.
kubectl apply -f otel-collector-crd.yaml
Opentelemetry 설정
OpenTelemetry가 데이터를 어떻게 수줍하고 처리할지는 OpentelemetryCollector 리소스를 생성할 떄 config 부분애 설정합니다. config 부분은 다음과 같이 4가지 항목으로 구성됩니다. 이중에서 receivers와 exporters는 plugin 형태이며 연동하고자 하는 tool와 맞는 plugin을 선택해서 사용합니다.
- receivers: telemetry 데이터를 어디서 어떻게 수집할지 설정하는 부분입니다.
- processors: 수집한 데이터를 가공하거나 변경할 수 있는 기능입니다.
- exporters: 최종 데이터를 어디로 어떤 프로토콜로 보낼자 설정합니다.
- service: 위 3가지 plugin들을 이용해서 실제로 데이터를 수집하고 처리할 파이프라인을 구성합니다.
service 하위에 있는 pipelines 항목에는 여러개의 pipeline을 정의할 수 있으며 위 예제와 같이 logs, metrics, traces 로 구분해서 정의합니다. 즉 하나의 OpenTelemetry Collector에서 3가지 telemetry 데이터 모두에 대한 처리를 할 수 있다는 것입니다.
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
batch:
exporters:
otlp:
endpoint: otelcol:4317
extensions:
health_check:
pprof:
zpages:
service:
extensions: [health_check, pprof, zpages]
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [otlp]
metrics:
receivers: [otlp]
processors: [batch]
exporters: [otlp]
logs:
receivers: [otlp]
processors: [batch]
exporters: [otlp]
Opentelemetry로 모니터링 시스템 구성하기
OpenTelemtry로 수집한 telemetry 데이터를 저정하는 저장소와 시각화 툴을 연동해야 온전한 모니탕링 시스템이 됩니다. 여기서 OpenTelemetry + GrafanaStack을 이용한 모니터링 시스템을 보여주고 있습니다.
apiVersion: opentelemetry.io/v1alpha1
kind: OpenTelemetryCollector
metadata:
name: otel-collector
spec:
mode: deployment
config: |
receivers:
filelog:
exclude:
- /var/log/pods/*/otel-collector/*.log
include:
- /var/log/pods/*/*/*.log
include_file_name: false
include_file_path: true
start_at: beginning
prometheus:
config:
scrape_configs:
- enable_compression: true
enable_http2: true
follow_redirects: true
honor_timestamps: true
job_name: otel-qks-mariadb
kubernetes_sd_configs:
- enable_http2: true
follow_redirects: true
kubeconfig_file: ""
namespaces:
names:
- accu
own_namespace: false
role: endpoints
metrics_path: /metrics
relabel_configs:
- action: replace
replacement: $$1
separator: ;
source_labels:
- job
target_label: __tmp_prometheus_job_name
- action: keep
regex: (accu-mariadb);true
replacement: $$1
separator: ;
source_labels:
- __meta_kubernetes_service_label_app_kubernetes_io_instance
- __meta_kubernetes_service_labelpresent_app_kubernetes_io_instance
scheme: http
scrape_interval: 15s
scrape_protocols:
- OpenMetricsText1.0.0
- OpenMetricsText0.0.1
- PrometheusText0.0.4
scrape_timeout: 10s
track_timestamps_staleness: false
exporters:
debug: {}
loki:
endpoint: http://loki-gateway.accu-monitoring.svc.cluster.local/loki/api/v1/push
otlp:
endpoint: http://otel.accuinsight.co:80
tls:
insecure: true
otlphttp:
endpoint: http://loki.accu-monitoring.svc.cluster.local:3100/otlp
processors:
attributes/clustername:
actions:
- action: insert
key: cluster_name
value: sk
transform:
metric_statements:
- context: datapoint
statements:
- set(attributes["namespace"], resource.attributes["k8s.namespace.name"])
- set(attributes["container"], resource.attributes["k8s.container.name"])
- set(attributes["pod"], resource.attributes["k8s.pod.name"])
service:
pipelines:
logs:
exporters:
- loki
receivers:
- filelog
metrics:
exporters:
- debug
- otlp
processors:
- transform
- attributes/clustername
receivers:
- prometheus
Opentelemetry로 MultiCluster 모니터링 시스템 구성하기
OpenTelemetry는 자체적으로 지원하는 OTLP 프로토클로 외부 시스템과 연동뿐만 아니라 Collector끼리 서로 연동할 수 있습니다. 이 기능을 이용하면 아래 그림과 같이 Workload 클러스터에 있는 Collector들이 수집한 데이터를 중앙에 있는 Management 클러스터에 설치된 Collector로 전송하고 메인 Collector는 각 telemetry 데이터를 해당 백엔드 저장소에 저장하고 이를 Grafana 시각화하는 방식입니다.
아래 메인 Collector 설정 예시입니다:
apiVersion: opentelemetry.io/v1alpha1
kind: OpenTelemetryCollector
metadata:
name: qks-main-collector
spec:
mode: deployment
serviceAccount: qks-opentelemetry-collector
managementState: managed
config: |
receivers:
otlp:
protocols:
http: {}
grpc: {}
processors: {}
exporters:
debug: {}
prometheus:
endpoint: 0.0.0.0:9090
service:
pipelines:
metrics:
receivers: [otlp]
processors: []
exporters: [debug, prometheus]
각 workload 클러스터에 있는 Collector는 아래와 같이 설정합니다. 여기서 핵심은 export 부분에 메인 collector로 otlp로 프로토클로 데이터 전송한다는 설정입니다.
그리고 각 workload 클러스터에서 수집된 metric 정보를 구분하기 위해 모든 metric에 cluster_name 항목을 추가해주는 processer가 있습니다.
apiVersion: opentelemetry.io/v1alpha1
kind: OpenTelemetryCollector
metadata:
name: qks-collector
spec:
mode: deployment
serviceAccount: qks-opentelemetry-collector
config: |
receivers:
prometheus:
config:
scrape_configs:
- job_name: qks-mariadb-otel
honor_timestamps: true
track_timestamps_staleness: false
scrape_interval: 15s
scrape_timeout: 10s
scrape_protocols:
- OpenMetricsText1.0.0
- OpenMetricsText0.0.1
- PrometheusText0.0.4
metrics_path: /metrics
scheme: http
enable_compression: true
follow_redirects: true
enable_http2: true
relabel_configs:
- source_labels: [job]
separator: ;
target_label: __tmp_prometheus_job_name
replacement: $$1
action: replace
- source_labels: [__meta_kubernetes_service_label_app_kubernetes_io_instance, __meta_kubernetes_service_labelpresent_app_kubernetes_io_instance]
separator: ;
regex: (qks-mariadb);true
replacement: $$1
action: keep
...
생략
...
kubernetes_sd_configs:
- role: endpoints
kubeconfig_file: ""
follow_redirects: true
enable_http2: true
namespaces:
own_namespace: false
names:
- qks
processors:
transform:
metric_statements:
- context: datapoint
statements:
- set(attributes["namespace"], resource.attributes["k8s.namespace.name"])
- set(attributes["container"], resource.attributes["k8s.container.name"])
- set(attributes["pod"], resource.attributes["k8s.pod.name"])
attributes/clustername:
actions:
- key: cluster_name
value: "qms"
action: insert
exporters:
# NOTE: Prior to v0.86.0 use `logging` instead of `debug`.
debug: {}
otlp:
endpoint: http://otel.quantumcns.ai:80 # The address of the second collector
tls:
insecure: true
service:
pipelines:
metrics:
receivers: [prometheus]
processors: [transform, attributes/clustername]
exporters: [debug, otlp]