1. 개요
1) MSA 구조에서는 작은 마이크로 서비스들 사이에서 주고 받는 이벤트가 자주 일어나기 때문에 서비스에 대한 이슈 원인을 찾기 힘듭니다. 그래서 Trace를 활용해서 Observability하게 서비스들을 관리 할 수 있도록 해야합니다.
2) Trace는 각 요청마다 고유한 ID를 부여합니다. 해당 ID를 가진 요청이 이벤트를 발생시킬 때마다 이벤트의 시작시간과 끝시간을 측정해 레이턴시를 파악합니다. 결과적으로 고유 ID를 가진 이벤트끼리 묶어주면 아래 이미지와 같이 하나의 다이어그램이 완성되어 이벤트에 대한 연관성을 추적할 수 있습니다.

3) 앞서 포스팅했듯, Azure Application Insights를 통해서도 가능하지만 상용 제품인 Grafana Tempo를 알아보도록 하겠습니다.
2. Grafana Tempo 란 ?
1) 위에서 설명했듯이, Trace에 대해 추적 모니터링이 필요합니다. 그렇기위해서는 Tracing을 위한 도구가 필요합니다.
2) 상용적으로 사용하는 도구들은 많습니다. 예를들어, Datadog, Dynatrace, Elastic, Jaeger, Zipkin 같은 다양한 도구가 있습니다. 여기서는 Grafana 사의 OSS 트레이싱 도구인 Tempo를 알아보겠습니다.
3. Grafana Tempo Architecture

1) 구성요소 및 역할
- 각 구성요소에 대해서 MSA로 다른 서비스로 배포할 수 있지만, 복잡도가 높아 여기서는 하나의 애플리케이션으로 배포합니다.
- Distributor : Trace를 수집하는 역할
- Ingester : Trace를 저장하는 역할
- Querier : ID로 Trace를 찾아주는 역할
- Query Frontend : 검색을 위해 샤딩하는 역할
- Compactor : Backend Storage에 데이터를 넣거나 빼는 역할
- 여기서는 helm 기반으로 하나이 애플리케이션으로 Tempo를 배포하여서 아래와 같이 tempo 네임스페이스에 하나의 Pod만 생성됩니다.

- pod가 어떻게 구성되어있는지 아래 명령어를 통해서 상세 정보를 확인합니다 .
- 해당 Pod는 helm에 의해서 구성되었으며 아래 describe 내용과 같이 Configmap의 tempo.yaml파일에 의해서 설정이 제어 됩니다.
- 해당 tempo.yaml파일을 custom하기 위해서는 values.yaml 파일을 생성하여 새로 커스텀 해야합니다. 여기서는 그대로 tempo.yaml파일을 사용합니다.
$ kubectl describe pod -n tempo tempo-0
# tempo-0 Pod 상세 정보
cheol@terzmy-vm-win-0:/mnt/c/ollacare/Application_Monitoring/grafanatempo_monitoring/tns/production/k8s-yamls$ kubectl describe pod -n tempo tempo-0
Name: tempo-0
Namespace: tempo
Priority: 0
Service Account: tempo
Node: aks-nodepool1-32536577-vmss00000a/10.224.0.10
Start Time: Fri, 01 Nov 2024 13:17:25 +0900
Labels: app.kubernetes.io/instance=tempo
app.kubernetes.io/name=tempo
apps.kubernetes.io/pod-index=0
controller-revision-hash=tempo-6ffc599495
statefulset.kubernetes.io/pod-name=tempo-0
Annotations: checksum/config: 611da1bb43aabb73f2f8face7a614b1bf51b538bdfed8042be32c6d469729845
Status: Running
IP: 10.224.0.29
IPs:
IP: 10.224.0.29
Controlled By: StatefulSet/tempo
Containers:
tempo:
Container ID: containerd://2ffc557e71a2f1191cdecd23d41e96851549856f92df7539fa961055d50e7565
Image: grafana/tempo:2.5.0
Image ID: docker.io/grafana/tempo@sha256:f0200a9bff6d14eb3a4332194f7b77c37ee1a3535e7e41db024d95aab6f1b4e8
Ports: 3100/TCP, 6831/UDP, 6832/UDP, 14268/TCP, 14250/TCP, 9411/TCP, 55680/TCP, 4317/TCP, 55681/TCP, 4318/TCP, 55678/TCP
Host Ports: 0/TCP, 0/UDP, 0/UDP, 0/TCP, 0/TCP, 0/TCP, 0/TCP, 0/TCP, 0/TCP, 0/TCP, 0/TCP
Args:
-config.file=/conf/tempo.yaml #Pod의 설정파일은 tempo.yaml에 의해 제어됩니다.
-mem-ballast-size-mbs=1024
State: Running
Started: Fri, 01 Nov 2024 13:17:31 +0900
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/conf from tempo-conf (rw)
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-cg4wh (ro)
Conditions:
Type Status
PodReadyToStartContainers True
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
tempo-conf:
Type: ConfigMap (a volume populated by a ConfigMap) # Configmap에서 생성된 볼륨으로 pod의 설정 파일을 제공합니다.
Name: tempo
Optional: false
kube-api-access-cg4wh:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events: <none>
- 아래 configmap에 의해서 tempo Pod 설정 파일이 제어됩니다.
- Distributor, Ingester, Query Frontend 등 Temp에서 주요 기능에 대해 설정 파일입니다.
# tempo Configmap 정보
cheol@terzmy-vm-win-0:/mnt/c/ollacare/Application_Monitoring/grafanatempo_monitoring/tns/production/k8s-yamls$ kubectl describe configmap -n tempo tempo
Name: tempo
Namespace: tempo
Labels: app.kubernetes.io/instance=tempo
app.kubernetes.io/managed-by=Helm
app.kubernetes.io/name=tempo
app.kubernetes.io/version=2.5.0
helm.sh/chart=tempo-1.10.3
Annotations: meta.helm.sh/release-name: tempo
meta.helm.sh/release-namespace: tempo
Data
====
overrides.yaml:
----
overrides:
{}
tempo.yaml:
----
multitenancy_enabled: false
usage_report:
reporting_enabled: true
compactor:
compaction:
block_retention: 24h
distributor:
receivers:
jaeger:
protocols:
grpc:
endpoint: 0.0.0.0:14250
thrift_binary:
endpoint: 0.0.0.0:6832
thrift_compact:
endpoint: 0.0.0.0:6831
thrift_compact:
endpoint: 0.0.0.0:6831
thrift_http:
thrift_http:
endpoint: 0.0.0.0:14268
opencensus: null
otlp:
otlp:
otlp:
otlp:
otlp:
protocols:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
ingester:
{}
server:
http_listen_port: 3100
storage:
trace:
backend: local
local:
path: /var/tempo/traces
wal:
path: /var/tempo/wal
querier:
{}
query_frontend:
{}
overrides:
per_tenant_override_config: /conf/overrides.yaml
BinaryData
====
Events: <none>
- 테스트 환경 tempo 관련 리소스 구성도

2) 구성도 개념
- [데이터 생성] -> [데이터 수집/전송] -> [데이터 저장/관리] -> [데이터 시각화]
- 데이터 생성 : 애플리케이션에서 Trace 데이터를 생성 합니다.
- 데이터 수집/전송 : OpenTelemetry와 같은 도구로 애플리케이션 데이터를 수집하고 백엔드 시스템으로 전송합니다.
- 데이터 저장/관리 : Grafana Tempo와 같은 도구로 데이터를 저장(클라우드 스토리지 등)하고 TraceQL을 사용해 쿼리 및 관리가 가능합니다.
- 데이터 시각화 : Grafana Dashboard와 같은 도구로 데이터를 시각화합니다.
※ 데이터 수집기 및 저장소 도구
- 데이터 수집기 : OpenTelemetry Collector (표준), Jaeger Collect , Zipkin (레거시) 등
- 데이터 저장소 도구 : Garafana Tempo , Azure LogAnalytics , Jaeger, Zipkin 등
- 데이터 시각화 : Grafana Dashboard , Azure Monitor
- 올인원: DataDog, Dynatrace, Elastic 등
※ 차이점 정리
- Grafana Tempo VS Azure LogAnalytics
- Grafana Tempo는 Trace 전용 로그에 대해서 저장 및 관리합니다.
- Grafana Tempo는 CSP Storage를 사용하여 데이터 저장에 대한 비용 효율적인 장점이 있습니다.
- Grafana Tempo를 사용했을 경우, 시각화는 Grafana Dashboard를 사용하는 것을 권장 합니다.
- Azure LogAnalytics는 범용 로그 데이터에 대해서 저장 및 관리합니다.
- Azure LogAnalytics를 사용했을 경우, 시각화는 Azure Monitor (Application Insights)를 사용하는 것을 권장합니다.
4. 테스트
★테스트 전체 구성도

1) demo 애플리케이션 가져오기
git clone https://github.com/grafana/tns.git
2) tns >> production >> k8s-yaml >> deployment관련 yaml 파일 수정
- 각 deployment yaml 파일의 JAEGER_AGENT_HOST 환경변수를 변경해줍니다.
- 환경변수를 "<tempo_servicename>.<tempo_namespace>.svc.cluster.local"로 변경해줍니다.
- 아래 yaml 파일 배포는 Grafana 및 tempo를 helm chart로 tempo라는 네임스페이스에 배포한 뒤 해당 yaml파일들을 배포합니다. (deployment, service 배포)
# app-dep.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
spec:
replicas: 1
selector:
matchLabels:
name: app
template:
metadata:
labels:
name: app
spec:
containers:
- name: app
image: grafana/tns-app:latest
imagePullPolicy: IfNotPresent
args:
- -log.level=debug
- http://db
ports:
- name: http-metrics
containerPort: 80
env:
- name: JAEGER_AGENT_HOST
value: tempo.tempo.svc.cluster.local
- name: JAEGER_TAGS
value: cluster=docker,namespace=default
- name: JAEGER_SAMPLER_TYPE
value: const
- name: JAEGER_SAMPLER_PARAM
value: "1"
-------------------------------------------------------
# db-dep.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: db
spec:
replicas: 1
selector:
matchLabels:
name: db
template:
metadata:
labels:
name: db
spec:
containers:
- name: db
image: grafana/tns-db:latest
imagePullPolicy: IfNotPresent
args:
- -log.level=debug
ports:
- name: http-metrics
containerPort: 80
env:
- name: JAEGER_AGENT_HOST
value: tempo.tempo.svc.cluster.local
- name: JAEGER_TAGS
value: cluster=docker,namespace=default
- name: JAEGER_SAMPLER_TYPE
value: const
- name: JAEGER_SAMPLER_PARAM
value: "1"
-------------------------------------------------------
# loadgen-dep.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: loadgen
spec:
replicas: 1
selector:
matchLabels:
name: loadgen
template:
metadata:
labels:
name: loadgen
spec:
containers:
- name: loadgen
image: grafana/tns-loadgen:latest
imagePullPolicy: IfNotPresent
args:
- -log.level=debug
- http://app
ports:
- name: http-metrics
containerPort: 80
env:
- name: JAEGER_AGENT_HOST
value: tempo.tempo.svc.cluster.local
- name: JAEGER_TAGS
value: cluster=docker,namespace=default
- name: JAEGER_SAMPLER_TYPE
value: const
- name: JAEGER_SAMPLER_PARAM
value: "1"
3) Grafana Tempo 배포
- 설치 방법은 Helm을 통해서 배포합니다.
- 다음 명령어를 통해서 Helm chart를 레포지토리에 추가합니다.
helm repo add grafana https://grafana.github.io/helm-charts

- 다음 명령어를 통해서 Tempo 네임스페이스를 생성하고 Helm Chart로 Tempo와 Grafana를 배포합니다.
- grafana/tempo에 대한 자세한 정보는 여기를 클릭하세요.
- grafana/grafana에 대한 자세한 정보는 여기를 클릭하세요.
kubectl create ns tempo
helm install tempo grafana/tempo -n tempo
helm install grafana grafana/grafana -n tempo

- 배포 후 정상적으로 실행되어 리소스가 만들어졌는지 확인합니다.

- 상단에 수정해놨던 deployment와 service를 배포합니다.
- pod가 running 상태인지 확인합니다.

4) Grafana 설정
- Trace를 관측하기 위해서 Grafana 설정을 진행합니다.
- Grafana Dashboard에 접근하기 위해서 포트 포워딩을 진행합니다.
kubectl port-forward GRAFANA_POD 3000 -n tempo &


- 접속 후 초기비밀번호를 초기화 합니다.
- 비밀번호를 admin으로 초기화하고나면 업데이트하라고 합니다. 자신의 비밀번호로 업데이트 합니다.
kubectl exec -i -t <Grafana_pod_name> -n tempo -- grafana-cli admin reset-admin-password admin


- 정상적으로 로그인이 완료 되었다면 Connection >> Data source로 진입하여 Data source로 Tempo를 설정해야합니다.
- Connection URL을 http://tempo:3100으로 설정하고 save & test 버튼을 클릭합니다.
- (aks cluster의 metric을 받아오는 tempo container가 3100으로 되어있고 svc이름이 tempo라서 그런거 같은데..틀린부분 댓글 달아주세요 ㅠㅠ)



5) Tempo Trace 관측하기
- 성공적으로 Tempo와 Connection 됐다면 이제 Trace를 Grafana에서 모니터링할 수 있습니다.
- Explore로 이동해서 Trace를 쿼리합니다.
- 아래 이미지와 같이 Trace ID를 이용해서 쿼리를 진행하여 트랜잭션을 모니터링 할 수 있습니다.

- trace ID 확인하는 방법은 아래와 같습니다.
- deployment yaml파일로 배포한 app, db, loadgen은 서로 의존성이 있으며 app log를 찍었을때 trace ID가 출력되도록 애플리케이션이 구성되어있습니다.
kubectl logs APP_POD

- Trace ID를 입력하고 실행하면 트랜잭션을 추적 모니터링 하여 Dashboard로 볼 수 있습니다.

'Azure' 카테고리의 다른 글
| WebSocket 통신과 Azure Front Door (0) | 2025.01.15 |
|---|---|
| Azure CDN을 이용한 정적 웹 애플리케이션 서비스 (1) | 2024.11.28 |
| Azure Application Insights를 이용한 Application Monitoring (nodejs)- 2/2 (1) | 2024.10.31 |
| Azure Application Insights를 이용한 Application Monitoring (nodejs)- 1/2 (0) | 2024.10.31 |
| Azure Application Insights를 이용한 Application Monitoring (java) (0) | 2024.10.29 |