OpenShift 3.11のPrometheus Operatorを観察する

Red HatでOpenShiftのサポートをしているid:nekopです。OpenShift 全部俺 Advent Calendar 2018 - Qiitaの8日目のエントリです。昨日の以下のエントリの続きです。

rheb.hatenablog.com

OpenShiftのPrometheus Cluster Monitoringのドキュメントをさらっと読むと、以下の注意書きがあったり、Supported ConfigurationsのところにConfiguring OpenShift Container Platform cluster monitoringに書いてあるパラメータによる設定変更しかサポートしないよ、ということが書いてあります。

In order to be able to deliver updates with guaranteed compatibility, configurability of the OpenShift Container Platform Monitoring stack is limited to the explicitly available options.

openshift_cluster_monitoring_operator_alertmanager_configというAlertManagerの設定以外はほぼPVの設定なので、ほとんど何も設定ができない、ということになります。ちょっとびっくりします。

変更するとどうなるのでしょうか。まずはStatefulSetを削除してみましょう。

$ oc get statefulset
NAME                DESIRED   CURRENT   AGE
alertmanager-main   3         3         1h
prometheus-k8s      2         2         1h
$ oc delete statefulset --all
statefulset.apps "alertmanager-main" deleted
statefulset.apps "prometheus-k8s" deleted
$ oc get statefulset
NAME                DESIRED   CURRENT   AGE
alertmanager-main   3         1         3s
prometheus-k8s      2         0         3s

一瞬で復活しました。

他にも変更をやってみましょう。たとえばPrometheusが2 pods, AlertManagerが3 podsでデフォルトHA構成なのですが、シングルノードでテストするときなどにこのpod数は必要ないので、変更してみましょう。

$ oc get statefulset
NAME                DESIRED   CURRENT   AGE
alertmanager-main   3         3         1h
prometheus-k8s      2         2         1h
$ oc scale statefulset --all --replicas=1
statefulset.apps/alertmanager-main scaled
statefulset.apps/prometheus-k8s scaled
$ oc get statefulset
NAME                DESIRED   CURRENT   AGE
alertmanager-main   3         3         1h
prometheus-k8s      1         1         1h

AlertManagerは3 podsのまま、Prometheusは1 podsになりました。この差はなんでしょうか。Operatorをデバッグしてみましょう。prometheus-operatorのソースツリーをさらっと見るとdebugレベルでログがいろいろ出力されるようになっているようなので、オプション指定を調べます。

$ oc rsh deploy/prometheus-operator
$ ps -eaf  | cat
UID        PID  PPID  C STIME TTY          TIME CMD
1000180+     1     0  0 08:26 ?        00:00:00 /usr/bin/operator --kubelet-service=kube-system/kubelet --logtostderr=true --config-reloader-image=registry.redhat.io/openshift3/ose-configmap-reloader:v3.11.16 --prometheus-config-reloader=registry.redhat.io/openshift3/ose-prometheus-config-reloader:v3.11.16 --namespace=openshift-monitoring
1000180+    10     0  0 08:32 ?        00:00:00 /bin/sh
1000180+    25    10  0 08:33 ?        00:00:00 ps -eaf
1000180+    26    10  0 08:33 ?        00:00:00 cat
$ operator --help
(省略)
  -log-level string
        Log level to use. Possible values: all, debug, info, warn, error, none (default "info")

-log-level=debugを指定すれば良さそうです。deploy/prometheus-operatorのargsに指定します。

$ oc edit deploy/prometheus-operator

ログを見ると、StatefulSetの更新は認識しているが、更新する条件に当てはまっていない、というような出力があります。

level=debug ts=2018-12-10T08:24:21.944926624Z caller=operator.go:871 component=prometheusoperator msg="StatefulSet updated"
level=debug ts=2018-12-10T08:24:22.034088665Z caller=operator.go:959 component=prometheusoperator msg="new statefulset generation inputs match current, skipping any actions"

ソースコードを見ると、prometheus-operator-input-hashというannotationの値を比較しています。

https://github.com/coreos/prometheus-operator/blob/v0.26.0/pkg/prometheus/operator.go#L1030-L1034

$ oc get statefulset prometheus-k8s -o yaml | grep prometheus-operator-input-hash
    prometheus-operator-input-hash: "7438763470836378780"

処理がなんとなく意図的であるところまではわかりました。

追記: statefulset/prometheus-k8sはscaling対応していたので、正常な動作でした。

そんなこんなしているうちに、debugログを有効化していたdeploy/prometheus-operatorが再デプロイされました。これもOperatorによる自己修復でしょう。

PrometheusのStatefulSetの元となる情報はCRDのPrometheusというリソースに記述されています。こちらを変更すればStatefulSetも合わせて変更されるでしょうか。Prometheusリソースにreplicasが定義されていたので変更してみましょう。

$ oc scale statefulset prometheus-k8s --replicas=2
$ oc get statefulset
NAME                DESIRED   CURRENT   AGE
alertmanager-main   3         3         6m
prometheus-k8s      2         2         6m
$ oc get prometheus k8s -o yaml
replicas: 2
$ oc edit prometheus k8s # replicas: 1へ変更
$ oc get prometheus -o yaml | grep replica
    replicas: 1
$ oc delete statefulset prometheus-k8s 
statefulset.apps "prometheus-k8s" deleted
$ oc get statefulset
NAME                DESIRED   CURRENT   AGE
alertmanager-main   3         3         6m
prometheus-k8s      1         0         5s

replicaが1になりました。

5分待ってもう一度実行するとどうでしょうか。

$ oc get prometheus -o yaml | grep replica
    replicas: 2
$ oc get statefulset
NAME                DESIRED   CURRENT   AGE
alertmanager-main   3         3         10m
prometheus-k8s      2         2         3m

インストール時のあるべき状態に自己修復されていました。

CRDを変更したのに元に戻ったということはさらに元となる定義がどこかにある、ということになります。

あまり長くなるのもアレなので答えを書きますが、以下のファイルが修復元の定義です。

このassetsファイルの中身はbindata.goというコードに変換されていて、CMOはこの定義を利用しています。

というわけでOperatorでは意図しない変更は基本的にすべて自己修復される、という動作をすることがわかりました。

* 各記事は著者の見解によるものでありその所属組織を代表する公式なものではありません。その内容については非公式見解を含みます。