【徹底解説】PrometheusをKubernetesにデプロイする方法

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/7e29d85c-e5f5-87cf-0715-e9e056245122.png)

#はじめに
この記事では、Kubernetes上にPrometheusをデプロイする方法を説明していきます。また、Prometheusのマネージドサービスを提供する[Metricfire](https://try.metricfire.com/japan/?utm_source=blog&utm_medium=Qiita&utm_campaign=Japan&utm_content=How%20to%20deploy%20Prometheus%20on%20Kubernetes)上のリモートでの長期ストレージの設定についても解説していきます。このチュートリアルでは1つのノードを持つminikubeクラスタを使用していますが、この手順はどのKubernetesクラスタでも動作するはずです。以下にある、すべての手順を説明したビデオ（英語）をご覧になるか、この記事をご覧ください。

**[無料トライアル](https://www.hostedgraphite.com/accounts/signup-metricfire/?signup=japan&utm_source=blog&utm_medium=Qiita&utm_campaign=Japan&utm_content=How%20to%20deploy%20Prometheus%20on%20Kubernetes)を利用すれば、[MetricFire](https://try.metricfire.com/japan/?utm_source=blog&utm_medium=Qiita&utm_campaign=Japan&utm_content=How%20to%20deploy%20Prometheus%20on%20Kubernetes)の製品にアクセスし、学んだことを簡単に応用することができます。**

###**動画はこちらから**
https://youtu.be/V4ApOm37XCU 


YAMLファイルを使ってリソースを作成していきます。これによって、私たちが行ったことを記録し、変更を加える必要があるときはいつでもファイルを再利用できることを意味します。ファイルのバージョンはここにありますが、あなた自身の詳細を書くためのスペースもあります。

https://github.com/shevyf/prom_on_k8s_howto

ここでは、YAMLファイルに何が含まれているのか、何をしているのかを見ていきますが、Kubernetesがどのように動作するのかについてはあまり深くは触れません。ただ、これからさらに深掘りしていきたいと思ったときの良い出発点になるはずです。これらの YAML ファイルはそれぞれ Kubectl に Kubernetes API サーバーへのリクエストを送信するように指示し、その指示に基づいてリソースを作成します。

#Namespace
Kubernetesのすべてのリソースはnamespaceで起動され、namespaceが指定されていない場合は「デフォルト」のnamespaceが使用されます。モニタリングの設定をより細かく制御できるようにするために、今回は"monitoring "という名前の別のnamespaceを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/1801fc49-da70-6d46-9c8a-c9458d2544a5.png)

これは手動で実行するには非常に簡単なコマンドですが、速度、正確さ、正確な再現性のために、後で代わりにファイルを使用することに固執します。ファイルを見てみると、v1と呼ばれるapiversionに投稿されていることがわかり、namespaceと呼ばれるリソースのようなもので、その名前が”monitoring”です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/a9803b92-8f02-9889-9c82-d059dbbbb206.png)

これを適用するコマンドは

```
kubectl apply -f monitoring-namespace.yaml
```

これを適用すると、利用可能なnamespaceをコマンドで表示することができます。

```
kubectl get namespaces
```

#ConfigMap
次のステップはConfigMapの設定です。KubernetesのConfigMapは、デプロイメント内のすべてのポッドに設定データを提供します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/416931bb-4e3f-0053-fa3d-ed4b9b75db0e.png)

このファイルには apiversionは v1 で表示され、kindはConfigMapになっています。metadataには "prometheus-config" という名前と "monitoring" という名前が表示されています。

その下のデータセクションには、非常にシンプルな prometheus.yml ファイルがあります。個別に見てみると、簡単なインターバル設定が含まれており、アラートやルールの設定は何もなく、スクレイプジョブでPrometheusから自分自身に関するメトリクスを取得するだけです。

また、Metricfireのリモートストレージの詳細も含まれているため、このPrometheusインスタンスが起動して実行されると、リモート書き込み場所へのデータの送信が開始されます。 remote_readとremote_writeの両方にエンドポイントとAPIキーを提供するだけです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/4c6a7532-015b-cc72-a72a-149362d33ab7.png)

configMap自体は何もしませんが、記事の後半でprometheusをデプロイするときに使用できるように、それを適用します。

```
kubectl apply -f prometheus-config.yaml
```

#役割
次に、両方のmonitoring namespaceで、すべてのKubernetesリソースへのアクセス権を付与する役割と、役割を適用するサービスアカウントを設定します。 具体的には、ClusterRoleを設定します。通常の役割では、同じnamespace内のリソースにのみアクセスできます。Prometheusは、提供するすべてのメトリックを取得するために、クラスター全体からノードとポッドにアクセスする必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/a0bb3a60-d0cd-25a7-362e-9efc2f6b4efe.png)

ClusterRoleのルールは、kubernetes APIのグループ（kubectlがこれらのyamlファイルを適用するために使用するのと同じAPI）または非リソースURL（この場合は「/ metrics」）に適用できます。これは、Prometheusメトリックをスクレイピングするためのエンドポイントになります。 各ルールの動詞は、それらのAPIまたはURLで実行できるアクションを決定することになります。

ServiceAccountは、実行中のリソースとポッドに適用できる識別子です。 ServiceAccountが指定されていない場合は、デフォルトのサービスアカウントが適用されるため、namespaceがMonitoringのデフォルトのサービスアカウントを作成します。 つまり、Prometheusはデフォルトでこのサービスアカウントを使用することになります。

最後に、ClusterRoleBindingを適用して、役割をサービスアカウントにバインドします。

これら3つすべてを1つのファイルで作成しています。必要に応じて、これらをデプロイメントにバンドルすることもできます。 わかりやすくするために、それらを別々に保持します。

```
kubectl apply -f prometheus-roles.yml
```

注：これを独自のKubernetesクラスターに適用すると、kubectlによって特定の方法で既に作成されているリソースに対してkubectl applyを使用することのみに関するエラーメッセージがこの時点で表示されることがありますが、コマンドは正常に機能します。

#デプロイメント

すべてを入れるnamespaceがあり、構成があり、クラスターの役割がバインドされたデフォルトのサービスアカウントが設定されましたので、Prometheus自体をデプロイする準備が整いました。

デプロイメントファイルには、セット内のすべてのポッドに適用するPodTemplateを含む、ReplicaSetの詳細が含まれています。 ReplicaSetデータは、ファイルの最初の「spec」セクションに含まれています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/f11477f7-63a1-6247-3cbb-d31203c7b944.png)

replicasは、セット内の必要なレプリカの数です。この例では、1つだけを起動します。

selectorは、R​​eplicaSetが制御しているポッドをどのように認識するかを詳しく示します。これは、あるリソースが別のリソースをターゲットにする一般的な方法です。

strategyは、更新の実行方法です。

templateセクションは、セット内の各ポッドに適用されるポッドテンプレートです。

namespaceは、ReplicaSetによって決定されるため、今回は必要ありません。

上記のセレクタールールに従ってlabelsが必要であり、適用するポッドを見つけるために起動するすべてのサービスで使用されます。

annotationsの値は、Prometheusを設定してエンドポイントをスクレイピングするだけでなく、メトリックのポッドをスクレイピングするときに非常に重要になります。それらはlabelsに変換され、実行前にジョブの値を設定するために使用できます。たとえば、使用する代替ポートやメトリックをフィルターするための値などです。これはすぐには使用しませんが、ポートに9090と注釈を付けたことがわかります。これをさらに下に表示することもできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/ace5f2da-a66f-c03d-0329-55d1f092a19b.png)

テンプレート内の2番目のSpecセクションには、各コンテナの実行方法の仕様が含まれています。これは非常に複雑なので、Prometheusに固有のオプションについてのみ詳しく説明します。

- Imageは、使用されるDockerイメージです。この場合、quay.ioでホストされているprometheusイメージです。

- commandは、コンテナの起動時にコンテナで実行するコマンドです。

- argsは、そのコマンドに渡す引数であり、以下で設定する構成ファイルの場所も含まれます。
- portsは、ポート9090がWebトラフィック用に開かれるように指定する場所です。
- volumeMountsは、外部ボリュームまたはディレクトリがコンテナにマウントされる場所です。ここではnameとmountPathが指定されています-ここでは、起動時にprometheusに渡される引数で指定された場所に構成ボリュームがマウントされていることがわかります。

volimeとその名前はコンテナに対して個別に設定され、ここで2つのvolumeが定義されています。

1つ目はConfigMapです。これはボリュームのタイプと見なされるため、コンテナー内のプロセスで参照できます。 2つ目は、ポッドが存在する限り存在するタイプのストレージであるemptyDirボリュームです。コンテナーを削除してもボリュームは残りますが、ポッド全体が削除されると、このデータは失われます。

理想的には、データをより永続的な場所に保存する必要があります。チュートリアルでは一時ストレージのみを使用していますが、remote_readとremote_writeの詳細を構成したので、Prometheusはオフサイトで受信したすべてのデータをMetricfireに送信します。

ここで、そのデプロイメントファイルを適用します。

```
kubectl apply -f prometheus-deployment.yaml
```

そして、monitoring namespaceのリソースのステータスを見てみましょう。

```
Kubectl get all --namespace=monitoring
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/d9341da4-380a-f66a-9363-9ed6d5a4f7e7.png)

#NodePort
Prometheusでメトリックを確認する前に、やるべきことが1つ残っています。 現在のところ、Prometheusはクラスターで実行されているため、アクセスできません。 NodePortと呼ばれるサービスをセットアップして、ノードのIPアドレスを介してprometheusにアクセスできるようにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/8e692129-d21f-e06a-f870-666eb6f53c35.png)

このファイルは非常にシンプルで、namespace、selectorを記述しているため、正しいポッドと使用するポートに自分自身を適用できます。

```
kubectl apply -f prometheus-nodeservice.yaml
```

これを適用したら、任意のノードのポート30900で実行中のPrometheusを確認できます。 ノードのIPアドレスの取得は、Kubernetesのセットアップごとに異なりますが、幸運なことに、MinikubeにはノードのURLを取得する簡単な方法があります。 以下を使用してすべてのサービスを確認できます。

```
minikube service list
```

または、次のコマンドを使用して、デフォルトのブラウザーでprometheusのURLを直接開くことができます。

```
minikube service --namespace=monitoring prometheus
```

使用可能なメトリックはすべて、構成内の1つのスクレイピングジョブを介してPrometheus自体から取得されます。 「prometheus」という値を持つラベル「job」を検索することで、そのジョブのすべてのメトリックを表示できます

```
{job=”prometheus”}
```

#Node Exporterと新しいConfigMap
次に、クラスターに関するいくつかの有用なメトリックを取得する必要があります。 Node Exporterというアプリケーションを使用してクラスターノードに関するメトリックを取得し、Prometheus configmapを変更してクラスター内のノードとポッドのジョブを含めます。 Kubernetesサービスディスカバリを使用して、これらの新しいジョブのエンドポイントとmetadataを取得します。

ノードエクスポーターは、DaemonSetと呼ばれる特別な種類のReplicaSetを使用してデプロイされます。 ReplicaSetが1つ以上のノードで実行されている任意の数のポッドを制御する場合、DaemonSetはノードごとに1つのポッドを実行します。 ノード監視アプリケーションに最適です。

DaemonSetを作成するためのファイルは、通常のデプロイメント用のファイルとよく似ています。 ただし、DaemonSetによって修正されるため、レプリカの数はありませんが、以前と同様に、アノテーション付きのメタデータやコンテナの仕様を含むPodTemplateがあります。

ただし、Node Exporterのvolumeはかなり異なります。 configmap volumeはありませんが、代わりにノードからのシステムディレクトリがvolumeとしてコンテナにマッピングされていることがわかります。 これが、node exporterがメトリック値にアクセスする方法です。 securityContext設定「privileged：true」により、node exporterにはこれらの値にアクセスする権限があります。

ここでそれを適用してから、DaemonSetが実行されていることを確認します。

```
kubectl apply -f node-exporter-daemonset.yml

kubectl get all --namespace=monitoring
```

新しいconfigMapファイルでは、別の方法でメトリックを取得するため、prometheusジョブはコメント化されています。 代わりに、kubernetes-nodesとkubernetes-podsの2つの新しいジョブが追加されました。

Kubernetes-podsは、Node ExporterやPrometheusを含むクラスター内の各ポッドからメトリックを要求し、kubernetes-nodesはサービスディスカバリを使用してすべてのノードの名前を取得し、Kubernetes自体からそれらに関する情報を要求します。

ノードジョブでは、Kubernetesによって提供された認証情報を使用した安全な接続の詳細が追加されていることがわかります。 いくつかのラベル変更ルールもあります。 これらは、prometheusによって作成された標準ラベルとサービスディスカバリによって提供されるmetadata labelsで構成されるジョブのlabelsetに作用します。 これらのルールは、新しいラベルを作成したり、実行前にジョブ自体の設定を変更したりできます。

この場合、ルールは3つのことを行っています。

- 最初に、ノードに適用されたラベルに基づいてジョブのラベルを作成します。

- 次に、ジョブに使用されるアドレスを、サービスディスカバリによって提供されるアドレスから、ノードメトリックにアクセスするための特定のエンドポイントに変更します。
- 3番目に、メトリックパスを/ metricsから、ノード名を含む特定のAPIパスに変更します。


2番目のジョブでは、ポッドに設定されたannotationにアクセスします。 メトリック用にスクレイピングする必要があるポッドを明確にするために、prometheus.io / scrapeというアノテーションが使用されています。__address__tagとともにannotation prometheus.io/portが各ポッドのスクレイプのために、正しいポートが使用されていることを確実にしてくれます。

configMapの置き換えは、Prometheusの2ステップのプロセスです。 まず、replaceコマンドを使用して、Kubernetesに置換マップを提供します。

```
kubectl replace -f prometheus-config2.yaml
```

configMapは、それを使用しているすべてのコンテナーに適用されます。 ただし、Prometheusは新しい構成を自動的にロードしません。PrometheusUIを見ると、古い構成とジョブが表示されます。-prometheus：30900 / config

新しい構成をロードする最も簡単な方法は、replicasの数を0に減らしてから1に戻すことです。これにより、新しいポッドが作成されます。 これにより既存のデータは失われますが、もちろん、すべてがMetricfireのグラフに送信されます。

構成ページを更新すると、新しいジョブが表示されます。ターゲットページを確認すると、ターゲットとメタデータも表示されます。 メトリックはkubernetes-podsジョブの下にあり、ノードのPrefixが付いています。

Metricfireに切り替えると、ノードエクスポートメトリックのダッシュボードがすでに設定されています。 ダッシュボードを更新すると、これらの新しいメトリックがMetricfireデータソースを介して表示されるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/e2d66d7f-b1f8-1678-87f2-1c2ce5f7dc06.png)


まとめると、次のようになります。

- namespaceを作成しました

- configMapを作成しました
- デフォルトのServiceAccountであるClusterRoleを作成し、それらをバインドしました。
- Prometheusをデプロイしました
- Prometheus UIを公開するノードポートサービスを作成しました
- node-exporterデーモンセットをデプロイしました
- ノードエクスポーターの新しいジョブでconfigMapを更新
- そして、0にスケーリングして1に戻すことで、Prometheusをリロードしました。

この設定に慣れたら、コンテナーを監視するためのcAdvisorのような他のサービスや、Kubernetesの他の部分に関するメトリックを取得するためのジョブを追加できます。 新しいサービスごとに、新しいスクレイプジョブを構成し、configMapを更新して、Prometheusに構成を再ロードするだけです。 簡単です！

この記事の最後として、環境をクリーンアップする方法を説明することで終了します。実はこれ、本当に簡単です。namespaceを削除すると、その中のすべてが削除されます！ 

```
kubectl delete namespace monitoring
```

そして、すべてがなくなったか又はシャットダウンしているか確認してください。

```
kubectl get all --namespace=monitoring
```

しばらくすると、すべてがクリーンアップされているはずです。

さて、[Metricfire](https://try.metricfire.com/japan/?utm_source=blog&utm_medium=Qiita&utm_campaign=Japan&utm_content=How%20to%20deploy%20Prometheus%20on%20Kubernetes)のHosted Prometheusを試す準備はできましたか？ 14日間の[無料トライアル](https://www.hostedgraphite.com/accounts/signup-metricfire/?signup=japan&utm_source=blog&utm_medium=Qiita&utm_campaign=Japan&utm_content=How%20to%20deploy%20Prometheus%20on%20Kubernetes)を開始するか、[デモを予約](https://calendly.com/metricfire-chatwithus/chat?utm_source=blog&utm_medium=Qiita&utm_campaign=Japan&utm_content=How%20to%20deploy%20Prometheus%20on%20Kubernetes)して質問等ございましたら、是非お問い合わせください（日本語可）。

それでは、またの記事で！