zaki work log

作業ログやら生活ログやらなんやら

Prometheus OperatorでデプロイしたPrometheusにカスタムリソースを使ってレコードルール追加してみる

昨日の素のPrometheusでGetting Startedを通して動かしたことで、Node Exporterを使ったメトリクス値の収集と、ルールの追加時のファイル作成・prometheus.ymlへの設定追加を完全にマスターしたので、同じことをPrometheus OperatorでデプロイしたK8s上のPrometheusでやってみる。

参考記事

Operatorを使ってデプロイしたのでカスタムリソースで何とかなるだろうと辺りをつけつつ、かめねこさんのQiitaの記事を再度確認。

qiita.com

大体この辺りの機能で、やりたいことができそう。

  • ConfigReloader

    • PrometheusOperatorでは、単にPrometheusの展開だけではなく、設定の自動再読み込みもサポートしています

  • PrometheusRule

    • PrometheusRuleでは、PrometheusのRuleを設定することができます。

PrometheusRule

かめねこさんの記事の通り、PrometheusRuleというカスタムリソースが作成されている。

[zaki@cloud-dev ~]$ kubectl get prometheusrule -A
NAMESPACE    NAME                   AGE
monitoring   prometheus-k8s-rules   4d21h

kubectl get -o yamlで出力すればわかるけど、spec以下の内容は、Prometheusのrule_filesで読み込まれるルール設定が定義されている。

以下抜粋

spec:
  groups:
  - name: node-exporter.rules
    rules:
    - expr: |
        count without (cpu) (
          count without (mode) (
            node_cpu_seconds_total{job="node-exporter"}
          )
        )
      record: instance:node_num_cpu:sum
    - expr: |
        1 - avg without (cpu, mode) (
          rate(node_cpu_seconds_total{job="node-exporter", mode="idle"}[1m])
        )
      record: instance:node_cpu_utilisation:rate1m

      # ...

なので、このリソースに自分が必要なPrometheusルールの定義を追加してやればOK。

試しに、素のPrometheusをさわったときに作ったサンプルルールを追加してみる。
※ Node Exporterはこの通り標準で動作している。

[zaki@cloud-dev ~]$ kubectl get pod -n monitoring
NAME                                   READY   STATUS    RESTARTS   AGE
alertmanager-main-0                    2/2     Running   0          4d21h
alertmanager-main-1                    2/2     Running   0          4d21h
alertmanager-main-2                    2/2     Running   0          4d21h
grafana-86445dccbb-gx4p7               1/1     Running   0          4d21h
kube-state-metrics-5b67d79459-z4xh6    3/3     Running   0          4d21h
node-exporter-7rq9n                    2/2     Running   0          4d21h
node-exporter-cfxqr                    2/2     Running   0          4d21h
node-exporter-rzsh5                    2/2     Running   0          4d21h
prometheus-adapter-66b855f564-cst25    1/1     Running   0          4d21h
prometheus-k8s-0                       3/3     Running   1          4d21h
prometheus-k8s-1                       3/3     Running   1          4d21h
prometheus-operator-78fcb48ccf-zbx77   2/2     Running   0          4d21h

リソースの末尾に以下を追記

  - name: cpu-node
    rules:
    - record: job_instance_mode:node_cpu_seconds:avg_rate5m
      expr: avg by (job, instance, mode) (rate(node_cpu_seconds_total[5m]))

変更すると、ConfigMapはOperatorによって再作成される。

[zaki@cloud-dev ~]$ kc get cm -n monitoring  prometheus-k8s-rulefiles-0
NAME                         DATA   AGE
prometheus-k8s-rulefiles-0   1      7s

ConfigMapをVolumeMountしているPodは、通常であれば動的にPod内のファイルシステムへ反映されるが、Prometheusのプロセスは動的にファイルの状態を認識しないので本来はリスタートが必要。
ただしここでConfigReloaderの機能が効いてきて、PrometheusのPodを再作成することなく追加したルールが反映される。

f:id:zaki-hmkc:20201015215602p:plain

初期設定

ちなみに、初回デプロイ時から設定する場合は、たぶんこのYAMLに書いておけば良いはず。(未確認)

github.com

(参考) Prometheusの仕組みとPodの定義からみた設定情報

生のPrometheusだと、設定は--config.file=prometheus.ymlで実行時のオプションで指定していた。

Prometheus Operator環境だとどうなっているかと言うと、Podの定義(親リソースはStatefulSet)を見ると

  - args:
    - --web.console.templates=/etc/prometheus/consoles
    - --web.console.libraries=/etc/prometheus/console_libraries
    - --config.file=/etc/prometheus/config_out/prometheus.env.yaml

    [...]

となっており、Pod内の/etc/prometheus/config_out/prometheus.env.yamlにあるファイルの内容のルール関連は以下の通り。

rule_files:
- /etc/prometheus/rules/prometheus-k8s-rulefiles-0/*.yaml

じゃあこの/etc/prometheus/rules/prometheus-k8s-rulefiles-0/*.yamlはどうなってるかと言うと、Podの定義に戻ると、

    volumeMounts:

    # ...

    - mountPath: /etc/prometheus/rules/prometheus-k8s-rulefiles-0
      name: prometheus-k8s-rulefiles-0
  volumes:

  # ...

  - configMap:
      defaultMode: 420
      name: prometheus-k8s-rulefiles-0
    name: prometheus-k8s-rulefiles-0

こうなっていて、ConfigMapの定義をマウントしている。(mountPathはPrometheus本体と、rules-configmap-reloaderの両方にある)

じゃあConfigMapはどうなっているかと言うと、kubectl get configmaps -n monitoring prometheus-k8s-rulefiles-0 -o yamlを見ると、ズラーっとYAMLの定義を見ることができる。
ちなみにこのConfigMapリソース、よくよく見るとPrometheusというカスタムリソースが親リソースとして存在してReconciliation Loopで管理されてるので、直接変更はしないようにする。(というか、kubectl editとか使って変更しても、元に復元される)

  ownerReferences:
  - apiVersion: monitoring.coreos.com/v1
    blockOwnerDeletion: true
    controller: true
    kind: Prometheus
    name: k8s