📑

Grafanaでサービスグラフを表示する

2024/05/08に公開

こんにちは。
ご機嫌いかがでしょうか。
"No human labor is no human error" が大好きな吉井 亮です。

分散システムの運用の悩みどころは「どこで何が起きているのか把握しにくい」という方も多いと思います。
サービスグラフ(サービスマップ)は、分散システムの関係性を視覚化するための有効な手段です。

Grafana ファミリーを使ってサービスグラフを表示する方法を紹介します。

セットアップ

kubectl インストール

Kubernetes クラスターを操作するために kubectl をインストールします。

Install Tools に OS ごとのインストール方法が記載されています。それを参照してインストールしましょう。

minikube インストール

今回は minikube を使用します。
minikube はローカル環境で Kubernetes クラスターを起動できるツールです。

インストール手順は minikube start を参照ください。

$ brew install minikube

# help が表示されることを確認
$ minikube --help
minikube は、開発ワークフロー用に最適化されたローカル Kubernetes クラスターを構築・管理します。
〜〜省略〜〜

minikube を起動するのですが、デモの動作環境メモリが「6 GB of free RAM for the application」なので、minikube 起動時にメモリ容量を 6GB 以上に指定します。

$ minikube start --cpus='4' --memory='8G'

Helm インストール

Helm のインストール を参照してインストールしてください。
難しくないです。Mac なら brew でインストールできます。

$ brew install helm

OpenTelemetry Demo Helm Chart ダウンロード

今回は OpenTelemetry のデモを使用します。Helm Chart をダウンロードします。

$ helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts
$ helm repo update
$ helm pull open-telemetry/opentelemetry-demo
$ tar -zxf opentelemetry-demo-0.30.2.tgz

TAR Ball を展開すると、opentelemetry-demo というディレクトリが作成されます。

Tempo Helm Chart ダウンロード

サービスグラフを表示する方法はいくつかありますが、Grafana ファミリーの Tempo を使用します。
Tempo の Helm Chart をダウンロードします。
opentelemetry-demo/charts/ に展開します。ディレクトリに移動して helm pull、展開の順に実施します。

$ cd opentelemetry-demo/charts/
$ helm repo add grafana https://grafana.github.io/helm-charts
$ helm repo update
$ helm pull grafana/tempo-distributed
$ tar -xzf tempo-distributed-1.9.4.tgz 

Chart.yamk に Tempo を追記

opentelemetry-demo/Chart.yaml に以下を追記します。

opentelemetry-demo/Chart.yaml
apiVersion: v2
appVersion: 1.9.0
dependencies:
(省略)
# dependencies ブロックに以下の4行を追記
- condition: tempo.enabled
  name: tempo-distributed
  repository: https://grafana.github.io/helm-charts
  version: 1.9.4
(省略)

values.schema.json に Tempo のスキーマを追記

opentelemetry-demo/values.schema.json に以下を追記します。

opentelemetry-demo/values.schema.json
(省略)
    "opensearch": {
      "type": "object"
    },    # ← セミコロンを追加
    # opensearch の下に以下3行を追記
    "tempo-distributed": {
      "type": "object"
    }
(省略)

Tempo の設定

opentelemetry-demo/values.yaml の末に Tempo を追記します。
ここで注目してほしいのは metricsGenerator です。

metricsGenerator は、トレースからメトリクスを生成します。
分散システムの関係性を示すためのサービスグラフを生成する service-graphs、RED (Request, Error and Duration) を生成する span-metrics、高度な計算のためスパンをローカルに保存する local-blocks を有効にしています。

opentelemetry-demo/values.yaml
tempo-distributed:
  enabled: true
  traces:
    otlp:
      grpc:
        enabled: true
  compactor:
    compaction:
      block_retention: 8h        # Optional. Duration to keep blocks.  Default is 14 days (336h).
  storage:
    trace:
      backend: local        # ローカルで動かすのでストレージもローカルに設定
      wal:
        path: /var/tempo/wal
      local:
        path: /var/tempo/blocks
  metricsGenerator:
    enabled: true
    persistence:
      enabled: true
    config:
      storage:
        remote_write:        # スパンからメトリクスを生成して Prometheus に送信する設定
          - url: http://my-otel-demo-prometheus-server:9090/api/v1/write
            send_exemplars: true
  global_overrides:
    metrics_generator_processors:         # metricsGenerator を有効にするための設定
      - "service-graphs"
      - "span-metrics"
      - "local-blocks"
  resources:
    limits:
      memory: 150Mi

OpenTelemetry Collector の設定

opentelemetry-demo/values.yamlopentelemetry-collector ブロックに Tempo 向けの設定を追記します。
OpenTelemetry Demo では Jaeger にトレースを送信していますが、Tempo に送信するように変更します。

opentelemetry-demo/values.yaml
opentelemetry-collector:
(省略)
    exporters:
(省略)
      # exporter に以下のブロックを追記
      otlp/tempo:
        endpoint: '{{ include "otel-demo.name" . }}-tempo-distributor:4317'
        tls:
          insecure: true
(省略)
    service:
      pipelines:
        traces:
          processors: [memory_limiter, resource, batch]
          exporters: [otlp/tempo, debug]    # traces の exporters を otlp/tempo に向ける
(省略)

Prometheus の設定

opentelemetry-demo/values.yamlprometheus ブロックに Remote Write Receiver 設定を追記します。
Tempo でトレースをメトリクスに変換します。そのメトリクスを Prometheus に送信するための設定です。

opentelemetry-demo/values.yaml
prometheus:
(省略)
  server:
    extraFlags:
      - "enable-feature=exemplar-storage"
      - "enable-feature=otlp-write-receiver"
      - "web.enable-remote-write-receiver"        # この行を追記、Tempo からのメトリクスを受け取るための設定
(省略)

Grafana の設定

opentelemetry-demo/values.yamlgrafana ブロックに Tempo の設定を追記します。
ここが本エントリの本題です。Grafana でサービスグラフを表示するための設定です。

opentelemetry-demo/values.yaml
grafana:
(省略)
        - name: Tempo
          type: tempo
          uid: tempo
          url: 'http://{{ include "otel-demo.name" . }}-tempo-query-frontend:3100'
          access: proxy
          editable: true
          isDefault: false
          jsonData:
            httpMethod: GET
            serviceMap:
              datasourceUid: 'webstore-metrics'
(省略)

デモ起動

変更したらローカルに保存した chart を使ってデモを起動します。

$ helm install my-otel-demo ./opentelemetry-demo -n otel-demo --create-namespace
NAME: my-otel-demo
LAST DEPLOYED: 
NAMESPACE: otel-demo
STATUS: deployed
REVISION: 1
NOTES:
=======================================================================================


 ██████╗ ████████╗███████╗██╗         ██████╗ ███████╗███╗   ███╗ ██████╗
██╔═══██╗╚══██╔══╝██╔════╝██║         ██╔══██╗██╔════╝████╗ ████║██╔═══██╗
██║   ██║   ██║   █████╗  ██║         ██║  ██║█████╗  ██╔████╔██║██║   ██║
██║   ██║   ██║   ██╔══╝  ██║         ██║  ██║██╔══╝  ██║╚██╔╝██║██║   ██║
╚██████╔╝   ██║   ███████╗███████╗    ██████╔╝███████╗██║ ╚═╝ ██║╚██████╔╝
 ╚═════╝    ╚═╝   ╚══════╝╚══════╝    ╚═════╝ ╚══════╝╚═╝     ╚═╝ ╚═════╝


- All services are available via the Frontend proxy: http://localhost:8080
  by running these commands:
     kubectl --namespace otel-demo port-forward svc/my-otel-demo-frontendproxy 8080:8080

  The following services are available at these paths once the proxy is exposed:
  Webstore             http://localhost:8080/
  Grafana              http://localhost:8080/grafana/
  Load Generator UI    http://localhost:8080/loadgen/
  Jaeger UI            http://localhost:8080/jaeger/ui/


# 正常起動確認、数分かかります
$ kubectl get pod -n otel-demo

出力で示されている通り、別ターミナルを開いてコマンドを実行します。
http://localhost:8080/grafana/ で Grafana にアクセスできます。

$ kubectl --namespace otel-demo port-forward svc/my-otel-demo-frontendproxy 8080:8080

Grafana から Explore → Tempo → Service Graph を選択すると、RED (Request, Error and Duration) とサービスグラフが表示されます。

alt text

参考

Get started with Grafana Tempo using the Helm chart
Configure Tempo
Metrics-generator

Discussion