KubernetesにGrafana Lokiをインストールする

# この記事について
KubernetesにGrafana Lokiをインストールしたのでメモを残す。

# 前提条件
- Kubernetesクラスタは構築済み
- kubectl, helm導入済み

# Kubernetesにおけるログ
以下のKubernetesの公式ドキュメントに詳しく書かれている。

https://kubernetes.io/ja/docs/concepts/cluster-administration/logging/

Podのログは、`kubectl logs <pod name>`で出力されるが、
これは、Podが稼働しているノードの`/var/log`の下に保存されている。
（kubernetesの構成要素のうち、非コンテナのものは、`/var/log`に保存されないものもあるが、今回は割愛。）
KubernetesではPodが終了するとログも消去するため、ログを永続化するためには自前でソリューションを導入しなければならない。
今回は、Grafana + Grafana Loki + Promtailでこれを実現する。

# Grafana Lokiについて
LokiはGrafanaとセットで使われるログ収集のOSS。Grafana Labsが開発している。

- Grafana: Lokiが集めたログを可視化するダッシュボードである。モニタリングツールのPrometheusとよくセットで使われる。
- Grafana Loki: ログを集約するエージェント。
- Promtail: 各ノードにDaemonSetとしてデプロイされ、ノードに保存されたログをGrafana Lokiに転送する。


https://grafana.com/docs/loki/latest/fundamentals/architecture/deployment-modes/


## Lokiのデプロイモードについて

Lokiには、コンポーネントの分割粒度によっていくつかのデプロイモードが用意されている。

- モノリシックモード: すべてのコンポーネントをシングルのバイナリでデプロイする。Lokiのテストや、1日100GB程度のread/writeなどの場合に選択する。
- シンプルスケーラブルデプロイモード: readとwriteのコンポーネントを分離してデプロイする。1日100GBを超える場合や、readとwriteを別々にスケールしたい場合に選択する。
- マイクロサービスモード: Lokiのコンポーネントをすべて個別にデプロイする。コンポーネントごとに細かくスケールしたい場合に選択する。保守が大変。

https://grafana.com/docs/loki/latest/fundamentals/architecture/deployment-modes/

HELM Chartは以下にある。

https://github.com/grafana/helm-charts

HELM Chartも複数用意されており、用途にあったものを選ぶ必要がある。主要なのは、以下の3つ。
- grafana/loki: シンプルスケーラブルデプロイモードでlokiをデプロイする。
- grafana/loki-distributed: マイクロサービスモードでlokiをデプロイする。
- grafana/loki-stack: モノリシックモードでlokiをデプロイする。あわせて、promtailなどもセットでデプロイする。

ただ動作を確認するだけであればgrafana/loki-stackが最も楽だが、他の2つに比べてvalues.yamlで指定できる項目が少ないため、カスタマイズがしづらい。
マイクロサービスモードまでは不要なので、今回はシンプルスケーラブルデプロイモードのgrafana/lokiを選択する。

# 構築手順

## 環境
- Azure Kubernetes Service
    - Kubernetes Version: 1.26.6
    - Agentpoolのノードサイズと数: Standard_B2ms x 1

## helmリポジトリの追加
```bash
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
```

## Grafana Lokiのインストール

grafana lokiをインストールする。
- ストレージはとりあえずminioを使う。
- デフォルトではloki.auth_enabled=trueがセットされマルチテナントモードになる。マルチテナントモードではGrafanaとの通信にテナントの選択などが必要で設定が煩雑なので、とりあえずfalseにしておく。
- read, write, backendのreplica数は1でOK。
    - replication_factorはデータ保護のためにwriteデータをレプリケーションするための設定。writeを1にしたため、こちらも1にしておかないと正常動作しない。

https://grafana.com/docs/loki/latest/operations/multi-tenancy/

https://grafana.com/blog/2021/02/16/the-essential-config-settings-you-should-use-so-you-wont-drop-logs-in-loki/

```bash
kubectl create namespace grafana
helm install loki -n grafana grafana/loki \
  --set minio.enabled=true \
  --set write.replicas=1 \
  --set read.replicas=1 \
  --set backend.replicas=1 \
  --set loki.auth_enabled=false \
  --set loki.commonConfig.replication_factor=1
```

## Promtailのインストール
これも公式の手順を参考に。基本的にデフォルト設定のままでOK。
namespaceはLokiと同じものを指定しておく。

https://grafana.com/docs/loki/latest/clients/promtail/installation/

```bash
helm install promtail -n grafana grafana/promtail
```

## Grafana のインストール
公式を参考に。

https://grafana.com/docs/loki/latest/installation/helm/

grafanaのインストール
```bash
helm install grafana -n grafana grafana/grafana --set service.type=LoadBalancer
```

Adminパスワードを取得する。
```bash
kubectl get secret --namespace grafana grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo
```

External IPアドレスを取得する。
```bash
kubectl get svc -n grafana grafana -o jsonpath="{.status.loadBalancer.ingress[0].ip}"
```

取得したIPアドレスにブラウザでアクセスし、ユーザー名：admin、パスワード：(先程取得したパスワード)でログインする。


### Data Sourceの設定
- 以下の設定を参考に
- HTTPのURLの欄に`http://loki-gateway`と入力し設定を保存する
    - grafanaとlokiのnamespaceが異なる場合は`http://loki-gateway.{namespace}.svc.cluster.local`と入力する


https://grafana.com/docs/grafana/latest/datasources/loki/configure-loki-data-source/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290024/cb0434ae-adbd-bee6-b988-db1eab4aef03.png)


## 動作確認
ログを収集できているか確認するため、
カウンターを標準出力にアウトプットする以下のサンプルPodをデプロイする。
（サンプルPodの出典は[Kubernetesの公式ドキュメント](https://kubernetes.io/ja/docs/concepts/cluster-administration/logging/
)）

```
kubectl apply -f https://k8s.io/examples/debug/counter-pod.yaml
```

grafanaのHOME > Exploreから``` {pod="counter"} |= `` ```  等のクエリを発行すると、counterが表示されていることが確認できる。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290024/99544f89-73e3-9607-f8a8-9abc2c04a5b6.png)


# まとめ
公式のHelm Chartほぼそのままでデプロイできた。
Lokiのインストール時のオプションの組み合わせによっては、Lokiが正常動作せず、Grafanaから接続できなくて結構ハマった。