쿠버네티스 교육

Tracing - OpenTelemetry + Tempo

Jerry_이정훈 2023. 5. 31. 15:38
728x90

회사에서 테스트한 Tracing 내역을 공유합니다.



Observability 중 metric(Prometheus), logging(Loki)은 구성하였는데 tracing은 구축하지 않았다. 대중화되지 않고 개발자도 익숙하지 않아 어떻게 사용하는지 모르는 경우가 많다. 아마도 APM을 사용하지 않는 회사라면 크게 쓸모를 못 느낄 듯.

 

간단히 트레이싱의 정의를 알아보면 다음과 같다. 

트레이싱(Tracing)은 소프트웨어 개발과 성능 모니터링 관점에서, 요청 또는 트랜잭션이 응용 프로그램이나 시스템의 다양한 구성 요소를 통과하는 과정을 추적하고 모니터링하는 것을 말합니다. by 챗GPT

 

그림으로 표현하면 아래와 같다. 개인적으로 하나의 트랜잭션이 어디, 어디를 거치고 각 단계에서 얼마나 소요되는지 추적(tracing)하는 시스템 정도로 이해하고 있다.

 

from : https://marvel-b1-cdn.bc0a.com/f00000000236551/dt-cdn.net/wp-content/uploads/2021/06/traces_spans.png

 

MSA 환경이라 여러 애플리케이션 간 복잡하게 구성되는데 각각의 파드 혹은 외부 서비스(RDS, MSK 등) 간 소요 시간을 측정하여 어떤 단계에서 트랜잭션 시간이 많이 소요되었는지 알 수 있게한다. 많이 사용하고 있는 제니퍼 등의 APM(Application Performance Management)과 동일하다.

 

TL; DR;

. 쿠버네티스 환경에서 Open Telemetry, Tempo를 사용하여 Tracing 시스템 구축 사례 공유

. k8s Open Telemetry Operator를 사용하면 손쉽게 설치할 수 있다.

. Open Telemetry Auto Instrumenation 사용하면 소스 코드 수정없이 Application에서 Tracing 데이터를 가져올 수 있다.

. Tempo 사용하면 추가 대시보드 GUI 구축하지 않고 기존 Grafana를 사용할 수 있다.

. 설치 단계에서 각 도구 간 EndPoint 지정을 유의한다.

 

여러 Tracing 도구(대표적으로 Jaeger)를 사용할 수 있는데 이번에 테스트한 Tool Set은 Application에서 tracing 데이터를 가져오는 Open Telemetry instrumenation, 이를 1차 수집하는 Open Telemetry Collector, 그리고 이 데이터를 저장하는 backend로 사용하는 Tempo, 시각화하는 Grafana로 구성된다.

 

from : https://grafana.com/oss/opentelemetry/

 

그럼 실습으로 알아보자. 실습 내용은 아래와 같다.

 

. Cert-Manager 설치

. k8s Open Telemetry Operator 설치

. Grafana Tempo 설치

. Open Telemetry Collector + Auto Instrumentation 설치

. Grafana Tempo UI에서 Tracing Data 및 대시보드 확인

 

1. Cert-Manager 설치

cert-manager가 없으면 아래와 같이 opentelemetry-operator 설치 시 에러가 발생한다.

$ (⎈ |switch-seoul-stage:opentelemetry-operator-system) helm install opentelemetry-operator -f my-values.yaml .
Error: INSTALLATION FAILED: unable to build kubernetes objects from release manifest: [resource mapping not found for name: "opentelemetry-operator-serving-cert" namespace: "opentelemetry-operator-system" from "": no matches for kind "Certificate" in version "cert-manager.io/v1"
ensure CRDs are installed first, resource mapping not found for name: "opentelemetry-operator-selfsigned-issuer" namespace: "opentelemetry-operator-system" from "": no matches for kind "Issuer" in version "cert-manager.io/v1"
ensure CRDs are installed first]

에러 메시지는 'certificate'가 없다는 것이다. 설치에 인증서(certificate)를 사용하는데 참조할 수 있는 인증서가 없다는 메시지다. 쿠버네티스 cert-manager는 self-signed 인증서 발급, 갱신 등을 자동으로 진행하는 도구다.

 

공식 cert-manager 설치 가이드에 따라 헬름으로 설치한다. 공식 가이드는 CRD(Custom Resource Definition) 설치 옵션으로 헬름도 가능하다고 하는데 에러로 가이드에 따라 Manifest(명세서)로 설치하였다.

 

cert-manager CRD 설치

$ (⎈ |ypbooks:cert-manager) kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.12.0/cert-manager.crds.yaml
customresourcedefinition.apiextensions.k8s.io/clusterissuers.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/challenges.acme.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/certificaterequests.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/issuers.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/certificates.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/orders.acme.cert-manager.io created

다음으로 cert-manager 헬름 설치.

$ (⎈ |sent-seoul-stage:gmaestro) helm repo add jetstack https://charts.jetstack.io
$ (⎈ |sent-seoul-stage:gmaestro) helm repo update
$ (⎈ |sent-seoul-stage:gmaestro) k create ns cert-manager
$ (⎈ |sent-seoul-stage:gmaestro) k ns cert-manager

헬름 value 파일을 아래와 같이 수정한다. 이름을 my-values.yaml로 지정한다. 실습에 사용한 cert-manager 헬름 차트와 value 파일은 필자의 깃헙에서 확인할 수 있다.

prometheus:
  enabled: false

prometheus는 따로 설치하지 않는다. (enabled: false) 수정한 my-values.yaml 파일 기준으로 설치한다.

(⎈ |sent-seoul-stage:cert-manager) helm install \
  cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  -f my-values.yaml --version v1.12.1

참고로 나는 GitOps를 좀 더 용이하게 하기 위해 헬름 차트를 로컬에 다운받아서(helm pull) 사용한다.

 

설치가 완료되면 파드를 확인할 수 있다.

$ (⎈ |sent-seoul-stage:cert-manager) k get pod
NAME                                       READY   STATUS    RESTARTS   AGE
cert-manager-6f64976868-gh4n7              1/1     Running   0          3m37s
cert-manager-cainjector-86dcff788d-zt8hk   1/1     Running   0          3m37s
cert-manager-webhook-8cf9f8df6-bq69f       1/1     Running   0          3m37s

2. k8s Open Telemetry Operator 설치

Open Telemetry Operator CRD가 설치되어야 이 후에 설치할 open telemetry collector, auto instrumentation CRD를 사용할 수 있다.

 

공식 가이드에 따라 헬름으로 설치한다. 헬름 차트 레포를 추가한다.

$ (⎈ |sent-seoul-stage:cert-manager) helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts
$ (⎈ |sent-seoul-stage:cert-manager) helm repo update

공식 가이드의 네임스페이스 opentelemetry-operator-system 마음에 안들어 opentelemetry-operator로 지정하였다.

$ (⎈ |sent-seoul-stage:cert-manager) k create ns opentelemetry-operator
k ns namespace/opentelemetry-operator created
$ (⎈ |sent-seoul-stage:cert-manager) k ns opentelemetry-operator
$ (⎈ |sent-seoul-stage:opentelemetry-operator) helm install \
  opentelemetry-operator open-telemetry/opentelemetry-operator
  NAME: opentelemetry-operator
LAST DEPLOYED: Thu Jun  1 06:07:36 2023
NAMESPACE: opentelemetry-operator
STATUS: deployed
REVISION: 1
NOTES:
opentelemetry-operator has been installed. Check its status by running:
  kubectl --namespace opentelemetry-operator get pods -l "release=opentelemetry-operator"

Visit https://github.com/open-telemetry/opentelemetry-operator for instructions on how to create & configure OpenTelemetryCollector and Instrumentation custom resources by using the Operator.

operator 파드가 정상으로 설치되었다.

$ (⎈ |sent-seoul-stage:opentelemetry-operator) k get pod
NAME                                      READY   STATUS    RESTARTS   AGE
opentelemetry-operator-765fb59c47-fb848   2/2     Running   0          60s

3. Grafana Tempo 설치

Tempo는 open telemetry로 가져온 데이터를 저장하는 스토리지 설정을 포함한 백엔드 시스템이다. Prometheus, Loki가 exporter, promtail이 가져온 데이터를 처리, 저장하는 용도로 사용하는 것과 동일하다.

 

Tempo만 자세하게 그림으로 나타내면 아래와 같다. Open Telemetry로 정의된 데이터를 받아서 가공, 저장하고 이를 Query해서 Grafana 시각화 도구로 표현해준다. 구성은 Logging 시스템의 Promtail에서 데이터를 받아와 처리하는 Loki와 매우 유사하다.

 

from : https://grafana.com/docs/tempo/latest/operations/architecture/

 

그럼 헬름으로 설치한다. 공식 설치 가이드

(참고로 로키부터 느끼는 거지만 그라파나는 문서가 그리 친절하지 않다)

 

tempo 네임스페이스를 만들고 헬름 차트를 내려받는다.

$ (⎈ |switch-seoul-stage:otel-demo) k create ns tempo
namespace/tempo created
$ (⎈ |switch-seoul-stage:otel-demo) k ns tempo

$ (⎈ |switch-seoul-stage:tempo) helm pull grafana/tempo-distributed
$ (⎈ |switch-seoul-stage:tempo) tar xvfz tempo-distributed-1.4.2.tgz 
$ (⎈ |switch-seoul-stage:tempo) mv tempo-distributed tempo-distributed-1.4.2
$ (⎈ |switch-seoul-stage:tempo) rm -rf tempo-distributed-1.4.2.tgz 
$ (⎈ |switch-seoul-stage:tempo) cd tempo-distributed-1.4.2

내려받은 헬름 value 파일(my-values.yaml)을 수정한다. 깃헙 링크

ingester:
  persistence:
    enabled: true
    size: 10Gi
traces:
  otlp:
    http:
      enabled: true
      receiverConfig: {}
    grpc:
      enabled: true
      receiverConfig: {}

storage:
  trace:
    block:
      version: vParquet
    backend: local
  admin:
    backend: filesystem

 

주요 설정 내용

. ingester.persistence.enables: true

. traces.otlp, traces.grpc.traces

  traces 프로토콜로 otlp, grpc 데이터를 처리한다.

. storage.trace.backend: local, storage.admin.backend: filesystem

실제 운영 환경에는 Tempo에서 권고하는 S3를 사용할 예정이나, 일단 local storage를 사용하였다.

 

수정한 헬름 value 파일로 설치한다.

$ (⎈ |switch-seoul-stage:tempo) helm install tempo -f my-values.yaml .
NAME: tempo
LAST DEPLOYED: Tue May 30 15:03:11 2023
NAMESPACE: tempo
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
***********************************************************************
 Welcome to Grafana Tempo
 Chart version: 1.4.2
 Tempo version: 2.1.1
***********************************************************************

Installed components:
* ingester
* distributor
* querier
* query-frontend
* compactor
* memcached

설치가 완료되면 아래의 파드를 확인할 수 있다.

k get pod -o wide
NAME                                    READY   STATUS    RESTARTS   AGE   IP                NODE                                                 NOMINATED NODE   READINESS GATES
tempo-compactor-649bb66999-lhpfs        1/1     Running   0          84s   192.168.39.224    ip-192-168-52-239.ap-northeast-2.compute.internal    <none>           <none>
tempo-distributor-859d6c646b-n6bzq      1/1     Running   0          84s   192.168.6.71      ip-192-168-6-117.ap-northeast-2.compute.internal     <none>           <none>
tempo-ingester-0                        1/1     Running   0          84s   192.168.152.77    ip-192-168-159-59.ap-northeast-2.compute.internal    <none>           <none>
tempo-ingester-1                        1/1     Running   0          84s   192.168.20.187    ip-192-168-2-180.ap-northeast-2.compute.internal     <none>           <none>
tempo-ingester-2                        1/1     Running   0          84s   192.168.129.202   ip-192-168-136-120.ap-northeast-2.compute.internal   <none>           <none>
tempo-memcached-0                       1/1     Running   0          84s   192.168.22.127    ip-192-168-6-117.ap-northeast-2.compute.internal     <none>           <none>
tempo-querier-7b5949db9b-5lc7q          1/1     Running   0          84s   192.168.37.250    ip-192-168-45-176.ap-northeast-2.compute.internal    <none>           <none>
tempo-query-frontend-86b8ccb5c5-v2t5w   1/1     Running   0          84s   192.168.155.226   ip-192-168-159-59.ap-northeast-2.compute.internal    <none>           <none>

open telemetry collector와 연동을 위해서 필요한 정보는 tempo의 서비스 이름이다. tempo-distributing-discovery 서비스를 확인할 수 있다.

$ (⎈ |sent-seoul-stage:tempo) k get svc tempo-distributor-discovery 
NAME                          TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                                AGE
tempo-distributor-discovery   ClusterIP   None         <none>        3100/TCP,4318/TCP,4317/TCP,55680/TCP   2m45s

 

서비스 타입의 cluster-ip가 없는것을 보아서 headless 타입 서비스다.

 

생성한 Tempo를 그라파나의 데이터 소스로 등록한다. 아래 스크린캡쳐를 참조하여 등록한다.

 

 

HTTP > URL 에 tempo query frontend 서비스 이름을 참고하여 네임스페이스 이름 + Port 3100 까지 입력한다.

$ (⎈ |sent-seoul-stage:tempo) k get svc tempo-query-frontend-discovery -n tempo
NAME                             TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                      AGE
tempo-query-frontend-discovery   ClusterIP   None         <none>        3100/TCP,9095/TCP,9096/TCP   7m29s

 

설정이 정상이고 화면 아래의 'Save & test' 버튼을 클릭하면 위와같이 녹색의 'Data source is working' 내용을 확인할 수 있다.

 

이제 Tempo 설정이 완료되었다.

 

4. Open Telemetry Collector + Auto Instrumentation 설치

(포스팅 내용이 너무 길어진다. 2개로 나눌 것 그랬나..흐음)

 

이제 이전에 설치한 k8s open telemetry operator를 이용하여 open telemetry collector와 auto instrumentation의 Custom Resource를 설치한다.

 

auto instrumenation(계측기)가 좋은게 쿠버네티스 환경에서는 application 소스 수정없이 instrumentation CRD 설치하고 파드(혹은 네임스페이스 전체)에 annoation 설정만 하면 알아서 tracing에 필요한 데이터가 appliation에 포함된다. (신기하다. 어떻게 가능하지?) 그리고 해당 데이터의 저장 target을 open telemetry collector로 지정하면 데이터가 collector로 저장된다. 그러고 다시 collector를 다시 백엔드 tempo로 전달하도록 설정한다.

 

위에서 사용한 이미지를 반복하면 좀 더 이해가 쉽다.

 

 

코드로 확인하면 눈에 더 잘 들어온다. 먼저 open telemetry collector를 설치한다.

$ (⎈ |sent-seoul-stage:opentelemetry-operator) helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts
"open-telemetry" already exists with the same configuration, skipping

# jerry @ Jerrys-MacBook-Pro in ~/private/k8s-class/opentelemetry-crd on git:main x [9:48:13] 
$ (⎈ |sent-seoul-stage:opentelemetry-operator) helm pull open-telemetry/opentelemetry-collector

$ (⎈ |sent-seoul-stage:opentelemetry-operator) tar xvfz opentelemetry-collector-0.59.1.tgz 
$ (⎈ |sent-seoul-stage:opentelemetry-operator) rm -rf opentelemetry-collector-0.59.1.tgz                
$ (⎈ |sent-seoul-stage:opentelemetry-operator) mv opentelemetry-collector opentelemetry-collector-0.59.1
$ (⎈ |sent-seoul-stage:opentelemetry-operator) cd opentelemetry-collector-0.59.1

헬름 value 파일을 my-values.yaml로 복사하고 수정한다. (깃헙 링크)

# Valid values are "daemonset", "deployment", and "statefulset".
mode: "deployment"
config:
  exporters:
    otlp:
      endpoint: tempo-distributor-discovery.tempo:4317
      tls:
        insecure: true
  extensions:
    # The health_check extension is mandatory for this chart.
    # Without the health_check extension the collector will fail the readiness and liveliness probes.
    # The health_check extension can be modified, but should never be removed.
    health_check: {}
    memory_ballast: {}
  processors:
    memory_limiter:
      check_interval: 1s
      limit_percentage: 75
      spike_limit_percentage: 15
    batch:
      send_batch_size: 10000
      timeout: 10s
  receivers:
    otlp:
      protocols:
        grpc:
          endpoint: ${env:MY_POD_IP}:4317
        http:
          endpoint: ${env:MY_POD_IP}:4318
  service:
    extensions:
    - health_check
    - memory_ballast
    pipelines:
      traces:
        exporters:
        - otlp
        processors:
        - memory_limiter
        - batch
        receivers:
        - otlp

 

눈여겨 볼 부분은

. config.receivers.otlp
receivers로 logging이 아닌 tracing에 사용하는 otlp(익숙한 OLTP로 계속 발음하는데, 아니다) open telmetry protocol만 받겠다는 의미

. config.exporters.otlp.endpoint 
받은 데이터를 백엔드 tempo에 전달하도록 tempo distributed 서비스 이름으로 지정한다. Tempo 헬름 차트를 설치한 네임스페이스와 이름에 따라 각자 다르게 설정한다.

. config.exporters.otlp.tls.insecure: true
insecure 설정을 하지 않으면 설치 에러 발생한다.

. config.receivers.otlp.protocols.grpc, http

grpc, http 2가지 프로토콜의 데이터를 받도록 설정한다.

. config.service.pipelines.traces.exporters.otlp 
이 부분이 default로 logging이 되어 있어서 tempo에서 trace 데이터가 들어오지 않아서 고생했다. 우리는 트레이싱 otlp 데이터를 전달하니 otlp로 지정하고 나서 Tempo에서 정상적으로 데이터를 확인할 수 있었다.

 

변경한 my-values.yaml 파일 기준으로 open telemetry collector의 CRD를 생성한다.

$ (⎈ |sent-seoul-stage:opentelemetry-operator) helm install otel-collector -f my-values.yaml .

정상으로 설치되면 아래의 파드를 확인할 수 있다.

$ (⎈ |sent-seoul-stage:opentelemetry-operator) k get pod
otel-collector-opentelemetry-collector-659fbd7dc8-hqd9h   1/1     Running   0          3h24m   10.0.186.252   ip-10-0-186-22.ap-northeast-2.compute.internal    <none>           <none>

다음으로 auto instrumentation의 CRD를 생성한다. 설치는 단일 매니페스트 파일로 진행한다. (깃헙 링크)

apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
  name: otel-instrumentation
spec:
  exporter:
    endpoint: http://otel-collector-opentelemetry-collector.opentelemetry-operator:4317
  propagators:
  - tracecontext
  - baggage
  sampler:
    type: parentbased_traceidratio
    argument: "1"

. spec.exporter.endpoint
위에서 설치한 open telemetry collector의 서비스 이름과 네임스페이스 이름을 지정한다. 

 

주의할것은 설치 네임스페이스는 instrumentation을 주입할 application 네임스페이스에서 설치한다. 우리 환경은 nlp 네임스페이스라 해당 네임스페이스로 이동해서 설치한다.

$ (⎈ |sent-seoul-stage:opentelemetry-operator) k ns nlp
Context "sent-seoul-stage" modified.
Active namespace is "nlp".

$ (⎈ |sent-seoul-stage:nlp) k apply -f opentelemetry-instrumentation.yaml

설치되면 아래와 같이 instrumenation CRD를 확인할 수 있다.

$ (⎈ |sent-seoul-stage:nlp) k get instrumentations.opentelemetry.io 
NAME                   AGE   ENDPOINT                                                                    SAMPLER                    SAMPLER ARG
otel-instrumentation   42s   http://otel-collector-opentelemetry-collector.opentelemetry-operator:4317   parentbased_traceidratio   1

 

참고로 webhook 에러로 설치가 되지 않으면 open telemetry operator의 webhook 포트 9443을 EKS control plane 노드와 worker 노드를 열어준다. 참고 링크

 

이제 모든 준비가 완료되었다. Tracing이 필요한 파드에서 아래의 annotations만 추가하면 해당 파드는 Tempo에서 결과를 확인할 수 있다.

spec:
  template:
    metadata:
      annotations:
        instrumentation.opentelemetry.io/inject-nodejs: "true"

사용하는 언어에 따라 공식 홈페이지를 참고하여 inject-nodejs 부분을 수정해서 적용한다.

 

5. Tempo 확인

Tempo는 아래와 같이 Explore 메뉴에서 확인할 수 있다. 화면 중앙 Query type 메뉴에서 Search를 선택하면 아래와 같이 Open Telemetry Instrumentation 적용된 파드가 보인다.

 

 

Tracing 필요한 Trace ID 를 클릭하면 자세한 내역을 확인할 수 있다.

 

 

이상 Open Telemetry Operator, Tempo로 구성한 Tracing 실습을 알아보았다.

 

참조

https://nangman14.tistory.com/69 

 

트레이싱 관측 도구 Grafana Tempo로 트레이스를 관측해보자

우리가 관측 가능성(Observability)에 대해서 말할때, 보통 시계열의 수치 데이터를 뜻하는 메트릭(Metric)이나 인간이 읽을 수 있는(human-readable) 형태로 상태를 출력하는 로그(Log)를 떠올릴 것입니다.

nangman14.tistory.com

https://opentelemetry.io/docs/concepts/signals/traces/

 

Traces

Traces give us the big picture of what happens when a request is made to an application. Whether your application is a monolith with a single database or a sophisticated mesh of services, traces are essential to understanding the full “path” a request

opentelemetry.io

 

반응형

'쿠버네티스 교육' 카테고리의 다른 글

AWS ALB & LoadBalancer Controller  (2) 2023.04.11
Github Action Self-hosted 세팅  (4) 2023.04.06
파일시스템 기반 Loki 설치  (8) 2023.04.01
원격 EKS 접속 환경 설정  (0) 2022.11.08
EKS OJT 교육 실습 목차  (2) 2022.11.08