KialiAPIでPodのトラフィックを取得してみた

## Kialiとは
Istioが提供しているKubernetesクラスタ内のマイクロサービスアプリケーションの可視化，トラフィックのモニタリング，サービスメッシュの分析のためのオープンソースのプロジェクトです．提供する機能は以下のものになります．
* **サービスメッシュの可視化**
    サービスメッシュ内のサービスの関係を可視化するダッシュボードの提供．
* **トラフィックモニタリング**
    トラフィックの流れ，通信パターンを視覚化．
* **トポロジーマップの提供**
    サービスやワークロードの関係を示すトポロジーマップを提供．
* **サービスのヒストリカルデータ**
    過去のトラフィックデータやメトリクスを取得・分析が可能．

## KialiAPI
Kialiが提供する機能に対してプログラムがアクセスするためのAPIです．今回はこれを使用してPodのトラフィックを取得する．

## 今回使用する環境
* **K3sクラスタ**
今回Podをデプロイする環境．軽量化されたKubernetesクラスタで，公式のドキュメントを参考にしてインストールを行いました．
* **SockShop**
Weaveworksが公開しているマイクロサービスで作られたECサイトのデモアプリケーションです．K3sクラスタにデプロイして使用します．

* **Envoyコンテナ**
Istioサービスメッシュ内で動作するインスタンス．サービスメッシュ内でのトラフィック制御や監視を行います．マイクロサービスのPod内にサイドカーコンテナとして挿入して使用します．

* **Kiali**
KialiAPIを使用するためにクラスタ内にデプロイします．

SockShopにIstioを導入する方法は[こちら](https://qiita.com/hikida621/items/ddebe34566d5fce913fc)を参考にしました．

## PodのトラフィックをAPIを介して取得
トラフィックを取得するためのAPIは下のものになります．
```
curl http://{クラスタのIPアドレス}:{Kialiのポート番号}/kiali/api/namespaces/{対象のPodが配置されたnamespace}/services/{対象のPodのマイクロサービス名}/graph
```

※トラフィックを取得する際にはアプリケーションの全てのエンドポイントに対してアクセスを行った後，APIを用いてトラフィックを取得することで各Pod間で通信が行われすべてのトラフィックを把握することが可能

実行結果↓
<details>
<summary>クリックして結果を表示/非表示</summary>
{
  "timestamp": 1700632702,
  "duration": 600,
  "graphType": "workload",
  "elements": {
    "nodes": [
      {
        "data": {
          "id": "7507eac8fd04d1b6d8f7580ab1b0e6d9",
          "nodeType": "workload",
          "cluster": "Kubernetes",
          "namespace": "sock-shop",
          "workload": "carts",
          "app": "carts",
          "version": "latest",
          "destServices": [
            {
              "cluster": "Kubernetes",
              "namespace": "sock-shop",
              "name": "carts"
            }
          ],
          "traffic": [
            {
              "protocol": "http",
              "rates": {
                "httpIn": "4.78",
                "httpIn5xx": "0.003"
              }
            }
          ],
          "healthData": null
        }
      },
      {
        "data": {
          "id": "77497bd9a4e70ad6ef8cbc06bb0b0c39",
          "nodeType": "workload",
          "cluster": "Kubernetes",
          "namespace": "sock-shop",
          "workload": "front-end",
          "app": "front-end",
          "version": "latest",
          "traffic": [
            {
              "protocol": "http",
              "rates": {
                "httpOut": "3.66"
              }
            }
          ],
          "healthData": null,
          "isRoot": true
        }
      },
      {
        "data": {
          "id": "80182136e061224ba3514be7dc777205",
          "nodeType": "workload",
          "cluster": "Kubernetes",
          "namespace": "sock-shop",
          "workload": "orders",
          "app": "orders",
          "version": "latest",
          "traffic": [
            {
              "protocol": "http",
              "rates": {
                "httpOut": "1.05"
              }
            }
          ],
          "healthData": null,
          "isRoot": true
        }
      },
      {
        "data": {
          "id": "375ab940b56ae7bcf0f89cb1a7af5d44",
          "nodeType": "unknown",
          "cluster": "unknown",
          "namespace": "unknown",
          "workload": "unknown",
          "app": "unknown",
          "version": "latest",
          "traffic": [
            {
              "protocol": "http",
              "rates": {
                "httpOut": "0.07"
              }
            }
          ],
          "healthData": null,
          "isInaccessible": true,
          "isRoot": true
        }
      }
    ],
    "edges": [
      {
        "data": {
          "id": "0b45e9d28f781c4f4e2e6a6a589caa47",
          "source": "375ab940b56ae7bcf0f89cb1a7af5d44",
          "target": "7507eac8fd04d1b6d8f7580ab1b0e6d9",
          "destPrincipal": "unknown",
          "responseTime": "250",
          "sourcePrincipal": "unknown",
          "throughput": "1402",
          "traffic": {
            "protocol": "http",
            "rates": {
              "http": "0.07",
              "httpPercentReq": "100.0"
            },
            "responses": {
              "200": {
                "flags": {
                  "-": "100.0"
                },
                "hosts": {
                  "carts.sock-shop.svc.cluster.local": "100.0"
                }
              }
            }
          }
        }
      },
      {
        "data": {
          "id": "dfa1c9193a4a98f556205f06f1e06224",
          "source": "77497bd9a4e70ad6ef8cbc06bb0b0c39",
          "target": "7507eac8fd04d1b6d8f7580ab1b0e6d9",
          "destPrincipal": "spiffe://cluster.local/ns/sock-shop/sa/default",
          "isMTLS": "100",
          "responseTime": "9493",
          "sourcePrincipal": "spiffe://cluster.local/ns/sock-shop/sa/default",
          "throughput": "3603",
          "traffic": {
            "protocol": "http",
            "rates": {
              "http": "3.66",
              "http5xx": "0.003",
              "httpPercentErr": "0.1",
              "httpPercentReq": "100.0"
            },
            "responses": {
              "201": {
                "flags": {
                  "-": "29.6"
                },
                "hosts": {
                  "carts.sock-shop.svc.cluster.local": "29.6"
                }
              },
              "202": {
                "flags": {
                  "-": "70.3"
                },
                "hosts": {
                  "carts.sock-shop.svc.cluster.local": "70.3"
                }
              },
              "500": {
                "flags": {
                  "-": "0.1"
                },
                "hosts": {
                  "carts.sock-shop.svc.cluster.local": "0.1"
                }
              }
            }
          }
        }
      },
      {
        "data": {
          "id": "69a23bb3cf73059a73710a059d871eb8",
          "source": "80182136e061224ba3514be7dc777205",
          "target": "7507eac8fd04d1b6d8f7580ab1b0e6d9",
          "destPrincipal": "spiffe://cluster.local/ns/sock-shop/sa/default",
          "isMTLS": "100",
          "responseTime": "3190",
          "sourcePrincipal": "spiffe://cluster.local/ns/sock-shop/sa/default",
          "throughput": "1189",
          "traffic": {
            "protocol": "http",
            "rates": {
              "http": "1.05",
              "httpPercentReq": "100.0"
            },
            "responses": {
              "200": {
                "flags": {
                  "-": "98.6",
                  "DC": "1.4"
                },
                "hosts": {
                  "carts.sock-shop.svc.cluster.local": "100.0"
                }
              }
            }
          }
        }
      }
    ]
  }
}