3scaleとJaegerを連携してみた

初版: 2018/12/7
著者: 田畑義之, 株式会社日立製作所 (GitHubアカウント: [@y-tabata](https://github.com/y-tabata))
本記事は、あくまで執筆者の見解であり、所属企業及びRed Hatの公式なドキュメントではありません。

# はじめに
2018年10月5日、Red Hat 3scale API Management (以下、3scale)の[バージョン2.3](https://access.redhat.com/documentation/en-us/red_hat_3scale/2.3/html/release_notes/)がリリースされました。2018年5月31日の2.2のリリースから約4か月ぶりの新バージョンです。
本稿では、3scale 2.3で可能になった「OpenTracing対応」を検証すべく、3scaleとJaegerを連携してみましたので、ご紹介します。
3scale 2.3の新機能の概要に関しては、「[完全OSSになった3scale 2.3の新機能紹介](https://qiita.com/yo-tabata/items/c91e49364a084fdf09b5)」をご参照ください。

# 3scaleとは
3scaleとは、Red Hat主体で開発が進められているAPI管理製品です。
詳細は、「[OSSベースのAPI管理製品 3scale 2.2を試してみた](https://qiita.com/yo-tabata/items/eb81c5cb324cefa87efc)」の「[3scaleとは](https://qiita.com/yo-tabata/items/eb81c5cb324cefa87efc#3scale%E3%81%A8%E3%81%AF)」をご参照ください。

# OpenTracingとは
マイクロサービスを代表とする分散型ソフトウェアアーキテクチャをデバッグ・監視する技術として、分散トレーシングがあります。
OpenTracingとは、標準化を目的として作成された分散トレーシングの実装であり、OpenTracingを使用することで、特定の製品やベンダにロックインされずに、アプリケーションコードに分散トレーシングのための計装(instrumentation)を導入できます。
詳細は[公式サイト](https://opentracing.io/)をご参照ください。

# Jaegerとは
Jaegerとは、OpenTracingを実装する代表的なトレーサの一つで、Uber社が開発し、Cloud Native Computing Foundationがホストしています。
詳細は[公式サイト](https://www.jaegertracing.io/)をご参照ください。

# 3scaleとJaegerを連携させてみる
3scale 2.3では、OpenTracingの実装として、Jaegerがサポートされました。3scaleとJaegerを連携することで、APIcastの処理を可視化することができます。
それでは、実際に連携してみましょう。

## Jaegerをインストールする
まずはJaegerをインストールします。今回は検証用なので、All-In-One構成のJaegerを3scaleと同じプロジェクトに、テンプレートを用いてインストールします。

```sh
oc process -f https://raw.githubusercontent.com/jaegertracing/jaeger-openshift/master/all-in-one/jaeger-all-in-one-template.yml | oc create -f -
```

インストールに成功すると、下記リソースが作成されます。

-   Deployment: jaeger
-   ReplicaSet: jaeger-XXXXXXXXXX
-   Pod: jaeger-XXXXXXXXXX-YYYYY
-   Service: jaeger-agent
-   Service: jaeger-collector
-   Service: jaeger-query
-   Service: zipkin
-   Route: jaeger-query

## Jaegerの設定ファイルをAPIcastにマウントする
Jaegerの設定ファイルを作成します。
APIcastのリポジトリに[サンプル](https://github.com/3scale/apicast/blob/master/gateway/conf.d/opentracing/jaeger.example.json)があるので、そのサンプルを参考にして、下のように作成しました。

```json:jaeger_config.json
{
  "service_name": "apicast",
  "disabled": false,
  "sampler": {
    "type": "const",
    "param": 1
  },
  "reporter": {
    "queueSize": 100,
    "bufferFlushInterval": 10,
    "logSpans": false,
    "localAgentHostPort": "jaeger-agent:6831"
  },
  "headers": {
    "jaegerDebugHeader": "debug-id",
    "jaegerBaggageHeader": "baggage",
    "TraceContextHeaderName": "uber-trace-id",
    "traceBaggageHeaderPrefix": "testctx-"
  },
  "baggage_restrictions": {
      "denyBaggageOnInitializationFailure": false,
      "hostPort": "127.0.0.1:5778",
      "refreshInterval": 60
  }
}
```

この設定ファイルからConfigMapを作成し、APIcastにマウントします。

```sh
oc create configmap jaeger-config --from-file=jaeger_config.json
oc volume dc/apicast-production --add -m /tmp/jaeger/ --configmap-name jaeger-config
```

以上でJaegerを使う準備が整いました。

## APIcastの環境変数を設定する
APIcastのOpenTracingはデフォルトで無効になっています。有効にするために、APIcastの下記環境変数を設定します。

-   OPENTRACING_TRACER<br>
    ロードするトレーサのライブラリを指定する環境変数です。3scale 2.3では、`"jaeger"`のみサポートしています。本環境変数に`"jaeger"`を設定することによって、OpenTracingが有効になります。
-   OPENTRACING_CONFIG<br>
    トレーサの設定ファイルを指定する環境変数です。設定しない場合、デフォルトの設定ファイルが使われます。(Jaegerの場合は、`conf.d/opentracing/jaeger.example.json`です。)<br>
    今回は、`/tmp/jaeger/jaeger_config.json`に設定ファイルをマウントしたので、`/tmp/jaeger/jaeger_config.json`を指定します。

![env.png](https://qiita-image-store.s3.amazonaws.com/0/267112/b4a462d6-449f-3fce-8f97-975c95b39c6c.png)

以上でJaegerの設定は終了です。

## Jaeger UIでAPIcastの処理をトレースする
それでは、Jaeger UIでAPIcastの処理を見てみましょう。

ブラウザで、Jaegerインストール時に作られたRoute: jaeger-queryにアクセスすると、Jaeger UIが表示されます。上述した設定が適切に行われていると、ここでサービスとして`"apicast"`を選択することができます。`"apicast"`を選択し、[Find Traces]ボタンを押すと、下のようにAPIcastのトレースが表示されます。

![jaeger_ui.png](https://qiita-image-store.s3.amazonaws.com/0/267112/075850b9-7cdc-c6c0-9a72-aac39c075193.png)

表示されたトレースの中から、APIをコールしたときのトレースを選択し、詳細を見てみます。

![jaeger_apicast.png](https://qiita-image-store.s3.amazonaws.com/0/267112/8754b086-f2ea-a5fb-9d27-8b4d3aa85c75.png)

このトレースでは、処理が3つに分かれていますが、各処理は以下の通りです。

-   `"/"`: APIcastの処理。APIバックエンドをコールするための各種チェックなど。
-   `"@upstream"`: APIバックエンドの処理。
-   `"@out_of_band_authrep_action"`: 3scaleバックエンドの認証&レポート処理。APIcastにて認証情報がキャッシュされていると、このトレースのように、本処理がAPIバックエンドをコールした後に非同期で実行されます。

以上より、APIcastの処理を可視化することができました。

# おわりに
本稿では、3scaleの「OpenTracing対応」を紹介しました。
今回はAPIcastにのみ計装を導入しましたが、APIバックエンドやクライアントアプリケーション等にも計装を導入することで、APIリクエスト全体の流れを追うことができるようになると、さらに分散トレーシング技術の恩恵を享受できると思います。是非お試しください。