ㅡ.ㅡ

[Tracing] Grafana Tempo 본문

Observabillity

[Tracing] Grafana Tempo

ekwkqk12 2023. 12. 20. 15:32

Architecture

  • Distributor
    Jaeger, OpenTelemetry, Zipkin등에서 전달한 SPAN 내 TraceID 값을 해싱하여 해싱 링으로 구성된 ingester에 해당하는 해싱 범위값을 갖는 노드에 전달하여 처리량을 증가시키며 병목 현상은 완화시키는 역할 담당한다.

  • Ingester
    Distributor에서 수집한 Trace 데이터를 효율적인 검색을 지원하기위해 아래와 같이 인덱싱 후 스토리지 Object Storage에 저장하는 역할을 담당한다.

    <bucketname> / <tenantID> / <blockID> / <meta.json>
                                          / <index>
                                          / <data>
                                          / <bloom_0>
                                            ...
                                          / <bloom_n>
                                            ...
    
  • Object Storage
    Object Storage는 Tempo에서 추적 데이터를 영구적으로 보관하는 저장소로 S3와 같은 클라우드 기반의 객체 스토리지 시스템을 사용한다.

  • Query Frontend
    쿼리 요청이들어오면 쿼리 공간을 샤딩하고 쿼리 처리의 효율성을 향상시키기 위해 큐에 저장하여 Querier가 병렬 처리를 수행하게하며 아래와 같은 엔드포인트를 노출한다.

    GET /api/traces/
    
  • Querier
    큐에 저장된 쿼리 요청을 가져와 Ingester(mem Cache)와 Object Storage에 데이터를 요청하여 QueryFrontend에 전달한다.

    GET /querier/api/traces/
    
  • Compactor
    Object Storage에 저장된 데이터를 압축하여 저장 공간을 절약하고, 여러 세그먼트를 단일 세그먼트로 병합하여 데이터의 효율성을 향상시킨다.

  • memcached
    일시적으로 데이터를 저장하고 검색하는 데 사용되는 메모리 기반의 키-값 저장소로 Ingester, Querier의 작업 내역을 캐싱하여 데이터 수집 및 검색 작업의 성능을 향상시는데 도움을 준다.

  • metricgenerator
    수신된 스팬의서비스의 상관관계 및 RED기반의 메트릭을 생성하여 prometheus remote_write 방식으로 전달한다.

helm

helm repo add grafana https://grafana.github.io/helm-charts

values.yaml

tempo:
  repository: grafana/tempo
  tag: null
  pullPolicy: IfNotPresent

server:
  # -- 최대 수신 가능한 gRPC 메시지 크기
  grpc_server_max_recv_msg_size: 52428800
  # -- 최대 전송 가능한 gRPC 메시지 크기
  grpc_server_max_send_msg_size: 52428800

ingester:
  replicas: 2
  persistence:
    # -- boltdb-shipper를 사용할 때 필요한 PVC 생성 활성화
    enabled: true
    # -- PVC 대신 빈 디렉토리와 램 디스크 사용. **파드 다시 시작시 ingester 내 모든 데이터가 손실됩니다**
    inMemory: false
    # -- 지속적인 메모리 또는 메모리 디스크 크기
    size: 30Gi
    storageClass: gp3
  # -- ingester용 구성 옵션
  config:
    # -- ingester 링에 저장할 스팬의 복사 횟수
    replication_factor: 3
    # -- 트레이스를 wal에 플러시하기 전에 유휴 상태로 있어야하는 시간
    trace_idle_period: null
    # -- 모든 테넌트를 스윕하고 트레이스를 live -> wal -> completed 블록으로 이동하는 빈도
    flush_check_period: null
    # -- 블록을 자르기 전의 최대 블록 크기
    max_block_bytes: null
    # -- 블록을 자르기 전의 최대 시간
    max_block_duration: null
    # -- 블록이 플러시된 후 ingester에 블록을 유지하는 기간
    complete_block_timeout: null

distributor:
  replicas: 2
  autoscaling:
    enabled: false
  config:
    # -- 수집 된 모든 추적 id를 로깅하여 수집을 디버깅하거나 로그를 사용하여 스팬 오류 분포를 계산하는 데 도움이 됩니다.
    # -- 경고: 사용되지 않음. log_received_spans 대신 사용하십시오.
    log_received_traces: null
    # -- 수집된 모든 스팬을 로깅하여 수집을 디버깅하거나 로그를 사용하여 스팬 오류 분포를 계산하는 데 도움이 됩니다.
    log_received_spans:
      enabled: false
      include_all_attributes: false
      filter_by_status_error: false

compactor:
  replicas: 1
  config:
    compaction:
      # 비 압축 블록 유지 기간(30일)
      block_retention: "720h"
      # 압축된 블록 유지 기간
      compacted_block_retention: "1h"
      # 블록 압축 작업의 시간 범위
      compaction_window: "1h"
      # 압축 된 블록의 최대 크기(바이트).
      max_block_bytes: 107374182400
      v2_in_buffer_bytes: 5242880
      v2_out_buffer_bytes: 20971520
      retention_concurrency: 10
      v2_prefetch_traces_count: 1000
      max_time_per_tenant: 5m
      compaction_cycle: 30s

querier:
  # -- querier의 리플리카 수
  replicas: 2
  autoscaling:
    enabled: false
  config:
    frontend_worker:
      # -- grpc 클라이언트 구성
      grpc_client_config: {}
    trace_by_id:
      # -- 트레이스 조회 요청 시간 제한
      query_timeout: 10s
    search:
      # -- querier가 백엔드 검색 요청을 올로드 할 사용할 외부 종단점 목록
      external_endpoints: []
      # -- 검색 요청에 대한 시간 제한
      query_timeout: 30s
      # -- search_external_endpoints가 설정되면 querier는 구성된 서버리스 백엔드의 프록시로 주로 작동합니다. 이 설정을 사용하면 연산자가 querier가 구성 가능한 하위 쿼리 수에 대해 자체적으로 선호할 수 있습니다.
      prefer_self: 10
      # -- 제공된 지속 시간에 두 번째 요청이 발행됩니다. 외부 검색 요청의 p99로 설정하는 것이 권장됩니다.
      external_hedge_requests_at: 8s
      # -- 제공할 때 실행할 요청의 최대 개수. hedge_requests_at을 설정해야 합니다.
      external_hedge_requests_up_to: 2
    # -- 이 값은 querier가 한 번에 처리할 동시 하위 쿼리의 전체 수를 제어합니다. 쿼리 유형에 관계 없습니다.
    max_concurrent_queries: 100

queryFrontend:
  query:
    # -- grafana 버전 <7.5의 경우 jaeger-ui와 호환성을 유지할 필요가 있습니다. ARM arch에서 작동하지 않습니다.
    enabled: false
  replicas: 1
  autoscaling:
    enabled: false
  config:
    # -- querier로 전송한 요청을 재시도하는 횟수
    max_retries: 2
    # -- 전체 쿼리가 실패한 것으로 고려되기 전에 오류로 용인되는 블록 쿼리 수. 0보다 큰 숫자는 부분 결과를 반환하는 데 필요합니다.
    tolerate_failed_blocks: 0
    search:
      # -- 백엔드 검색을 수행할 때 실행할 동시 작업 수
      concurrent_jobs: 2000
      # -- 백엔드 검색을 수행할 때 각 작업이 처리해야 할 대상 바이트 수
      target_bytes_per_job: 104857600
    # -- ID별 추적 조회 구성
    trace_by_id:
      # -- 추적 ID별 쿼리를 분할하는 샤드 수
      query_shards: 100
      # -- 제공된 지속 시간에 두 번째 요청이 발행됩니다. 검색 요청의 p99로 설정하는 것이 권장됩니다.
      hedge_requests_at: 2s
      # -- 제공할 때 실행할 요청의 최대 개수. hedge_requests_at을 설정해야 합니다. 0보다 커야 합니다.
      hedge_requests_up_to: 2

traces:
  jaeger:
    grpc:
      enabled: false
    thriftBinary:
      enabled: false
    thriftCompact:
      enabled: false
    thriftHttp:
      enabled: false
  zipkin:
    enabled: false
  opencensus:
    enabled: false
  kafka: {}
  # otlp만 사용
  otlp:
    http:
      enabled: true
    grpc:
      enabled: true

storage:
  trace:
    block:
      version: vParquet
    backend: s3
    s3:
      endpoint: s3.dualstack.ap-northeast-2.amazonaws.com
      bucket: <bucket-name>
      insecure: false

gateway:
  enabled: true
  replicas: 2
  autoscaling:
    enabled: false
  ingress:
    enabled: true
    annotations:
      kubernetes.io/ingress.class: alb
      alb.ingress.kubernetes.io/load-balancer-name: internal-ingress
      alb.ingress.kubernetes.io/scheme: internal
      alb.ingress.kubernetes.io/target-type: ip
      alb.ingress.kubernetes.io/group.name: <group-name>
      alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443},{"HTTP":80}]'
      alb.ingress.kubernetes.io/ssl-policy: ELBSecurityPolicy-FS-1-2-Res-2020-10
      alb.ingress.kubernetes.io/ssl-redirect: "443"
      external-dns.alpha.kubernetes.io/ttl: "60"
    hosts:
      - host: <host>
        paths:
          - path: /
            pathType: Prefix

metricsGenerator:
  enabled: true
  config:
    registry:
      collection_interval: "30s"
    processor:
      service_graphs:
        max_items: 10000
        wait: "90s"
        workers: 10
    storage:
      remote_write:
        - url: "<prometheus>"

memcached:
  enabled: true

metaMonitoring:
  serviceMonitor:
    enabled: true

memcachedExporter:
  enabled: true

prometheusRule:
  enabled: true
  namespace: null

serviceAccount:
  create: true
  name: tempo-sa
  annotations:
    eks.amazonaws.com/role-arn: <ARN>

S3 Policy

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "TempoPermissions",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:ListBucket",
                "s3:DeleteObject",
                "s3:GetObjectTagging",
                "s3:PutObjectTagging"
            ],
            "Resource": [
                "arn:aws:s3:::bucket-name/*",
                "arn:aws:s3:::bucket-name"
            ]
        }
    ]
}

Grafana

Loki
로그에 포함된 Trace, Span값을 Tempo로 연결시켜주는 링크 활성화 설정

Tempo
트레이스 데이터를 조회할 키워드를 Span의 Resource 속성인 service.name 값을 기반으로 지정하는 설정

해당하는 스팬에 저장된 속성값과 로키에 저장된 라벨값을 매칭하여 로그 뷰로 연결시켜주는 설정

Explorer

Reference

'Observabillity' 카테고리의 다른 글

[K8S] Opentelemetry  (0) 2023.12.20
[Monitoring] JVM Exporter(Micrometer)  (0) 2022.01.20
[Monitoring] Prometheus-Stack  (0) 2021.10.31
[Logging] APP Logging/Fluentd&Fluentbit  (0) 2021.10.17
[K8S] Kubernetes Dashboard  (0) 2021.01.30