はじめに
近年のDeep Learningブームの中で、多数のGPUノードをKubernetesで管理し、複数人で共有するといった運用形態を良く耳にするようになりました。弊社でもオンプレミス環境にGPUクラスタを構え、Deep Learningを用いたAI開発を行っています(開発プラットフォームとしてはOSSのKAMONOHASHIを利用しています)。
GPUクラスタを共有し利用していく中で、GPUノードの利用状況をメトリクスとして収集し、過去の利用過程を可視化したいという要望が出てきました。そこでNVIDIA DCGM exporter for PrometheusとPrometheusを用いて、GPUのメトリクスを収集してみました。
なお、本記事で利用するファイルはGitHubに置いています。
ゴール
GPUノードが含まれるKubernetesクラスタに、PrometheusとDCGM exporterを導入し、PrometheusでGPUのメトリクスが収集できるようにします。
バージョン情報
利用した各コンポーネントのバージョンは以下の通りです。
- Kubernetes: v1.14.1
- helm: v2.13.0
- NVIDIA DCGM exporter for Prometheus: d39e0cc8675c0b10aab14d4f66191eedf5029f66
- Prometheus: 2.13.1(helm chartはprometheus-9.3.1を利用)
- nginx-ingress: v0.26.1(helm chartはnginx-ingress-1.24.7を利用)
Prometheus, nginx-ingressに関してはHelmを用いて導入しました。
クラスタの構成
クラスタに含まれるノードは、以下のものとします。
- master: Kubernetesのmasterノード
- gpu1: NVIDIA Tesla K80搭載のGPUノード
- gpu2: NVIDIA Tesla K80搭載のGPUノード
- kamonohashi: KAMONOHASHIで利用のノード。今回は関係なし
※既存のKAMONOHASHIクラスタを利用しています。KAMONOHASHI導入時、Kubernetesはkubesprayを利用して構築しています。
今回はmasterノードにPrometheusをデプロイし、Ingressを通してアクセスします。Ingress ControllerにはNginx Ingress Controllerを利用します。
またDCGM exporterが動く要件は以下が提示されているため、各GPUノードでこれらの要件を満たすようにしておきます。
Prerequisites
- NVIDIA Tesla drivers = R384+ (download from NVIDIA Driver Downloads page)
- nvidia-docker version > 2.0 (see how to install and it's prerequisites)
- Optionally configure docker to set your default runtime to nvidia
NVIDIAが提供しているGPUのモニタリングツール
NVIDIAが提供しているGPUのモニタリングツールは、GitHubのNVIDIA/gpu-monitoring-toolsから入手できます。この中のNVIDIA DCGM exporter for Prometheusが、PrometheusでGPUのメトリクスを取る際のexporterとして利用できるものとなっています。DCGMはNVIDIA Data Center GPU Managerの略で、GPUクラスタのメトリクスを取るために用意されているツール群のことを表します。
このリポジトリですが、少し中身が分かりづらいため、ここで整理しておきます。
NVIDIA DCGM exporter for Prometheus内のk8s/node-exporter
が、exporterのDaemonSetのマニフェストが格納されたディレクトリとなっています(k8s/pod-gpu-metrics-exporter
は、exporter自体のソースコードが格納されています)。
k8s/node-exporter
内には、以下の3つのマニフェストファイルが格納されています。
gpu-node-exporter-daemonset.yaml
GPUノードのメトリクスをCPU等の情報も含めて取得するexporterのDaemonSet
gpu-only-node-exporter-daemonset.yaml
GPUノードのメトリクスをGPU情報のみを取得するexporterのDaemonSet
pod-gpu-node-exporter-daemonset.yaml
PodごとのGPU利用状況のメトリクスを取得するexporterのDaemonSet
これらのDaemonSetは、それぞれ以下のexporterの組み合わせにより構成されています。
prometheus/node-exporter
Prometheusが提供している一般的なexporterです。
nvidia/dcgm-exporter
NVIDIAが提供しているGPUノードのメトリクスを取るexporterです。このexporterを用いることで、GPUノードごとのGPU利用率やGPUメモリ利用量が取得できます。prometheus/node-exporter
とこのexporterを統合したものが、gpu-node-exporter-daemonset
、gpu-only-node-exporter-daemonset
で利用されています。
nvidia/pod-gpu-metrics-exporter
PodごとのGPU利用状況のメトリクスを取るexporterです。このexporterを用いることで、GPUノードに立っているPodごとのGPU利用率やGPUメモリ利用量が取得できます。prometheus/node-exporter
およびnvidia/dcgm-exporter
と、このexporterを統合したものが、pod-gpu-node-exporter-daemonset
で利用されています。
kubeletを利用してpodの情報を取得するため、FeatureGatesのKubeletPodResourcesが有効になっている必要があります(Kubernetes v1.15以降はデフォルトで有効になっています)
本記事ではpod-gpu-node-exporter-daemonset.yaml
を利用して、PodごとのGPU利用状況のメトリクスを取得してみます。
手順
1. kubeletの設定変更
今回用いたKubernetesはv1.14.1であるため、PodごとのGPU利用状況のメトリクスを取得するためには、各GPUノードにおいてkubeletのFeatureGatesの機能を有効にする必要があります。
各GPUノードで/etc/systemd/system/kubelet.service
を編集し、ExecStartの部分を修正します。
ExecStart=/usr/local/bin/kubelet \
+ --feature-gates KubeletPodResources=true \
そして以下のコマンドでkubeletを再起動します。
systemctl daemon-reload
systemctl restart kubelet
これらの作業により、上述のexporterがPodの情報を取得できるようになります。
2. namespaceの作成
今回デプロイするリソース用のnamespaceを作成します。名前はmonitoring
とします。
kubectl create namespace monitoring
3. GPUノードに対するラベル付与
pod-gpu-node-exporter-daemonset
ではnodeSelectorとしてhardware-type: NVIDIAGPU
が設定されており、このラベルが付与されたノードに対してexporterが配置される設定となっています。
そこで以下のように、GPUノードに対してラベル付けを行います(<gpu-node-name>をgpu1などのgpuノードのホスト名に変更)。
kubectl label nodes <gpu-node-name> hardware-type=NVIDIAGPU
ラベルの付与状況は、以下のコマンドで確認できます。
kubectl get nodes --show-labels
4. Prometheusのデータ保存先を作成
Prometheusをデプロイする際には、収集したデータの保存先を指定する必要があります。今回はmasterノードの/var/lib/prometheus
配下に保存することとします。以下のコマンドでディレクトリを作成し、ownerをnobodyに設定します。Prometheus serverはnobodyユーザで実行されるため、ownerの変更が必要となります。
mkdir /var/lib/prometheus
chown nobody /var/lib/prometheus
5. 各種リソースのデプロイ
以下のリソースをデプロイします。利用したファイルはGitHubに置いています
- GPUノード用のexporterを配置するためのDaemonSet(
pod-gpu-node-exporter-daemonset.yaml
) - exporterのPodにアクセスするためのservice(
exporter-service.yaml
) - Prometheusで利用するPersistent Volume, Persistent Volume Claim(
prometheus-pv-pvc.yaml
)
GPUノード用のexporterに関しては、元のリポジトリにあるpod-gpu-node-exporter-daemonset.yaml
のnamespaceをkube-system
からmonitoring
に変更したものを用います。またPrometheusがexporterのPodから情報を収集できるようにするためserviceも作成します。さらにPrometheusのデータ保存用のPVおよびPVCを、8GB(Prometheusチャートのデフォルト値)の容量で作成します。
これら3つのマニフェストファイルを以下のコマンドで適用します。
kubectl apply -f pod-gpu-node-exporter-daemonset.yaml -f exporter-service.yaml -f prometheus-pv-pvc.yaml
exporterのデプロイ後、正常にGPUノードのメトリクスが出力されているかは以下のコマンドで確認できます。
curl <gpu-node-name>:9100/metrics | grep dcgm
dcgm_gpu_utilization
等が出力されていれば、正常にexporterが起動しています。一度ここで確認することをおすすめします。
6. Prometheusのインストール
Helmを利用してPrometheusのインストールを行います。
以下のコマンドでprometheusの設定ファイルをダウンロードし、編集します。
helm inspect values stable/prometheus > prometheus-values.yaml
今回は、ひとまず動作させることを目的にしているため、ほぼ全ての機能を無効化した状態でデプロイします。
- Prometheus serverのみ有効化
-
http://master-hostname/prometheus
のような形でアクセスするためにprefixURLとbaseURLを変更 - prometheus serverのingressを有効化し、ingress.classとしてprometheus-nginxを指定
- masterノードにデプロイするようnodeSelectorを設定
- persistentVolumeとして上記で作成したものを指定
編集が完了後、以下のコマンドでPrometheusのインストールを行います。
helm install --name prometheus --namespace monitoring --version 9.3.1 -f prometheus-values.yaml stable/prometheus
7. Ingress Controllerのインストール
Prometheus ServerのIngress用に、Nginx Ingress Controllerをインストールします。
以下のコマンドで設定ファイルをダウンロードし、編集します。
helm inspect values stable/nginx-ingress > nginx-ingress-values.yaml
編集内容は次のようなものです。
- ingressClassをprometheus-nginxに変更
- scopeを有効にし、namespaceとしてmonitoringを指定
- defaultBackendServiceとして
monitoring/prometheus-server
を指定 - masterノードにデプロイするようnodeSelectorを設定
- externalIPsとしてmasterノードのIPを指定
編集が完了後、以下のコマンドでIngress Controllerのインストールを行います
helm install stable/nginx-ingress --name prometheus-nginx --namespace monitoring --version 1.24.7 -f nginx-ingress-values.yaml
8. Prometheusの利用
ブラウザでPrometheusデプロイ時に設定したURLにアクセスすることで、Prometheusでのメトリクス取得状況を見ることができます。gpu関連のメトリクスはdcgm_...というもので取得できます。
まとめ
NVIDIA DCGM exporter for PrometheusとPrometheusを組み合わせることで、GPUリソースの利用状況の監視が可能となりました。Grafanaと組み合わせることで、Prometheusでの収集結果を美しく可視化することも可能です。
実際に運用するには、メトリクスの保存領域のサイズ等を詳しく検討する必要がありますが、似たようなことを実現したい方の参考になれば幸いです。