はじめに
#5では、研究室サーバーの監視基盤としてPrometheus、Grafana、Alertmanagerを導入しました。この基盤で半年ほど問題なく運用できており、現在Grafanaダッシュボードは研究室の他のメンバーにも利用されています。
当時は引き継ぎやバージョンアップのコストを考慮して、各コンポーネントをバイナリインストール(Linuxサービス起動)ではなく、Dockerコンテナとして起動する意思決定を行いました。しかし、この方法でも依然として手動でのバージョンアップが必要であり、決してメンテナンス性が高いとは言えません。
一方、#14では研究室サーバーでオンプレミスのKuberentesクラスタを構築しました。本記事では、Prometheus Operatorなどを利用したKubernetesネイティブな監視基盤に移行する方法とそのメリットを紹介します。
1. Prometheus Operatorとは
Prometheus Operatorを利用することで、PrometheusやAlertmanagerなどをKubernetesネイティブなOperator patternでデプロイ・管理することができます。
目的として「KubernetesクラスタにおけるPrometheusベースの監視スタックの設定を簡素化し、自動化すること」を掲げていて、主に以下の3つの機能を提供しています。
- カスタムリソースの提供
- シンプルなデプロイ設定
- Prometheusターゲット設定
1つ目について、デプロイされるPrometheus
やAlertmanager
だけでなく、(prometheus.yaml
で指定されるような)Probe
やScrapeConfig
、PrometheusRule
などといった設定用のカスタムリソースも定義されています。また、Serviceに関連付けられたPodを間接的に指定するServiceMonitor
と、Podを直接指定するPodMonitor
も特徴的です。
例えばPrometheus
というCRDは、scrapeConfigSelector
やserviceMonitorSelector
などのフィールドによって、使用するScrapeConfig
やServiceMonitor
を特定できます。詳細は以下の公式ドキュメントが図解付きで分かりやすいです。
2つ目は冒頭で述べた課題を解決するもので、KubernetesのリソースとしてPrometheusのバージョンやレプリカ数などを管理できます。3つ目については、Kubernetesのラベルから監視ターゲットの設定を生成できるため、Prometheusの従来のYAML設定を必要としません。どちらも運用上のメリットが大きいです。
2. Prometheus Operatorのインストール
さて、Prometheus Operatorのインストール方法ですが、公式ドキュメントでは3通りの方法が紹介されていました。Prometheus OperatorとCRDのみインストールする方法もこのうちの1つですが、より簡単にデプロイできる方法を検討します。
kube-prometheusはPrometheus Operatorと同じOrganizationによってメンテナンスされています。しかし今回はHelmを利用してインストールしたかったため、kube-prometheus-stackを利用します。どちらもPrometheus Operatorを利用したGrafanaダッシュボード付きのマニフェストです。
kubeadmを利用している場合、いくつか事前準備が必要なので公式ドキュメントをご参照ください。
既にArgo CDを導入してGitOpsを実践しているため、以下のようなマニフェストを用意しました。
apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: kube-prometheus-stack namespace: argocd spec: project: default source: repoURL: https://prometheus-community.github.io/helm-charts chart: kube-prometheus-stack targetRevision: 70.4.2 helm: valuesObject: grafana: grafana.ini: server: root_url: "%(protocol)s://%(domain)s:%(http_port)s/grafana/" serve_from_sub_path: true prometheus: prometheusSpec: externalUrl: "http://<NodeIP>:<NodePort>/prometheus" routePrefix: /prometheus alertmanager: alertmanagerSpec: externalUrl: "http://<NodeIP>:<NodePort>/alertmanager" routePrefix: /alertmanager destination: server: https://kubernetes.default.svc namespace: kube-prometheus-stack syncPolicy: automated: {} syncOptions: - CreateNamespace=true - ServerSideApply=true
<NodeIP>
や<NodePort>
は各自で置き換えてください。
ブラウザからGrafana / Prometheus / Alertmanagerにアクセスするとリダイレクトが発生するため、私たちのように/grafana
/ /prometheus
/ /alertmanager
でアクセスさせたい場合はvalues.yaml
の値を上書きしてサブパスを指定する必要があります。
公式ドキュメントではPrometheusやAlertmanagerを公開する方法として、NodePortやKuberenetes API、Ingressを利用する方法が紹介されていましたが、今回は引き続きIstioのIngress Gatewayを利用することにしました。
Gateway
のマニフェスト
apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: http-gateway namespace: istio-system spec: selector: istio: ingressgateway servers: - port: number: 80 name: http protocol: HTTP hosts: - "*"
VirtualService
のマニフェスト
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: kube-prometheus-stack-virtualservice namespace: kube-prometheus-stack spec: hosts: - "*" gateways: - istio-system/http-gateway http: - match: - uri: prefix: /grafana route: - destination: host: kube-prometheus-stack-grafana port: number: 80 - match: - uri: prefix: /prometheus route: - destination: host: kube-prometheus-stack-prometheus port: number: 9090 - match: - uri: prefix: /alertmanager route: - destination: host: kube-prometheus-stack-alertmanager port: number: 9093
この設定によってhttp://<NodeIP>:<NodePort>/{grafana,prometheus,alertmanager}
のようなパスベースのルーティングを行うことができ、<NodeIP>:<NodePort>
さえ分かれば簡単にそれぞれのWeb UIにアクセスできます。
そうは言ってもやはりドメイン名でアクセスしたいので、近いうちにMetalLBとExternalDNSを導入する予定です。
3. NVIDIA GPU Operatorのインストール
お馴染みのNVIDIA/dcgm-exporterを利用してKubernetes上でもGPUメトリクスを監視する予定でしたが、READMEには以下のように書かれていました。
Note: Consider using the NVIDIA GPU Operator rather than DCGM-Exporter directly.
今度はNVIDIA/gpu-operatorのREADMEを確認すると以下のように紹介されています。
These components include the NVIDIA drivers (to enable CUDA), Kubernetes device plugin for GPUs, the NVIDIA Container Runtime, automatic node labelling, DCGM based monitoring and others.
DCGMだけでなく、#14でコンテナからGPUを利用するために導入したNVIDIA/k8s-device-pluginも含まれているようです。さらに、今まで手動でメンテナンスしていたNVIDIA GPU DriverやNVIDIA Container Toolkitも含まれているとのことで(インストール済みなので今回は無効化しますが)恩恵が大きいと感じました。
早速#14で導入したk8s-device-pluginは削除して、gpu-operatorを以下の公式ドキュメントに従ってインストールします。
注意点として、以下のような差分を一度にSyncしないようにしてください。k8s-device-pluginにもNode Feature Discovery(NFD)が含まれているため、一旦無効化してからgpu-operatorでNFDをインストールする必要があります(公式ドキュメント参照)。
apiVersion: argoproj.io/v1alpha1 kind: Application metadata: - name: nvidia-device-plugin + name: gpu-operator namespace: argocd spec: project: default source: - repoURL: https://nvidia.github.io/k8s-device-plugin - chart: nvidia-device-plugin - targetRevision: 0.17.1 + repoURL: https://helm.ngc.nvidia.com/nvidia + chart: gpu-operator + targetRevision: v25.3.0 helm: parameters: - - name: gfd.enabled - value: "true" + - name: driver.enabled + value: "false" + - name: toolkit.enabled + value: "false" destination: server: https://kubernetes.default.svc - namespace: nvidia-device-plugin + namespace: gpu-operator syncPolicy: automated: {} syncOptions:
nvidia-device-plugin-***
やnvidia-dcgm-exporter-***
というPodが起動していることを確認しましょう。
続いて、GPUメトリクスに関してPrometheusとGrafanaのセットアップも行います。
上記の公式ドキュメントに従うのが最も手っ取り早いです。2章のマニフェストで変更が必要なPrometheus部分だけを示します。
prometheus: prometheusSpec: externalUrl: "http://<NodeIP>:<NodePort>/prometheus" routePrefix: /prometheus serviceMonitorSelectorNilUsesHelmValues: false additionalScrapeConfigs: - job_name: gpu-metrics scrape_interval: 15s metrics_path: /metrics scheme: http kubernetes_sd_configs: - role: endpoints namespaces: names: - gpu-operator relabel_configs: - source_labels: [__meta_kubernetes_endpoints_name] action: drop regex: .*-node-feature-discovery-master - source_labels: [__meta_kubernetes_pod_node_name] action: replace target_label: kubernetes_node - source_labels: [__address__,__meta_kubernetes_endpoint_node_name] action: replace separator: , target_label: instance
relabel_configs:
の最後のアイテムは独自に付け加えました。理由はGrafanaダッシュボード上でホスト名による変数フィルタリングを行うためです。NVIDIA DCGM Exporterという人気のあるダッシュボードを利用する場合、フィルタリング変数はinstance
(デフォルトは__address__
つまり192.168.1.xxx:9400
のようなフォーマット)となり、ダッシュボード利用者がワーカーノードのIPアドレスを暗記しなければなりません。
__address__
と__meta_kubernetes_endpoint_node_name
(ホスト名)をカンマ区切りで結合した文字列でinstance
ラベルを置換することで、さらにダッシュボード側で正規表現を利用して表示用のtext
とクエリ用のvalue
を抽出できます。
ただし、これらの変更によって元のinstance
ラベルも変更されてしまったのでダッシュボード設定のJSON Modelタブで以下のような書き換えも行う必要があります。
s/instance=~\"${instance}\"/instance=~\"${instance}.*\"/g
Grafanaダッシュボードは管理者だけでなく研究室メンバーにも普及しているので可能な限り認知負荷を下げるようにダッシュボードをセットアップしました。
まとめ
今回は、Prometheus Operatorなどを利用してKubernetesネイティブな監視基盤に移行する方法を紹介しました。Kubernetes上でメトリクスを収集できましたが、古い監視基盤のAlertmanagerの設定はまだ移行できていないので徐々に進めていきたいです。
一般的な研究室ではワーカーノードが数台程度なので古い監視基盤でも問題にならない規模ですが、GitOpsで監視の設定を一元管理できる点と各コンポーネントのアップデートが現実的になる点で、Kubernetesネイティブな監視基盤に移行するメリットは大きいと考えました。
ただし、Kubernetesクラスタがある時点で逸般的な研究室である可能性は高いので、ファーストステップとして監視基盤を構築したい方は依然として#5の方法をオススメします。