Evidently AI 公開サンプルをkube-prometheus-stackで監視

<!--
title: Evidently AI 公開サンプルをkube-prometheus-stackで監視
tags: Kubernetes, MLOps, モニタリング, Evidently AI, kube-prometheus-stack
-->

# はじめに
前回、[Evidently AI 公開サンプルをKubernetes上で実行](https://qiita.com/kanchi_tdse/items/113ffde0d9ee77b9527c)ということを行いました。今回はその続きで、その結果をkube-prometheus-stackで監視することをやってみました。

[kube-prometheus-stack](https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack)はprometheus-communityで提供されているKubernetesリソースをprometheus/grafanaを使って監視するOSSで、可視化する専用のダッシュボードも予め数多く定義されています。この中でEvidently AI 公開サンプルのメトリクスも一緒に監視できないかなと考えました。


# システム環境
- PC: Windows 11
- WSL2: Ubuntu 20.04
- Docker 20.10.17
- Python 3.8.10
- Amazon Elastic Container Registry (ECR)
    - AWS CLIがインストールされていることが必要です。

今回はkubernetesがDockerイメージを取得するためのレジストリとしてECRを使っていますが、ここは別のコンテナレジストリで代用してもらっても大丈夫です。

# 構築手順
前提として、[Evidently AI 公開サンプルをKubernetes上で実行](https://qiita.com/kanchi_tdse/items/113ffde0d9ee77b9527c)の内容が一通り実行されていることが必要です。


## 1. 環境準備
まずは、minikubeを起動します。
```sh
# minikubeの起動
minikube start --kubernetes-version=v1.23.2 --memory=6g \
  --bootstrapper=kubeadm \
  --extra-config=kubelet.authentication-token-webhook=true \
  --extra-config=kubelet.authorization-mode=Webhook \
  --extra-config=scheduler.bind-address=0.0.0.0 \
  --extra-config=controller-manager.bind-address=0.0.0.0

# 認証情報の設定（新規にminikubeクラスタを作成した場合）
# ECRにアクセスするために設定します。対話形式でAWSの認証情報を入力します。
minikube addons configure registry-creds
#----- 対話形式での入力（ここから） -----
Do you want to enable AWS Elastic Container Registry? [y/n]: y
-- Enter AWS Access Key ID: <アクセスキーID>
-- Enter AWS Secret Access Key: <シークレットキー>
-- (Optional) Enter AWS Session Token: <空のままEnter>
-- Enter AWS Region: <リージョン名>
-- Enter 12 digit AWS Account ID (Comma separated list): <AWSアカウントID>
-- (Optional) Enter ARN of AWS role to assume: <空のままEnter>
# これ以降の質問はすべて"n"を入力
#----- 対話形式での入力（ここまで） -----

# 認証設定の有効化
minikube addons enable registry-creds
```

次に、kube-prometheus-stackをインストールします。インストールにはhelmを使いますが、helmは`asdf`を使って準備しました。
```sh
# helmのインストール
# 安定版の最新バージョンをインストールする
asdf plugin-add helm
asdf list-all helm
asdf install helm 3.9.0
asdf global helm 3.9.0

# Helmリポジトリ情報の取得
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update

# kube-prometheus-stackのインストール
helm upgrade kube-prometheus-stack prometheus-community/kube-prometheus-stack \
    --install --version 35.2.0 \
    --namespace prometheus --create-namespace \
    --set grafana.ingress.enabled=true \
    --set grafana.ingress.ingressClassName=nginx \
    --wait
```


## 2. kube-prometheus-stackのServiceMonitorの追加
AIモニタリングで算出されたメトリクスをkube-prometheus-stackが読み取るためには、ServiceMonitorというカスタムリソースを設定する必要があります。そのためのマニフェストファイルを作成します。
```yaml:manifests/servicemonitor_ai-monitor.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: ai-monitor-clusterip
  namespace: default
  labels:
    release: kube-prometheus-stack
spec:
  endpoints:
    - path: /metrics
      targetPort: 8085
      interval: 10s
  selector:
    matchLabels:
      app: ai-monitor-clusterip
```
- ai-monitorのアプリはPrometheus向けに/metricsのパスでメトリクスを取得できる口を設定しています。


## 3. 各種Kubernetesリソースの生成
Kubernetesリソースを生成します。次のコマンドを実行するには、[Evidently AI 公開サンプルをKubernetes上で実行](https://qiita.com/kanchi_tdse/items/113ffde0d9ee77b9527c)にある、「3. AIモニタのDockerイメージのビルド、およびECRへのプッシュ」「4. Kubernetesのマニフェストファイルの作成」が行われていることが必要になります。

```sh
# ai-monitorのリソース生成
kubectl apply -f manifests/depsvc_ai-monitor.yaml

# ServiceMonitorの生成
kubectl apply -f manifests/servicemonitor_ai-monitor.yaml
```


## 4. ポートフォワードの実行
Minikubeの外部からアクセスできるようにポートフォワードを行います。
```sh
# prometheusのポートフォワード（バックグラウンド実行）
kubectl --namespace prometheus port-forward svc/kube-prometheus-stack-prometheus --address 0.0.0.0 9090:9090 >/dev/null &
# grafanaのポートフォワード（バックグラウンド実行）
kubectl --namespace prometheus port-forward svc/kube-prometheus-stack-grafana --address 0.0.0.0 3000:80 >/dev/null &
# ai-monitorのポートフォワード（バックグラウンド実行）
kubectl port-forward svc/ai-monitor-clusterip --address 0.0.0.0 8085 >/dev/null &
```


## 5. データの送信とダッシュボードの確認
クライアントからデータを送信し、その結果をGrafanaのダッシュボードで確認します。
```sh
# Evidently AIサンプルのフォルダに移動
cd evidently/examples/integrations/grafana_monitoring_service

# データ送信のClient App実行
# これを実行すると2秒間隔で連続的にデータ送信する処理が約20分間動きます。
python scripts/example_run_request.py
```

データの送信が開始されたら、Grafanaのダッシュボードhttp//localhost:3000にアクセスします。
kube-prometheus-stackではGrafanaのadminユーザのパスワードがKubernetesのSecretで別途設定されています。パスワードは次のコマンドで確認します。
```sh
# grafanaのadminユーザのパスワード確認
kubectl get secret kube-prometheus-stack-grafana -n prometheus \
  -o jsonpath='{.data.admin-password}' | base64 --decode; echo
```

Grafanaにログインしたら、メニューから Create > Import を選択します。

![sub004-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724847/ef0b28e1-bb63-9811-2845-f3ce796d2e21.png)


ここに、evidently/examples/integrations/grafana_monitoring_service/dashboardsフォルダにあるjsonファイルを貼り付けて、Loadします。
この時に、jsonファイル中にある`UID`の記述の部分（複数個所あります）は削除します。
```json
          "datasource": {
            "type": "prometheus",
            "uid": "PBFA97CFB590B2093"    ← この部分を削除。複数個所あるのでそれぞれ削除します。
          },
```
![sub004-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724847/0de9588c-8d2c-de41-f5b9-20d7c32a9768.png)


すると下図のようにダッシュボードが表示されます。
![sub004-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724847/ba247151-b3d4-8935-0c91-eef284ebf99b.png)


## 終了・削除手順
今回作成したリソースは下記のように終了・削除します。
```bash
# ポートフォワードの終了
# job番号は実際の数値に変更してください
jobs
kill %1
kill %2
kill %3

# kubernetesリソースの削除
cd ~
kubectl delete -f manifests/depsvc_ai-monitor.yaml \
  -f manifests/servicemonitor_ai-monitor.yaml

# kube-prometheus-stackのアンインストール
helm uninstall kube-prometheus-stack -n prometheus

# minikubeの停止
minikube stop
```

## おわりに
kube-prometheus-stackはインストールしてすぐに使えるのがうれしいです。ServiceMonitorの追加をすればアプリのメトリクスも取ってこれるので、基盤のモニタリングとアプリのモニタリングが一括でできるのもいいですね。