おうちk8sにPrometheus/Grafanaを導入してNature Remoの可視化をする
前回おうちk8sにKubernetes Dashboardを導入しました
今回はPrometheus/Grafanaの導入に加え、自宅に設置しているNature Remoのセンサーを利用して部屋の室温や湿度などを可視化してみたいと思います
🆙 2020/06/26 更新 master環境にもnode-exporterをデプロイするようvalues.yamlの差分を更新しました
🆙 2020/03/17 更新
データ永続化のためにNFSのPV/PVCを利用するよう修正しました
事前準備
namespace
PrometheusとGrafanaをデプロイするnamespaceは何でも良いですが、今回はすべてmonitoring
というnamespaceを作ってそこにデプロイしていきます
$ kubectl create ns monitoring
kubensなどを使って作成したnamespaceに切り替えておいてください
Helm
PrometheusとGrafanaについてはHelmを使って入れてみます
まずはHelmのインストールから(Macでの動作を想定)
$ brew install helm # 確認 $ helm version version.BuildInfo{Version:"v3.1.0", GitCommit:"b29d20baf09943e134c2fa5e1e1cab3bf93315fa", GitTreeState:"clean", GoVersion:"go1.13.8"}
Prometheus/Grafanaのインストールのために公式のチャートリポジトリを追加します
$ helm repo add stable https://kubernetes-charts.storage.googleapis.com/
追加されたことを確認しておきます
$ helm search repo stable NAME CHART VERSION APP VERSION DESCRIPTION stable/acs-engine-autoscaler 2.2.2 2.1.1 DEPRECATED Scales worker nodes within agent pools stable/aerospike 0.3.2 v4.5.0.5 A Helm chart for Aerospike in Kubernetes stable/airflow 6.1.1 1.10.4 Airflow is a platform to programmatically autho... stable/ambassador 5.3.1 0.86.1 A Helm chart for Datawire Ambassador # ...
あとは対象のチャート名を指定してhelm installでインストール可能ですが、設定ファイルを修正して利用したいので、デフォルトの設定ファイルを取得します
# prometheus $ helm show values stable/prometheus > prometheus-values.yaml # grafana $ helm show values stable/grafana > grafana-values.yaml
Prometheus
Prometheusについては修正箇所がいくつかあります
kube-state-metrics
デフォルトの設定だと、kube-state-metricsのイメージにarmベースのものが用意されていないため、ラズパイ上で動かすことができません
そこで以前書いた、Github Actionsでの複数アーキテクチャ向けのイメージ作成の方法を使ってラズパイ(arm)向けのイメージを作成しました
上記の方法で作ってもらってもOKですが、現時点で最新版(v1.9.5)イメージを作ってあるのでそれを使ってもらっても構いません
作ったイメージは コチラ
PV/PVC
helmでPrometheusをインストールする際に、prometheus-serverとprometheus-alertmanagerにはPersistentVolume/PersistentVolumeClaimが必要になります
マネージドサービスでは動的に作ってくれる設定などもありますが、もちろんラズパイ上に立てたk8sにはそんな機能はありません
PV/PVCを使わずemptyDirを利用するように変更もできますが、Podが再起動した際にデータが消えてしまうので、事前にPV/PVCを作っておきましょう
PersistentVolumeはNFSを利用しますがmasterをNFSサーバとして利用する記事は以下で書いてるので、NFSサーバ/クライアントの設定を事前に行ってください
おうちk8sのmasterサーバにログインし、PVに利用するディレクトリを作っておきます
# masterサーバ上で $ sudo mkdir -p /mnt/share/nfs/prometheus/{alertmanager,server} # 各プロセスをNonRootで動かすため作成したディレクトリの所有権も変えておく $ sudo chown $USER /mnt/share/nfs/prometheus
準備ができたのでPV/PVCを作ります(今回はそれぞれ1GiBを利用する設定)
nfs-pv.yaml
kind: PersistentVolume apiVersion: v1 metadata: name: prometheus-alertmanager spec: capacity: storage: 1Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Recycle storageClassName: alertmanager nfs: server: raspberrypi-master.local path: /mnt/share/nfs/prometheus/alertmanager --- kind: PersistentVolume apiVersion: v1 metadata: name: prometheus-server spec: capacity: storage: 1Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Recycle storageClassName: prometheus-server nfs: server: raspberrypi-master.local path: /mnt/share/nfs/prometheus/server
nfs-pvc.yaml
kind: PersistentVolumeClaim apiVersion: v1 metadata: name: prometheus-alertmanager spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: alertmanager --- kind: PersistentVolumeClaim apiVersion: v1 metadata: name: prometheus-server spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: prometheus-server
デプロイします🚀
$ kubectl apply -f nfs-pv.yaml -f nfs-pvc.yaml -n monitoring
values.yaml
今までの変更点をprometheus-values.yaml
にも反映させます
変更差分は以下の通り
@@ -180,7 +180,7 @@ ## alertmanager data Persistent Volume existing claim name ## Requires alertmanager.persistentVolume.enabled: true ## If defined, PVC must be created manually before volume will be bound - existingClaim: "" + existingClaim: "prometheus-alertmanager" ## alertmanager data Persistent Volume mount root path ## @@ -188,7 +188,7 @@ ## alertmanager data Persistent Volume size ## - size: 2Gi + size: 1Gi ## alertmanager data Persistent Volume Storage Class ## If defined, storageClassName: <storageClass> @@ -276,10 +276,10 @@ ## Security context to be added to alertmanager pods ## securityContext: - runAsUser: 65534 + runAsUser: 1001 runAsNonRoot: true - runAsGroup: 65534 - fsGroup: 65534 + runAsGroup: 1001 + fsGroup: 1001 service: annotations: {} @@ -396,7 +396,7 @@ ## kube-state-metrics container image ## image: - repository: quay.io/coreos/kube-state-metrics + repository: sminamot/kube-state-metrics tag: v1.9.5 pullPolicy: IfNotPresent @@ -511,7 +511,7 @@ ## image: repository: prom/node-exporter - tag: v0.18.1 + tag: v1.0.0-rc.0 pullPolicy: IfNotPresent ## Specify if a Pod Security Policy for node-exporter must be created @@ -559,7 +559,8 @@ ## Node tolerations for node-exporter scheduling to nodes with taints ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ ## - tolerations: [] + tolerations: + - operator: "Exists" # - key: "key" # operator: "Equal|Exists" # value: "value" @@ -836,7 +837,7 @@ ## Prometheus server data Persistent Volume existing claim name ## Requires server.persistentVolume.enabled: true ## If defined, PVC must be created manually before volume will be bound - existingClaim: "" + existingClaim: "prometheus-server" ## Prometheus server data Persistent Volume mount root path ## @@ -844,7 +845,7 @@ ## Prometheus server data Persistent Volume size ## - size: 8Gi + size: 1Gi ## Prometheus server data Persistent Volume Storage Class ## If defined, storageClassName: <storageClass> @@ -953,10 +954,10 @@ ## Security context to be added to server pods ## securityContext: - runAsUser: 65534 + runAsUser: 1001 runAsNonRoot: true - runAsGroup: 65534 - fsGroup: 65534 + runAsGroup: 1001 + fsGroup: 1001 service: annotations: {} @@ -972,7 +973,7 @@ loadBalancerSourceRanges: [] servicePort: 80 sessionAffinity: None - type: ClusterIP + type: NodePort ## Enable gRPC port on service to allow auto discovery with thanos-querier gRPC:
- runAsUser/runAsGroup/fsGroup についてはnodeサーバの所有権を変えたユーザのuid/gidを設定します
- 自分の環境でのアカウントは
1001
でした
- 自分の環境でのアカウントは
cat /etc/passwd | grep $USER sminamot:x:1001:1001::/home/sminamot:/bin/bash
node-exporterのイメージはラズパイのCPU温度などを取得できるよう、latestでもある
v0.18.1
ではなく、v1.0.0-rc.0
を使ってますmaster nodeの環境の情報も取得できるようnode-exporterをmasterにも入れます
- nodeExporter.tolerationsの設定を変えてdaemonsetがmasterにも配置されるようにしています
Grafana
GrafanaについてもPV/PVCを作成します
Prometheus同様、おうちk8sのmasterサーバにログインし、PVに利用するディレクトリを作っておきます
# masterサーバ上で $ sudo mkdir -p /mnt/share/nfs/grafana
PV/PVCを作ります
nfs-pv.yaml
kind: PersistentVolume apiVersion: v1 metadata: name: grafana spec: capacity: storage: 1Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: grafana nfs: server: raspberrypi-master.local path: /mnt/share/nfs/grafana
nfs-pvc.yaml
kind: PersistentVolumeClaim apiVersion: v1 metadata: name: grafana spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: grafana
デプロイします🚀
$ kubectl apply -f nfs-pv.yaml -f nfs-pvc.yaml -n monitoring
grafana-values.yaml
を修正します
@@ -111,7 +111,7 @@ ## ref: http://kubernetes.io/docs/user-guide/services/ ## service: - type: ClusterIP + type: NodePort port: 80 targetPort: 3000 # targetPort: 4181 To be used with a proxy extraContainer @@ -186,16 +186,16 @@ ## persistence: type: pvc - enabled: false + enabled: true # storageClassName: default accessModes: - ReadWriteOnce - size: 10Gi + size: 1Gi # annotations: {} finalizers: - kubernetes.io/pvc-protection # subPath: "" - # existingClaim: + existingClaim: "grafana" initChownData: ## If false, data ownership will not be reset at startup
デプロイ
ここまででPrometheus/Grafanaのデプロイ準備が完了したのでデプロイしちゃいましょう🚀
$ helm install prometheus stable/prometheus -f prometheus-values.yaml --namespace monitoring $ helm install grafana stable/grafana -f grafana-values.yaml --namespace monitoring # 更新時は helm upgrade
各種リソースが正常にデプロイされていればOKです
$ kubectl get all -n monitoring
それぞれWebUIでも表示できるか見てみましょう
# Prometheus $ open http://$(kubectl get nodes --namespace monitoring -o jsonpath="{.items[0].status.addresses[0].address}"):$(kubectl get --namespace monitoring -o jsonpath="{.spec.ports[0].nodePort}" services prometheus-server) # Grafana $ open http://$(kubectl get nodes --namespace monitoring -o jsonpath="{.items[0].status.addresses[0].address}"):$(kubectl get --namespace monitoring -o jsonpath="{.spec.ports[0].nodePort}" services grafana)
Grafanaにはログインが必要で、usernameはadmin
、passwordは以下コマンドで確認可能です
$ kubectl get secret --namespace monitoring grafana -o jsonpath="{.data.admin-password}" | base64 -D
ログインできればOK
🎉🎉🎉🎉🎉
Grafanaのカスタマイズ
せっかくPrometheus/Grafanaのインストールができたので、Grafanaでなにかダッシュボードを作ってみます
ブラウザでGrafanaを開きログインしたら、Create a data source
を選択します(画像はすでに追加したあとなので、初回はもしかしたらAdd data source
かも)
"Prometheus" を選択
Settings -> HTTP -> URLにhttp://prometheus-server
と入力
Dashboardsの3つとも"Import"する
Settings から「Save & Test」を押し、正常に設定ができればOK
Dashboards -> Manageから取り込んだ3つのDashboardsが取り込まれればOK
試しに「Prometheus 2.0 Stats」など見てみるとそれっぽいものが表示されるはずです 👍
その他のダッシュボードは Grafana Labs にいろんなダッシュボードが共有されてて、IDを入力するだけでダッシュボードの作成が可能です
ちなみに自分は このダッシュボード を入れてみました
Nature Remoの可視化
やっと本題のNature Remoの可視化です(遅ぇ)
Nature Remo API用のアクセストークン取得
Nature Remo Cloud API のリクエストにはアクセストークンが必要になります
ここのページ からアクセストークンの生成ができるので、値を控えておきます
exporterのk8sへのデプロイ
PrometheusとGrafanaはmonitoring
ネームスペースにデプロイしてましたが、Nature Remo用のexporterはremo
ネームスペースを作ってそこにデプロイしたいと思います
$ kubectl create ns remo
Nature Remo用のexporterを作っている方がいたので使わせてもらいます
↑のリポジトリにはPrometheus/Grafanaのyamlも用意されていますが、先ほど作って不要なため、Nature Remoのexporterのyamlだけ拝借します
使うのはremo-exporter-dep.yaml
とremo-exporter-svc.yaml
ですが、apiVersionの書き方が古かったり、NodePortになってたり(クラスタ内でリクエストできれば良いのでClusterIPでよい)するので、修正を加えたものが以下になります
deployment.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: remo-exporter spec: replicas: 1 selector: matchLabels: app: remo-exporter template: metadata: labels: app: remo-exporter spec: containers: - name: remo-exporter image: kenfdev/remo-exporter:latest ports: - containerPort: 9352 protocol: TCP env: - name: OAUTH_TOKEN_FILE value: '/etc/secrets/api-keys' volumeMounts: - name: api-keys-volume readOnly: true mountPath: '/etc/secrets' volumes: - name: api-keys-volume secret: secretName: api-keys
service.yaml
apiVersion: v1 kind: Service metadata: name: remo-exporter labels: app: remo-exporter spec: type: ClusterIP ports: - port: 9352 protocol: TCP targetPort: 9352 selector: app: remo-exporter
先ほど取得したアクセストークンはsecret/api-keys
に記載しておきます
前回のKubernetes Dashboard と同様、kustomizeを使ってデプロイしましょう
kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: remo resources: - deployment.yaml - service.yaml secretGenerator: - name: api-keys files: - secret/api-keys
いざデプロイ🚀
$ kubectl apply -k .
デプロイができたらexporterから値が取得できるか確認しておきます
$ kubectl run -it --rm alpine --image alpine --restart=Never / # apk update && apk add curl / # curl http://remo-exporter.remo:9352/metrics # HELP go_gc_duration_seconds A summary of the GC invocation durations. # TYPE go_gc_duration_seconds summary go_gc_duration_seconds{quantile="0"} 8.3553e-05 go_gc_duration_seconds{quantile="0.25"} 0.000161035 # ...
正しく取得できてそうです 🎉
Grafanaの設定
exporterもデプロイできたのであとはGrafanaの設定をするだけです
Grafanaの設定はmonitoring
ネームスペースなので戻しておきましょう
独自のscrapeを追加するためにextraScrapeConfigs
の設定を加えます
grafana-values.yaml
のextraScrapeConfigs
に追記してもいいですが、今回は別ファイルで定義して利用してみます
extraScrapeConfigs.yaml
- job_name: 'nature-remo' dns_sd_configs: - names: ['remo-exporter.remo'] port: 9352 type: A refresh_interval: 5s
デプロイします🚀
$ helm upgrade prometheus stable/prometheus -f grafana-values.yaml --set-file extraScrapeConfigs=extraScrapeConfigs.yaml --namespace monitoring
あとはGrafanaのUIからポチポチグラフを追加していくと…
🎉🎉🎉🎉🎉
ダッシュボードのyamlは以下に置いておくので参考にどうぞ ✋
https://github.com/sminamot/raspi-k8s-monitoring/blob/master/grafana/remo/dashboard/grafana.json
まとめ
おうちk8sにPrometheus/Grafanaの導入と、GrafanaへNature Remoを可視化するダッシュボードを追加しました
最近Helmを少し触ってますが、公式のチャート使うと簡単にデプロイできるのでいいですね
あとHelmが2から3にアップデートされてから構成がシンプルになって扱いやすくなりました(まだ2の情報が多いので公式ドキュメント読むのが良さそう、2と3で公式のドキュメントがちゃんと別れてるのが良い)
今回作ったもの
以下に置いておきます