OCI APMを利用してIstio上で分散トレーシングを実施してみた

- IstioにZipkinを導入
- OCI APMとZipkinの連携
- bookinfoアプリに対する分散トレーシングの実行

# はじめに
分散トレーシングとはマイクロサービスアーキテクチャで構築されたアプリケーションを監視する仕組みで、複数のサービスに跨ってリクエストが伝搬する様子を可視化し、問題発生箇所の特定やパフォーマンス・ボトルネックの分析を行うことができます。前回の記事で導入したサービスメッシュ Istio では、オープンソースの分散トレーシングシステムのJaegerやZipkinと連携することができ、Envoyが生成するトレースを集約し分析することが可能です。

一方、Oracle Cloud Infrastructure (OCI) では分散トレーシングを実行可能なOracle Cloud Observability and Management PlatformのサービスとしてApplication Performance Monitoring (OCI APM) が提供されています。OCI APMでは、クライアントサイドのブラウザで実行されるWebアプリケーションのパフォーマンスを監視するリアル・ユーザー・モニタリングと、サーバーサイドの監視機能の一つとしてマイクロサービスアーキテクチャで実装されたシステムで分散トレーシングを実施し分析できるトレース・エクスプローラーの機能を提供しています。また、Javaアプリケーションの監視に利用できるAPM JavaエージェントやAPM Javaトレーサーを提供していますが、JaegerやZipkinといった分散トレーシングシステムならびにオープンソース・トレーサと統合することも可能です。

本記事では、IstioとZipkinおよびOCI APMを連携し、Oracle Cloud Infrastructure (OCI) で提供されるKubernetes基盤であるOracle Container Engine for Kubernetes (OKE)上で稼働するマイクロサービスアーキテクチャで実装されたbookinfoアプリケーションに対する分散トレーシングを実装します。

# 検証環境 
- Kubernetes: 1.22.5
- Istio: 1.13.3

OKEへのIstioのインストールは[前回の記事](https://qiita.com/orakurara/items/e0ccdcc3a8048e5f3c76)を参照ください。
なお、本記事の検証は管理者ユーザー (Administrators Groupに属したユーザー) で実施しています。
dministrators Groupに属したユーザーで実施する場合は、下記のドキュメントに従って必要なポリシーを設定する必要があります。

[Application Performance Monitoring (APM)
Application Performance Monitoringの詳細](https://docs.oracle.com/ja-jp/iaas/Content/Identity/Reference/apmpolicyreference.htm)


# APMドメインのセットアップ
OCIサービスコンソールの左上のメニュー**監視および管理**より、アプリケーション・パフォーマンス・モニタリングの**管理**を選択し、OCI APMの管理画面でAPMドメインを作成するコンパートメントを選択し、**APMドメインの作成**ボタンを押します。

![Fig18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/831381/3a5123fe-1fd6-aada-ef78-059f67037bb0.png)

![Fig19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/831381/67e0cf3f-430d-28e3-5a0c-6d798a4ea33b.png)

下記の様に各項目を入力し **作成**ボタンを押します。

---
* 名前: 任意の名前　IstioAPM
* コンパートメントの選択: 任意のコンパートメント名　 /dev
* 説明: 任意　Istio Test
* Always Freeドメインとして作成: 選択　一定の制約・機能制限の元で無償で利用可能

---

![Fig20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/831381/c6895575-06c3-b0bd-75d7-77c93c58195f.png)


数十秒から数分でAPMドメインがアクティブになり利用する準備が完了します。
ここで、監視対象となるアプリケーションとの連携に必要となる**データ・アップロード・エンドポイント**および**プライベート・データ・キー** (サーバー・サイドの監視に必要) をメモしておいてください。
（**パブリック・データ・キー**はリアル・ユーザー・モニタリングのためのブラウザ・エージェントの設定に利用しますが本記事では利用しません）

![Fig21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/831381/a9374bc0-6d7e-5be2-7f0e-ef75a98b1d14.png)


# IstioおよびZipkin, OCI APMの連携
[前回の記事]()で構築したOKE上のIstioにZipkinをインストールし、Istioのトレーシングを有効化します。
なお、この後の操作は全てistio-1.13.3ディレクイトリ下で実施しています。

```shell
$ kubectl apply -f samples/addons/extras/zipkin.yaml

deployment.apps/zipkin created
service/tracing created
service/zipkin created

$ istioctl install --set meshConfig.enableTracing=true

This will install the Istio 1.13.3 default profile with ["Istio core" "Istiod" "Ingress gateways"] components into the cluster. Proceed? (y/N) y
✔ Istio core installed                                                                                                                                                                                     
✔ Istiod installed                                                                                                                                                                                         
✔ Ingress gateways installed                                                                                                                                                                               
✔ Installation complete                                                                                                                                                                                    
Making this installation the default for injection and validation.

Thank you for installing Istio 1.13.  Please take a few minutes to tell us about your install/upgrade experience!  https://forms.gle/pzWZpAvMVBecaQ9h9

```

Zipkinを導入し、Istioのトレーシングを有効化します。

```shell
$ istioctl install --set meshConfig.defaultConfig.tracing.zipkin.address=“aaaa略: エンドポイント .apm-agt.ap-tokyo-1.oci.oraclecloud.com:443”

This will install the Istio 1.13.3 default profile with ["Istio core" "Istiod" "Ingress gateways"] components into the cluster. Proceed? (y/N) y
✔ Istio core installed                                                                                                                                                                                     
✔ Istiod installed                                                                                                                                                                                         
✔ Ingress gateways installed                                                                                                                                                                               
✔ Installation complete                                                                                                                                                                                    
Making this installation the default for injection and validation.

Thank you for installing Istio 1.13.  Please take a few minutes to tell us about your install/upgrade experience!  https://forms.gle/pzWZpAvMVBecaQ9h9

```

`aaaa略: エンドポイント .apm-agt.ap-tokyo-1.oci.oraclecloud.com`の部分はAPMドメインを作成した際に確認した**データ・アップロード・エンドポイント**の値に置き換えてください。
ZipkinトレースをOCI APMに送信するようにEnvoyを構成します。bookinfoアプリケーションが稼働するdefaultネームスペースにConfigmap `istio-custom-bootstrap-config`を作成するためのyamlファイルを作成します。まず、予め用意されている`samples/custom-bootstrap/custom-bootstrap.yamlファイル`のバックアップを取得し、内容を編集します。

```shell
$ cp samples/custom-bootstrap/custom-bootstrap.yaml samples/custom-bootstrap/custom-bootstrap_default.yaml

```

```samples/custom-bootstrap/custom-bootstrap_default.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: istio-custom-bootstrap-config
  namespace: default
data:
  custom_bootstrap.json: |
    {
        "tracing": {
            "http": {
                "name": "envoy.tracers.zipkin",
                "typed_config": {
                    "@type": "type.googleapis.com/envoy.config.trace.v3.ZipkinConfig",
                    "collector_cluster": "aaaa略: エンドポイント .apm-agt.ap-tokyo-1.oci.oraclecloud.com", 
                    "collector_endpoint": "/20200101/observations/private-span?dataFormat=zipkin&dataFormatVersion=2&dataKey=HZST 略: プライベート・データ・キー 5BTKE", 
                    "collectorEndpointVersion": "HTTP_JSON",
                    "trace_id_128bit": true,
                    "shared_span_context": false
                }
            }
        },
        "static_resources": {
            "clusters": [{
                "name": "aaaa略: エンドポイント .apm-agt.ap-tokyo-1.oci.oraclecloud.com", 
                "type": "STRICT_DNS",
                "lb_policy": "ROUND_ROBIN",
                "load_assignment": {
                    "cluster_name": "aaaa略: エンドポイント .apm-agt.ap-tokyo-1.oci.oraclecloud.com", 
                    "endpoints": [{
                        "lb_endpoints": [{
                            "endpoint": {
                                "address": {
                                    "socket_address": {
                                        "address": "aaaa略: エンドポイント .apm-agt.ap-tokyo-1.oci.oraclecloud.com", 
                                        "port_value": 443
                                    }
                                }
                            }
                        }]
                    }]
                },
                "transport_socket": {
                    "name": "envoy.transport_sockets.tls",
                    "typed_config": {
                        "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext",
                        "sni": "aaaa略: エンドポイント .apm-agt.ap-tokyo-1.oci.oraclecloud.com" 
                    }
                }
            }]
        }
    }
```

`aaaa略: エンドポイント .apm-agt.ap-tokyo-1.oci.oraclecloud.com`の部分はAPMドメインを作成した際に確認した**データ・アップロード・エンドポイント**に、`HZST 略: プライベート・データ・キー 5BTKE`の部分は**プライベート・データ・キー**の値に置き換えてください。
Configmapを作成します。

```shell
$ kubectl apply -f samples/custom-bootstrap/custom-bootstrap_default.yaml 

configmap/istio-custom-bootstrap-config configured

```

bookinfoのすべてのサービスにカスタム・ブートストラップの構成のConfigmapが適用されるように、`samples/bookinfo/platform/kube/bookinfo.yaml`に記載されている全てのDeploymentにannotationsとして、sidecar.istio.io/bootstrapOverrideを追加し、Configmap `istio-custom-bootstrap-config`を適用させます。下記はProductpage servicesの記述例となります。annotationsの追加位置と記述内容を確認し、`samples/bookinfo/platform/kube/bookinfo.yaml`内のすべてのサービスにannotationsを追加してください。

```samples/bookinfo/platform/kube/bookinfo.yaml
##################################################################################################
# Productpage services
##################################################################################################
apiVersion: v1
kind: Service
metadata:
  name: productpage
  labels:
    app: productpage
    service: productpage
spec:
  ports:
  - port: 9080
    name: http
  selector:
    app: productpage
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: bookinfo-productpage
  labels:
    account: productpage
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: productpage-v1
  labels:
    app: productpage
    version: v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: productpage
      version: v1
  template:
    metadata:
      labels:
        app: productpage
        version: v1
      annotations:
        sidecar.istio.io/bootstrapOverride: "istio-custom-bootstrap-config"
    spec:
      serviceAccountName: bookinfo-productpage
      containers:
      - name: productpage
        image:  nrt.ocir.io/nr6ka64odooa/bookinfo_productpage:latest
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9080
        volumeMounts:
        - name: tmp
          mountPath: /tmp
        securityContext:
          runAsUser: 1000
      volumes:
      - name: tmp
        emptyDir: {}
---

```
`samples/bookinfo/platform/kube/bookinfo.yaml`を適用します。Podが再起動しOCI APMへのトレースの送信を開始します。
Podの起動がうまく行かない場合は、APMのエンドポイント等の設定に不備がないか見直してください。


```shell
$ kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml

service/details unchanged
serviceaccount/bookinfo-details unchanged
deployment.apps/details-v1 configured
service/ratings unchanged
serviceaccount/bookinfo-ratings unchanged
deployment.apps/ratings-v1 configured
service/reviews unchanged
serviceaccount/bookinfo-reviews unchanged
deployment.apps/reviews-v1 configured
deployment.apps/reviews-v2 configured
deployment.apps/reviews-v3 configured
service/productpage unchanged
serviceaccount/bookinfo-productpage unchanged
deployment.apps/productpage-v1 configured

$ kubectl get pods

NAME                              READY   STATUS    RESTARTS   AGE
details-v1-864b679fdd-44k4g       2/2     Running   0          60s
productpage-v1-6cf57876db-8wfsr   2/2     Running   0          60s
ratings-v1-598d7d4cc6-grdjb       2/2     Running   0          60s
reviews-v1-5d6559df86-6qdwk       2/2     Running   0          60s
reviews-v2-6d7d68855b-lk9pf       2/2     Running   0          60s
reviews-v3-5bb4b69c94-rl9tc       2/2     Running   0          60s 

```

完全なトレースを取得するためにIstioのIngress Gateway経由でトレースを取得できるようにistio-systemネームスペースにもConfigmap `istio-custom-bootstrap-config`を作成するためのyamlファイルを作成します。
予め用意されている`samples/custom-bootstrap/custom-bootstrap.yamlファイル`のバックアップを取得し、内容を編集します。

```shell
$ cp samples/custom-bootstrap/custom-bootstrap_default.yaml samples/custom-bootstrap/custom-bootstrap_istiosystem.yaml

```

```custom-bootstrap_istiosystem.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: istio-custom-bootstrap-config
  namespace: istio-system
data:
  custom_bootstrap.json: |
    {
        "tracing": {
            "http": {
                "name": "envoy.tracers.zipkin",
                "typed_config": {
                    "@type": "type.googleapis.com/envoy.config.trace.v3.ZipkinConfig",
                    "collector_cluster": "aaaa略: エンドポイント .apm-agt.ap-tokyo-1.oci.oraclecloud.com", 
                    "collector_endpoint": "/20200101/observations/private-span?dataFormat=zipkin&dataFormatVersion=2&dataKey=HZST 略: プライベート・データ・キー 5BTKE", 
                    "collectorEndpointVersion": "HTTP_JSON",
                    "trace_id_128bit": true,
                    "shared_span_context": false
                }
            }
        },
        "static_resources": {
            "clusters": [{
                "name": "aaaa略: エンドポイント .apm-agt.ap-tokyo-1.oci.oraclecloud.com", 
                "type": "STRICT_DNS",
                "lb_policy": "ROUND_ROBIN",
                "load_assignment": {
                    "cluster_name": "aaaa略: エンドポイント .apm-agt.ap-tokyo-1.oci.oraclecloud.com", 
                    "endpoints": [{
                        "lb_endpoints": [{
                            "endpoint": {
                                "address": {
                                    "socket_address": {
                                        "address": "aaaa略: エンドポイント .apm-agt.ap-tokyo-1.oci.oraclecloud.com", 
                                        "port_value": 443
                                    }
                                }
                            }
                        }]
                    }]
                },
                "transport_socket": {
                    "name": "envoy.transport_sockets.tls",
                    "typed_config": {
                        "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext",
                        "sni": "aaaa略: エンドポイント .apm-agt.ap-tokyo-1.oci.oraclecloud.com" 
                    }
                }
            }]
        }
    }

```

`aaaa略: エンドポイント .apm-agt.ap-tokyo-1.oci.oraclecloud.com`の部分はAPMドメインを作成した際に確認した**データ・アップロード・エンドポイント**に、`HZST 略: プライベート・データ・キー 5BTKE`の部分は**プライベート・データ・キー**の値に置き換えてください。
Configmapを作成します。

```shell
$ kubectl apply -f samples/custom-bootstrap/custom-bootstrap_istiosystem.yaml

configmap/istio-custom-bootstrap-config configured

```

カスタム・ブートストラップ構成を適用させるために、Ingress Gateway用の`gateway-patch.yaml`という名前のパッチを作成します。

```gateway-patch.yaml
spec:
  template:
    spec:
      containers:
      - name: istio-proxy
        env:
        - name: ISTIO_BOOTSTRAP_OVERRIDE
          value: /etc/istio/custom-bootstrap/custom_bootstrap.json
        volumeMounts:
        - mountPath: /etc/istio/custom-bootstrap
          name: custom-bootstrap-volume
          readOnly: true
      volumes:
      - configMap:
          name: istio-custom-bootstrap-config
          defaultMode: 420
          optional: false
        name: custom-bootstrap-volume

```
Ingress Gatewayにパッチを適用します。

```shell
$ kubectl --namespace istio-system patch deployment istio-ingressgateway --patch "$(cat gateway-patch.yaml)"

deployment.apps/istio-ingressgateway patched

```

Ingress Gatewayが正常に稼働していることを確認します。

```shell
$ kubectl get pods -n istio-system

NAME                                    READY   STATUS    RESTARTS   AGE
istio-ingressgateway-7947fb996f-9gwx5   1/1     Running   0          99s
istiod-7c595445b6-j5xfz                 1/1     Running   0          3h2m
zipkin-6cd5d58bcc-j54nq                 1/1     Running   0          125m

```

Istioのトレースが生成されるように下記コマンドをシェルで実行し、bookinfoアプリケーションにアクセスしておきます。

```shell
for i in $(seq 1 100); do curl -s -o /dev/null "http://XX.XX.XX.XX/productpage"; done
```

# OCI APMのトレース・エクスプローラの確認
OCIサービスコンソールの左上のメニュー**監視および管理**より、アプリケーション・パフォーマンス・モニタリングの**ホーム**を選択します。

![Fig42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/831381/497e14ae-1f0a-8c44-faa5-361bde23e1d6.png)

![Fig43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/831381/0cff60d0-e7ca-f098-185e-c6d72795976a.png)

Istioで分散トレースが生成されていれば画面中央の**トレース**グラフで確認できます。設定して直ぐに表示されない場合は表示されるまで少し時間をおいて、画面右上の**アクション**メニューから**リフレッシュ**を行ってください。
**トレース**をクリックすると、トレースの詳細を確認出るトレース・エクスプローラの画面に遷移します。赤枠で囲われた**Traces**を選択し、検出されたトレースの一覧を表示します。

![Fig45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/831381/8808e436-2c68-4fbc-bbc9-f6fa67795607.png)

![Fig46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/831381/e4d15f32-ebe6-9685-726b-3b14463b09e0.png)


さらにサービスオペレーションの項目を選択することでトレースの詳細やスパンを確認することが出来ます。

![Fig47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/831381/8323fded-2ad8-bb99-236a-988b04296d7d.png)


# 最後に
IstioとZipkinおよびOCI APMを連携し、OKE上で稼働するマイクロサービスアーキテクチャで実装されたbookinfoアプリケーションに対する分散トレーシングを実施することが出来ました。
LoggingとLogging Analyticsを利用したIstioのログ分析に[続く](https://qiita.com/orakurara/items/b4a02394422aabc6ee8d)。。。

# 参考情報
[Oracle Cloud Infrastructureドキュメント　例: OKEへのIstioサービス メッシュのインストール](https://docs.oracle.com/ja-jp/iaas/Content/ContEng/Tasks/contengistio-intro-topic.htm#managing_traffic)

[Oracle Cloud Infrastructureドキュメント　Application Performance Monitoring](https://docs.oracle.com/ja-jp/iaas/application-performance-monitoring/index.html)

[OCIチュートリアル　Oracle Container Engine for Kubernetes(OKE)でサンプルマイクロサービスアプリケーションをデプロイしてオブザバビリティツールを利用してみよう](https://oracle-japan.github.io/ocitutorials/cloud-native/oke-for-advances/)