本日も乙

ただの自己満足な備忘録。

GCE インスタンス・GKE ノードの GPU メトリクスを Stackdriver に投げるツールを作った

本稿は Google Cloud Platform Advent Calendar 2019 の 17日目の記事です。

tl;dr

  • GCE インスタンスの GPU メトリクス(GPU 使用率、メモリ使用率、温度)を Stackdriver(Monitoring)に送るツールを作った
  • Docker イメージも公開していて、GKE ノードにも対応している
  • 移動平均でメトリクス値を滑らかにする工夫

GCE インスタンスで GPU メトリクスを取りたい!

まず、Stackdriver agent は GPU の取得に対応していません。そのため、サードパーティツールで GPU メトリクスを収集する必要があります。

GCP ドキュメントではサードパーティツールを使った方法が紹介されていますが、このツールがなんと Python 2系です。Python 3系にアップデートされるような Issue や Pull Request(PR)がありませんでした。

Python 3系に対応するように修正・PRを送る手も考えたのですが、pip インストールの煩わしさが嫌だったのでワンバイナリにするためにGo言語で一から書くことにしました。

リポジトリ

github.com

Docker イメージも公開しています。

hub.docker.com

サポートOS

Ubuntu 16.04/18.04 での動作は確認しています。NVML(NVIDIA Management Library)は NVIDIA が公開しているライブラリをつかっていて、その制約上 Linux のみ動きます。

github.com

メトリクス

  • custom.googleapis.com/gpu_utilization: GPU 使用率
  • custom.googleapis.com/gpu_memory_utilization: GPU メモリ使用率
  • custom.googleapis.com/gpu_temperature: 温度

使い方

予め GCE インスタンスに CUDA をインストールしておいてください。

バイナリをダウンロードするか、go get でインストールできます。バイナリを /usr/local/bin などのパスが通るところに置いてください。
systemd にするには次のようにします。

$ cat <<-EOH > /lib/systemd/system/gcp-gpu-stackdriver-reporting.service
[Unit]
Description=GPU Utilization Metric Reporting
[Service]
Type=simple
PIDFile=/run/gcp-gpu-stackdriver-reporting.pid
ExecStart=/usr/local/bin/gcp-gpu-stackdriver-reporting
User=root
Group=root
WorkingDirectory=/
Restart=always
[Install]
WantedBy=multi-user.target
EOH
$ systemctl daemon-reload
$ systemctl enable gcp-gpu-stackdriver-reporting.service
$ systemctl start gcp-gpu-stackdriver-reporting.service

しばらくすると Stackdriver でこのようなグラフが見れるようになります。

stackdriver-gpu-utilization

Docker コンテナで動かす

NVIDIA Docker が必要になります。Quickstart を参考に設定してください。

Docker コンテナを動かすこと自体はとても簡単です。

$ docker pull ohsawa0515/gcp-gpu-stackdriver-reporting:latest
$ docker run -d --runtime=nvidia --rm ohsawa0515/gcp-gpu-stackdriver-reporting:latest

GKE クラスタで動かす

GKE ノードは GCE インスタンスで動いているのでこれを使えば GPU メトリクスを取得することができます。

GPU 対応の GKE クラスタを作った後、NVIDIA GPU デバイスドライバをインストールします。

$ kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/master/nvidia-driver-installer/cos/daemonset-preloaded.yaml

あとは Daemonset で動かすだけです。サンプルファイルを用意したので参考にしてください。

$ kubectl apply -f daemonset-sample.yaml

メトリクス値の移動平均

NVMLによって GPU メトリクス値を取得する瞬間の値が取得できます。そのため、取得するタイミングで GPU が使われているかによって下図のようにグラフがガタガタになってしまいます。

stackdriver-gpu-utilization-before

そこで滑らかにするように移動平均をメトリクス値として投げるようにしています。以下のような設定値にしています。

Stackdriver に送る間隔: 60秒
平均値をとる間隔: 5秒

つまり、Stackdriver に送信するまでに 12回 メトリクスを取得してその平均値を送っています。そうすることで1枚目のような滑らかなグラフになります。このパラメータ値は今後変更できるようにしたいと思います。

まとめ

GPU メトリクスを Stackdriver に投げるツールを作りました。突如必要になって突貫で作ったので CI/CD などがないので(余裕があれば)対応していきます。