Prometheus を使って Kubernetes 上に構築した Redis を監視する
PrometheusからRedisの状態を取得する
私は普段 Redis を GKE 上に構築して使用していますが、GCP コンソール画面から得られる情報が Pod の CPU 使用率、メモリ使用率、ディスク使用率くらいしかなくもう少し細かい情報を得たいと考えていました。そこで Prometheus を使って Redis の状態を監視してしてみたところとても良い感じだったのでその方法を紹介してみたいと思います。 Prometheus を使うと Redis の INFO コマンドで得られる情報を時系列に見ることができます。Prometheus は機能が豊富でいろいろできるのですが、この記事では必要最低限の設定でサクッとPrometheusを使った監視環境を構築をしてみたいと思います。
Prometheusって何?
Prometheus は SoundCloud が中心になって開発しているプル型の監視ツールです。既存のプログラムコードを変えることなくサクッと導入できるのでおすすめです。詳細は本家サイト Prometheus - Monitoring system & time series database か、 最近は専門の書籍も出ていますのでその辺りをチェックしてみてください 。
構成
以下の3つを Kubernetes 上に構築します。
- Master/Slave構成のRedis
- 監視対象のコンテナ
- Exporter
- Redisのメトリクス情報をPrometheusが読み込める形式に変換するコンテナ
- Prometheus
- 収集したRedisのメトリクス情報を時系列DBに保存して公開してくれるコンテナ
PrometheusはPull型の監視ツールのため、被監視対象のサーバからメトリクスを取得する必要があります。Prometheus は Redis から直接メトリクス情報を取得することができません。代わりに Exporterと呼ばれる Redis のメトリクス情報取得するためのアダプタ的なコンテナを Reids と同じ Pod に配置してそこから監視に必要な情報を取得します。
Exporter はただの HTTP サーバです。Redis の各種メトリクス情報を Prometheus が解釈できるフォーマットに変換してくれます。Prometheus は Exporter が公開している /metrics
にアクセスしてメトリクスを収集します。
構築の手順
構築の流れは以下のようになります。
- Prometheus を単体で構築する
- マスタースレーブ構成の Redis を構築する
- Redis の配置された Pod に Exporter を追加する
- Prometheus が Exporter からデータを収集できるように設定を修正する
前準備
本記事では Kubernetes 関連の yaml ファイルのデプロイに Kustomize を使います。以下のように k8s 関連の yaml を base という名前のディレクトリに格納するようにしてください。
base/ ├ deployment.yaml ├ service.yaml └ ...etc
Prometheusを単体でk8s上に構築してみる
Prometheus を Kubernetes 上に構築するには Deployment と Service に加えて専用のコンフィグファイルをマウントする必要があります。
Deploymentの作成
はじめに Prometheus 本体の Pod リソースの設定をするため Deployment を作成します。Prometheus のコンテナは Docker Hub の prom/prometheus を使用します。 コンテナのポートは 9090 に設定します。stats という名前の Namespace 上に構築します(Namespaceの設定はあとでサービスと一緒に実施します)。
収集したメトリクス情報を保存するためのボリューム(data-volume)とConfigMap を読み込むためのボリューム(config-volume)をマウントしています。レプリカ数は1に設定します。
サービスの作成
Deployment が作成できたので Prometheus にアクセスするためのサービスを作成します。
今回は Service と一緒に Prometheus 専用の stats という名前の Namespace の定義もします。Service のタイプが LoadBalancer になっていますが、実際に運用する場合はロードバランサを internal にするか NodePort あたりを使ってください。
prometheus.yamlの作成
最後に Prometheus の設定をするためのコンフィグファイル(prometheus.yaml)を作成します。10秒間隔で Prometheus コンテナ自体の情報を収集するように設定してみます。この yaml ファイルは ConfigMap として読み込みます。
global: scrape_interval: 10s evaluation_interval: 10s scrape_configs: - job_name: 'prometheus' static_configs: - targets: ['localhost:9090']
global に Prometheus が情報を収集する時間間隔を定義し、scrape_configs に実施するジョブを定義しています。Prometheus は指定された間隔でジョブを実行してメトリクスデータを収集してくれます。
Prometheusをデプロイする
ここまで作成できるとファイル構成は以下のようになっています。
base/ ├ prom-deployment.yaml ├ prom-service.yaml └ prometheus.yaml
base ディレクトリ以下に kustomize用のファイル kustomization.yaml を作成します。
resources: - prom-service.yaml - prom-deployment.yaml configMapGenerator: - name: prometheus-config files: - prometheus.yaml
kubectl コマンドを使って Prometheus をデプロイします。
kubectl apply -k base
ブラウザにURLhttp://35.1x9.1x0.XXX:9090/graph
を入力して以下の画面が表示されればデプロイ成功です(35.1x9.1x0.XXXはサービスのIPアドレスです)。
Master/Slave構成のRedisを構築する
監視対象の Redis を Kubernetes 上に構築します。Headless Service を使ったシンプルなマスタースレーブ構成にしています。以前このブログで紹介した Redis Sentinel 構成から Sentinel 部分を取り払った構成になっています。Headless Service の説明もこちらの記事に書いてあります。
redis.confとRedisの起動ファイルを作成する
Redisの設定ファイル redis.conf ファイルを作成します。
bind 0.0.0.0 port 6379 maxclients 50000 dir /redis-data
Redisの起動時に実行されるスクリプトファイル launch.sh を作成します。
#!/bin/bash SERVICE=redis MASTER=${SERVICE}-0 if [ ${HOSTNAME} == ${MASTER} ]; then redis-server /config/redis.conf else redis-server /config/redis.conf --slaveof ${MASTER}.${SERVICE} 6379 fi
StatefulSet の作成
Redis の Pod リソースの設定をするため StatefulSet を作成します。マスター1台、スレーブ2台構成にするのでレプリカ数は3に設定します。
StatefulSetを使うことで redis-0, redis-1, redis-2 という名前の Pod が生成されます。
Serviceの作成
Redis にアクセスするための Service を作成します。clusterIP に None を指定して Headless Service にします。
Headless Service にすることでクラスタ内から Pod名.サービス名
でアクセスすることが可能になります(今回の構成だとredis-0.redisのようになります)。
Redis をデプロイしてみる
以下の Kustomize ファイルを作成してデプロイしてみます。
resources: - redis-service.yaml - redis-ss.yaml configMapGenerator: - name: redis-config files: - launch.sh - redis.conf
kustomize.yaml を base ディレクトリに保存して以下のコマンドを実行します。
kubectl apply -k base
Redis にアクセスしてみる
redis-2 にアクセスして IP アドレスが返ってくるか確認します。
$ kubectl exec redis-2 -c redis \ -- redis-cli -p 26379 sentinel get-master-addr-by-name master 10.0.9.6 6379
Redis Exporterを追加する
ここまでで Prometheus 単体と Redis のマスタ/スレーブ がそれぞれ構築できました。ただこのままでは Prometheus は Redis のメトリクス情報を取得できません。そこで Redis の StatefulSet に Prometheus 用の Exporter コンテナを追加して Prometheus が Redis のメトリクスを取得できるようにします。頑張れば Redis の Exporter を自前で開発することもできますが割と大変なのでオープンソースの Redis Exporter を使います。Redis の Exporter は redis_exporter が有名なのでそちらを使ってみます。
先ほど作成した Redis の StatefulSet のファイル redis-ss.yaml を以下のように修正します。Redis の Pod に Redis Exporter をサイドカーとして配置します。
...省略... containers: - name: redis command: [sh, -c, source /config/launch.sh] image: redis:5-alpine ports: - containerPort: 6379 volumeMounts: - mountPath: /config name: config - mountPath: /redis-data name: data - name: redis-exporter image: oliver006/redis_exporter:latest ports: - containerPort: 9121 ...省略...
Exporter のポートは9121にします。Redis Exporter のコンテナの配置ができたので Prometheus が Exporter アクセスできるように Service にポートの設定を追加します。redis-service.yaml に以下の設定を追加します。
apiVersion: v1 kind: Service metadata: name: redis spec: type: ClusterIP clusterIP: None ports: - port: 6379 name: port-redis - port: 9121 name: port-redis-exporter selector: redis-app: redis
PrometheusからExporterの情報を収集する
ここまでで Redis 側の準備は整いました。あとは Prometheus が Redis Exporter にアクセスしてメトリクスを収集できるように設定するだけです。
Prometheus が Exporter からデータを取得するための設定を prometheus.yaml ファイルに書きます。Redis Exporter には Pod名.サービス名.ネームスペース名.svc:ポート番号
でアクセスすることができるようになります。prometheus.yaml の static_configs の targets を以下のように修正してください。
global: scrape_interval: 10s evaluation_interval: 10s scrape_configs: - job_name: redis_exporter static_configs: - targets: - redis-0.redis.default.svc:9121 - redis-1.redis.default.svc:9121 - redis-2.redis.default.svc:9121
Prometheus に Exporter を認識させる方法は static_configs とサービスディスカバリがありますが、今回は static_configs を使いました。サービスディスカバリの方が実用的ではあるものの RBAC の設定やサービスアカウントの作成が必要になり設定が複雑になるので static_configs にしました。
デプロイして Prometheus の管理画面から Redis の状態を確認する
Kustomize のファイルを以下のように修正して
resources: - redis-service.yaml - redis-ss.yaml - prom-service.yaml - prom-deployment.yaml configMapGenerator: - name: redis-config files: - launch.sh - redis.conf - name: prometheus-config namespace: stats files: - prometheus.yaml
kustomize.yaml を base ディレクトリに保存して以下のコマンドを実行します。
kubectl apply -k base
デプロイが終わったら、ブラウザから Prometheus の管理画面(http://35.1x9.1x0.XXX:9090)にアクセスして Targets 画面に移動します。
以下のように Redis Exporter が認識されて入れば成功です。
試しに Redis の connected clients の情報を取得してみます。テキストボックスに redis_connected_clients
と入力してから(またはドロップダウンから選択) Execute ボタンを押します。
Redis の クライアント接続数が表示されました。取得したデータをグラフで見たい時は Graph タブを押すとグラフをみることができます。
まとめ
Redis のコンテナと一緒に Redis Exporter のコンテナを配置すると Prometheus から Redis のメトリクスを取得することができます。Prometheusの コンフィグ設定は static_config を使うとお手軽です。
サンプルコード
今回のサンプルコードはこちらに置いています。
参考書籍
Prometheus について一番詳しく書かれている書籍です。
アダプタパターンとして Redis Exporter を使った事例が紹介されていました。