こんにちは、もーすけです。
本日は、OpenShift 4.6から新規に追加された「ユーザ定義プロジェクトの監視機能 (Monitoring for user-defined project)」ってなんなのか?どこまでできるのか?と気になってので検証してみます。正式な機能名があるわけではなさそうなので、本ブログでは「ユーザ定義プロジェクトの監視」ということにしておきます。
ちなみに本ブログを読みすすめる上で、$ コマンド
はクラスタ管理者の操作、% コマンド
はユーザ(開発者)の操作として記述しているので注意してください。
Cluster Monitoringとは
OpenShiftは、インストール時点にデフォルトでCluster MonitoringというPrometheusやGrafanaで構成された機能が起動します。実態としては、Cluster Monitoring Operator というOperatorがインストールされており、OpenShiftクラスタを監視するのに必要な、以下のようなソフトウェアを起動しています。
- Prometheus Operator
- Prometheus
- Alertmanager cluster for cluster and application level alerting
- kube-state-metrics
- node_exporter
- prometheus-adapter
4.5以前では、このCluster Monitoringは名前の通り「クラスタのためのモニタリング」機能の提供であり、OpenShift上でアプリケーションを動かすユーザ側の監視はスコープ外でした。 4.6にて、ユーザ定義プロジェクトの監視機能が追加されたことで、ユーザ側の監視もできるようになったというわけです。(リリースノートはこちら)
OpenShiftを触っている人は、「Cluster Monitoringでもユーザ定義プロジェクトの監視できるのでは!?」と思うはずなので、現時点の状況を説明します。 従来のCluster Monitoringでも、たしかにユーザが作ったプロジェクト内のPodのメトリクスなどを確認することはできます。しかし、いくつかの課題がありました。
ひとつめは、Cluster Monitoringに搭載のPrometheus/Grafanaには権限分離する機能がなく、Cluster Monitoringにアクセスできる人は、すべてのNamespaceの状況が見えてしまいます。 ひとつのシステムのためだけにOpenShiftを利用していれば問題ないかもしれませんが、マルチテナントとして利用する場合は不適切です。
ふたつめは、カスタマイズができないということです。OpenShiftのプリセットの設定が入っており、こちらを編集してカスタマイズすることができないということです。そのため、ユーザがデプロイしたアプリケーションの監視設定・アラート設定を追加することはできません。
という背景があり、この新機能の「ユーザ定義プロジェクトの監視」に注目していたというわけです! どのくらい現時点で使えるのか?制限事項は何なのか?そのあたりを確認していきたいと思います。
設定と検証
本ブログの検証で利用しているOpenShiftはversion 4.6.20
となります
$ oc version
Client Version: 4.6.18
Server Version: 4.6.20
Kubernetes Version: v1.19.0+2f3101c
ユーザー定義プロジェクトの監視の有効化
デフォルトでは無効化されているため、有効化が必要です。
有効化の公式ドキュメントの手順はこちらです。
ちなみに、この有効化作業はクラスタ管理者の作業です。cluster-admin権限がないとできない操作で、ユーザ(開発者側)はこの作業について気にする必要はないです。
また、このユーザ定義プロジェクトの監視もCluster Monitoring Operatorの拡張機能として備わっているものになります。
公式ドキュメントの手順にしたがって行うのですが、デフォルトの設定のままだとしょっぱなからつまづきます。cluster-monitoring-config
というConfigMapはデフォルトで存在しないため、ない人は作成する必要があります。
$ oc -n openshift-monitoring edit configmap cluster-monitoring-config
Error from server (NotFound): configmaps "cluster-monitoring-config" not found
気を取り直して設定を追加します。
$ oc -n openshift-monitoring create configmap cluster-monitoring-config
configmap/cluster-monitoring-config created
$ oc -n openshift-monitoring edit configmap cluster-monitoring-config
# 以下を追加
data:
config.yaml: |
enableUserWorkload: true
openshift-user-workload-monitoring
namespaceにて、ユーザ定義プロジェクトの監視向けのPrometheusが作成されていることを確認できます。
$ oc get pod -n openshift-user-workload-monitoring
NAME READY STATUS RESTARTS AGE
prometheus-operator-6957669954-qq82t 2/2 Running 0 100s
prometheus-user-workload-0 4/4 Running 1 95s
prometheus-user-workload-1 4/4 Running 1 95s
thanos-ruler-user-workload-0 3/3 Running 0 93s
thanos-ruler-user-workload-1 3/3 Running 0 93s
$ oc get prometheus -n openshift-user-workload-monitoring
NAME VERSION REPLICAS AGE
user-workload v2.20.0 2 2m22s
ユーザへの権限付与
この機能をユーザに利用してもらうためには、ユーザ側への権限付与が必要です。
具体例でいうと、ユーザが監視設定を追加するためには ServiceMonitor
や PromtheusRule
といったリソースの作成が必要です。OpenShiftでは、いくつかのRoleを用意しているので、適切なものをユーザに付与しましょう。詳しくはこちらのドキュメントを参照ください。
監視設定もユーザ側で操作することが多いかと思うので、monitoring-edit
の利用頻度が高そうですね。
本ブログではuser1
をユーザ(開発サイド)とみなして権限付与をしてみます。
my-app
は、user1が利用しているnamespace名です。
$ oc policy add-role-to-user monitoring-edit user1 -n my-app
clusterrole.rbac.authorization.k8s.io/monitoring-edit added: "user1"
Prometheus Operatorとの関係
さきにお伝えしておくと、これからでてくるServiceMonitor
やPrometheusRule
といったリソースはPrometheus Operatorのカスタムリソースです。
Prometheus Operatorであることをユーザ側にあまり意識させない作りにはなっていますが、ユーザ側はPrometheus Operatorを一度さわっておくといいでしょう。
本記事では、Prometheus Operatorについては解説しませんが、別記事でまた紹介していきたいと思います。
アプリケーションのデプロイ
ここからはユーザ側の作業になります。 ユーザは任意のアプリケーションをデプロイしますが、そのアプリケーションはPrometheus形式のメトリクスを出力できる必要があります。 Prometheusのメトリクスを出力する方法にPrometheus exporterを用いることができます。
Prometheus exporterとは、簡易なHTTPサーバで、HTTPのリクエストがきたときにPrometheus形式のメトリクスを出力するツールです。オープンソースで、さまざまな種類のexporterがすでに開発されています。Kubernetesの世界で言えば、ノードのメトリクスを監視するためにnode exporterはよく使われます。実際、OpenShift内でも利用されています。その他、Nginx exporterやJMX exporterなどさまざまです。
本検証では、Nginx exporterを搭載したNginxを使って挙動を確認してみます。
ドキュメント通りではつまらないので、ここは違うアプローチで解説していきたいと思います。
つぎのマニフェスト(nginx.yaml
)を用います。コメントをいれました。
---
# NginxのDeployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-nginx
spec:
replicas: 3
selector:
matchLabels:
app: test-nginx
template:
metadata:
labels:
app: test-nginx
spec:
containers:
# Nginx本体
- name: nginx
image: nginxinc/nginx-unprivileged:1.20.0
ports:
- containerPort: 8080
volumeMounts:
- name: config-volume
mountPath: /etc/nginx/conf.d
# Nginx exporter
# 9113ポートでリッスンし、Nginx本体の/stub_statusの情報をみて
# Prometheus形式のメトリクスを出力する
- name: nginx-exporter
image: nginx/nginx-prometheus-exporter:0.9.0
ports:
- containerPort: 9113
args:
- -nginx.scrape-uri=http://localhost:8080/stub_status
volumes:
- name: config-volume
configMap:
name: nginx-conf
items:
- key: default.conf
path: default.conf
---
# Nginx本体のService
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
type: ClusterIP
ports:
- name: "http-port"
protocol: "TCP"
port: 8080
targetPort: 8080
selector:
app: test-nginx
---
# Nginx exporterのService
apiVersion: v1
kind: Service
metadata:
name: nginx-exporter-service
labels:
app: test-nginx
spec:
type: ClusterIP
ports:
- name: "exporter"
protocol: "TCP"
port: 9113
targetPort: 9113
selector:
app: test-nginx
---
# Nginxのコンフィグ
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-conf
data:
default.conf: |
server {
listen 8080;
root /usr/share/nginx/html;
location /stub_status {
stub_status;
}
}
Nginxを起動します。
ポイントとしては、Pod内に2つのコンテナが存在していること、そしてexporter用のService(nginx-exporter-service
)をあわせて作成したことです。
% oc apply -f nginx.yaml
deployment.apps/test-nginx created
service/nginx-service created
service/nginx-exporter-service created
configmap/nginx-conf created
% oc get pod,service,configmap
NAME READY STATUS RESTARTS AGE
pod/test-nginx-6c46668b79-6d8b8 2/2 Running 0 8s
pod/test-nginx-6c46668b79-fhc44 2/2 Running 0 8s
pod/test-nginx-6c46668b79-r4wzn 2/2 Running 0 8s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/nginx-exporter-service ClusterIP 172.30.255.65 <none> 9113/TCP 7s
service/nginx-service ClusterIP 172.30.151.21 <none> 8080/TCP 7s
NAME DATA AGE
configmap/nginx-conf 1 6s
メトリクスの収集
これから、exporterが公開したメトリクスを収集しますが、その前に生のメトリクス情報を確認しておきましょう。
fedora:33
イメージでデバッグ用のコンテナを起動します。
コンテナ内から、service/nginx-exporter-service
に接続してメトリクス情報を肉眼でも確認しておきましょう。
// デバッグ用コンテナの起動
% oc run debug -it --image=fedora:33 -- /bin/bash
If you don't see a command prompt, try pressing enter.
bash-5.0$
bash-5.0$ # まずはNginx本体へcurlしてレスポンスが返ってくることを確認
bash-5.0$ curl http://nginx-service:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
...
bash-5.0$ # 次にexporter側へcurlしてメトリクスを確認
bash-5.0$ curl http://nginx-exporter-service:9113/metrics
# HELP nginx_connections_accepted Accepted client connections
# TYPE nginx_connections_accepted counter
nginx_connections_accepted 3
# HELP nginx_connections_active Active client connections
# TYPE nginx_connections_active gauge
nginx_connections_active 1
# HELP nginx_connections_handled Handled client connections
# TYPE nginx_connections_handled counter
nginx_connections_handled 3
...
いよいよ、メトリクス収集するために、Prometheusに対して監視設定を投入します。
通常のPrometheusを利用している場合、Prometheusの監視設定は専用の設定ファイルに記述を行い読み込ませる必要があります(公式ドキュメント)。今回は、Prometheus Operatorを内部的に利用しているため、Prometheusの専用の設定ファイルを書く必要はなく、ServiceMonitor
というKubernetesリソースを作成すると、Prometheus Operatorが設定をPrometheusに反映してくれます。
非常にシンプルですが、指定した条件に合うServiceを検出し監視を開始してくれます。
ServiceMonitor
の設定内容について詳しく知りたい方は、Prometheus OperatorのAPIドキュメントがオススメです。
# servicemonitor.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: nginx-monitor
spec:
# メトリクスのエンドポイントの設定
# "exporter"という名前のService portを選択
endpoints:
- interval: 30s
port: exporter
scheme: http
# 検出するServiceの条件設定
# "app: test-nignx"のラベルを持つServiceを検出
selector:
matchLabels:
app: test-nginx
ServiceMonitorをデプロイ後に、OpenShiftのWebコンソールから、“Monitoring” -> “Metrics” -> “Custom Query"にて、nginx
などと入力するとNginx exporterから取得したメトリクスを確認できます。
% oc apply -f servicemonitor.yaml
servicemonitor.monitoring.coreos.com/nginx-monitor created
% oc get servicemonitor
NAME AGE
nginx-monitor 9s
アラート設定
続いてアラート設定です。
取得したメトリクスに対して条件を指定してアラートできます。
アラート設定はPrometheusRule
というリソースで設定できます。
PrometheusRule
の設定項目はこちらを参照ください。
試しに、次のマニフェストを使ってみます。
nginx_up
は、名前のとりNginxが起動しているかどうかのメトリクスです。
今回、Nginxはレプリカを3で起動していますから、何もなければsum(nginx_up) = 3
となるはずです。
ひとつ以上がダウンしていれば NginxPartiallyDown
のアラートを、全部ダウンしていれば NginxTotallyDown
のアラートを出すこととします。
# alert.yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: nginx-alert
spec:
groups:
- name: nginx-down
rules:
- alert: NginxPartiallyDown
expr: sum(nginx_up) < 3
for: 0m
labels:
severity: warning
- alert: NginxTotallyDown
expr: sum(nginx_up) < 1
for: 0m
labels:
severity: critical
アラート設定をデプロイし、Webコンソールにアラートが反映したことを確認。
% oc apply -f alert.yaml
prometheusrule.monitoring.coreos.com/nginx-alert created
% oc get prometheusrole
NAME AGE
nginx-alert 6h12m
Nginxのレプリカ数を2にして、わざとアラート発報させてみます。
Webコンソール上でもアラートがFiring
になっていることを確認しましょう。
% oc scale deploy test-nginx --replicas=2
deployment.apps/test-nginx scaled
通知設定
最後に通知設定についてみていきます。
ひとつまえの項目ではアラート設定を行いましたが、とくに通知の設定は行っていませんでした。
Prometheusでは Alertmanager
というコンポーネントがアラートを管理します。
このユーザ定義プロジェクトの監視では、アラート設定はユーザ側に権限はなくクラスタ管理者側となります。
理由は、利用しているAlertManagerは、クラスタ管理用のものと併用しているためです。
(※OpenShift 4.11からアラート機能は改善され、開発者側もセルフで設定できるようになりました。詳しくは「OpenShift、開発者向けの監視機能(アラート通知)が進化しました」を確認してください!)
OpenShiftのWebコンソールの"Administration” -> “Cluster Settings” -> “Global Configuration” -> “Alertmanager” -> “Create Receiver"から設定できます。公式ドキュメントの設定手順はこちらです。
今回はSlackを通知先に選びました。
設定で重要になるのは、Routing Labels
です。
これは、発報したアラートと通知設定を紐付けるための設定です。いちばん簡易なのはNamespaceを指定することでしょう。
以下のスクリーンショットのように namespace = my-app
とすることで、my-app namespace内で作成されたPrometheusRule
と紐づきNamespace毎に通知先を選べます。複数のチームがOpenShiftを利用していても通知先をある程度固定できます。
ただし、Namespaceごとではクラスタ管理者の管理も難しいので、チームごとに利用できるよう team = <任意のID>
としてIDをチーム側に知らせることなど運用の工夫が考えられそうです。
Routing Labels
に使用できるラベルは、PrometheusRule
を記述したときに設定したlabels
と対応します。以下であれば、severity=warning
, type=hoge
, foo=bar
のラベルと、namespace=xxxx
が付きます。
# alert.yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: nginx-alert
spec:
groups:
- name: nginx-down
rules:
- alert: NginxPartiallyDown
expr: sum(nginx_up) < 3
for: 0m
labels:
severity: warning
type: hoge
foo: bar
アーキテクチャ図
ここまでいろいろ検証してきて、ドキュメントに記載してあったアーキテクチャ図が理解できるようになってきました。 簡単ですが、ポイントを書き込んだので理解の深堀りに使ってください。
さいごに
長いブログでしたがお疲れさまでした。
OpenShiftのCluster Monitoringの拡張機能を使ったユーザ定義プロジェクトの監視いかがでしたでしょうか。
個人的には非常に良い仕組みだなと思っています。
いままで、ユーザ側で監視のの仕組みを作るのにPrometheus Operator/Grafana Operatorを使って独自に立ててきました。
Operator化されているので簡単ではあるのですが、それでもある程度の運用の大変さがあったのは事実です。
もちろん、いくつかの制約はあるもののカスタムのメトリクスの収集とアラート・通知ができるので使える場面も多いのではないかなと思っています。
以下の点が制約として考えられるので注意して使っていきましょう。
- ダッシュボードは作れない。Grafanaダッシュボードは含まない。OpenShiftのWebコンソール内で完結。
アラートの通知先管理がクラスタ管理側権限となる。(OpenShift 4.11で改善)- 大量のユーザで利用したときのスケーラビリティ(OpenShift 4.11でクラスタ監視とアプリケーション監視のAlertmanagerを分離できるように改善)
では、これからもOpenShift Lifeを楽しんでください!
本編の続報です。