Cloud Native なアプリケーションの L4/L7 Proxy として使われる機会の多い Envoy の Trace 情報を New Relic に転送する方法をご紹介致します。

今回は Envoy の opentelemetry サンプルを参考にしたリポジトリを用意しておりますので細かい設定や Envoy 自体の設定については公式ドキュメントを参考にしていただけたらと思います。

こちらが参考のリポジトリになります。
https://github.com/newrelickk/envoy-otel-example

事前設定

まず New Relic のアカウントをお持ちでない方は New Relic のアカウント作成を最初に実施していただく必要があります。

New Relic は月のデータ転送量(TDP)が100GBまででしたら1ユーザーまで基本的な全ての機能を無料でご利用いただけるようになっておりますので今回も無料の範囲でご利用頂けます。画面を操作しているとクレジットカード情報の入力を促すような挙動を何度かしますがそのまま登録せずにご利用ください。

また今回は Docker を使うため筆者は以下の環境で Docker Desktop for Mac を動作させています。
 

M1 Max Macbook pro Monterey 12.6.1
Docker Desktop 4.14.1 (91661)

Envoy の設定

まずは Envoy の設定をおこないます。

今回 Envoy の設定は envoy-1.yaml,envoy-2.yaml,envoy-front-proxy.yaml の3つにそれぞれありますが全て同じように設定ができますので同じ設定をそのままご利用ください。

Envoy には tracing という設定を追加することで New Relic や Jaeger など外部にトレース情報をすることができます。今回は OpenTelemetry 形式で New Relic に対して転送をするのでその設定から始めます。

    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          tracing:
            custom_tags:
              - tag: "service.name"
                literal:
                  value: "envoy-service-1"
            provider:
              name: envoy.tracers.opentelemetry
              typed_config:
                "@type": type.googleapis.com/envoy.config.trace.v3.OpenTelemetryConfig
                grpc_service:
                  envoy_grpc:
                    cluster_name: opentelemetry_collector #後程設定
                  timeout: 0.250s
                service_name: envoy-1

細かい設定は省略しますが custom.tagsservice.name という tag を付与しています。これは New Relic でこの Envoy の情報を UI に表示する際に必要になっているのでこのように設定をしております。

次に転送先の cluster の設定を行います。

clusters:
  - name: opentelemetry_collector
    type: STRICT_DNS
    lb_policy: ROUND_ROBIN
    typed_extension_protocol_options:
      envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
        "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
        explicit_http_config:
          http2_protocol_options: {}
    load_assignment:
      cluster_name: opentelemetry_collector
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                # k8s などを使っている場合は svc の宛先などを指定する。
                address: opentelemetry
                port_value: 4317

これで Envoy 側の設定は完了なので otel-collector 側の設定を行います。

OpenTelemetry Collector の設定

OpenTelemetry Collector (以降 otel-collector)は、テレメトリ・データの受信、処理、エクスポートの方法について、ベンダーにとらわれない実装を提供してくれます。オープンソースのバックエンド(Jaeger, Prometheus など)や New Relic のような商用サービスのバックエンドへの転送をサポートしているため、複数のエージェントやコレクタを実行、運用、保守する必要性をなくしてくれます。

今回は Envoy で生成した Tracing のデータを otel-collector へ転送して New Relic に送信します。
以下が config 全体になります。 

extensions:
  memory_ballast:
    size_mib: 512
  zpages:
    endpoint: 0.0.0.0:55679
  health_check:

receivers:
  otlp:
    protocols:
      grpc:
      http:

processors:
  batch:
  memory_limiter:
    limit_mib: 1536
    spike_limit_mib: 512
    check_interval: 5s

exporters:
  otlp:
    endpoint: "https://otlp.nr-data.net:4317"
    headers:
      api-key: "<set newrelic license key>"
  logging:
    loglevel: debug

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [memory_limiter, batch]
      exporters: [otlp, logging]
    metrics:
      receivers: [otlp]
      processors: [memory_limiter, batch]
      exporters: [otlp, logging]

  extensions: [memory_ballast, zpages, health_check]

詳細のそれぞれの設定に関しては otel-collector のドキュメントを参考にしていただくとわかりやすくなっております。今回は exporters 配下の設定に注目して endpointapi-key の設定になります。

endpoint の設定についてですが New Relic のドキュメントに otlp endpoint の一覧が掲載されていますのでご自身のお使いの New Relic のリージョンと同じものをご利用ください。
https://docs.newrelic.com/docs/more-integrations/open-source-telemetry-integrations/opentelemetry/opentelemetry-setup/

api-key は License Key をご利用ください。
こちらから INGEST のものを選択してコピーしてご利用ください。

動かしてみる

では実際に docker compose を利用してサービスたちを立ち上げます。

docker compose up --build で正常に立ち上がったことを確認した場合、ターミナルで以下のリクエストを何度か試してみましょう。

# reqest to front-proxy → envoy-1
curl localhost:10000/trace/1

# request to front-proxy → envoy-1 → envoy-2
curl localhost:10000/trace/2 

リクエストが無事に通り少し待つと New Relic にデータが転送されますので New Relic を開いて確認してみましょう。

New Relic の左のサイドーバーにある APM&services を選択して OpenTelemetry を見てもらうと3つのサービスが登録されているかと思います。

envoy-front-proxy を選択してもらい Distributed tracing を選択してもらうと Trace が表示されておりクリック後に実際にリクエストの一覧が表示されます。その際に参考の画像は3つのサービスをまたがっていますが以下のようになっていれば成功です。

最後に

今回は Envoy のトレース情報のみを New Relic に転送する方法をご紹介しましたが実際には Web アプリケーションの前段として Envoy を置くケースが多いかと思います。その際に New Relic APM Agent や OpenTelemetry SDK などを使っていただくことでアプリケーション全体としての分散トレーシングが可能になり一つのリクエストの全貌が把握できるようになりますので是非合わせてお試しください。