WSL上のKubernetesでホストマシンのGPUを使ってみる
はじめに
みなさんはKubernetes上でGPUをつかったことはありますか?自分はありません。
そもそもKubernetesを個人利用している方が少ないと思うので、仕事で使う機会が無ければ無いと思います。GPUも個人利用している方はゲームか機械学習コンペ目的などでしょう。そういったわけでGPU on Kubernetesなんてお金持ちの遊びみたいなことしたことある方はそうそう居ないだろう思います。今回は自宅PCで簡単にGPU on Kubernetesをやってみてとりあえずこの世界に入門してみようと思います。
環境
環境はWSL(ubuntu20.04)にKubernetesを建てて、GPUは汎用nvidia GPU(Geforce RTXシリーズ)を使用します。
WSL上のコンテナからGPUを使う
WSL上のKubernetesからGPUを使う前にまずWSLから直接(or コンテナから)GPUが使えるようにしないと始まらないので、そのためのセッティングを行います。
CUDA on WSLのページを見てみるとWSL上でGPU(CUDA)を使うためのかなり詳細なガイドが載っています。このページに従って各コンポーネントを用意していきます。図によるとCUDA on WSLに必要な手順は
- ホストマシンにNVIDIA Windows Driverを入れる
- WSLにNVIDIA Container Toolkitを入れる
だとわかります。
ホストマシンにNVIDIA Windows Driverを入れる
今回初めてGPUを使用する場合でない限り基本的には既にインストールされているかと思いますが、ちょうどいい機会なのでversion updateを兼ねて新しいものを入れ直します。
https://www.nvidia.com/Download/index.aspx こちらのページでご自身のホストマシン(windows)の環境に合わせてインストールしてください。
どうやらドライバーのインストールと同時に/usr/lib/wsl/lib
配下にnvidia-smi
等インストールしてくれるみたいです。早速WSLでnvidia-smi
コマンドを実行してみます。
$ nvidia-smi
Sat Feb 25 14:22:03 2023
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 525.89.02 Driver Version: 528.49 CUDA Version: 12.0 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|===============================+======================+======================|
| 0 NVIDIA GeForce ... On | 00000000:01:00.0 On | N/A |
| 0% 42C P8 15W / 240W | 571MiB / 8192MiB | 1% Default |
| | | N/A |
+-------------------------------+----------------------+----------------------+
ご自身のGPU(今回はNVIDIA GeForce ...)が確認出来たらokです。
WSLにNVIDIA Container Toolkitを入れる
setting-up-nvidia-container-toolkitを参照してnvidia-container-toolkitをインストールします。こちらはwsl上で行ってください。 Kubernetesで管理されていないピュアなコンテナを使用してnvidia-smiができることを確認しておきます。ここではDockerDesktopが用意してくれているdockerを使用していますがKubernetesでのランタイムはcontainerdなので、もちろんnerdctlを使用しても大丈夫です。(参照: https://github.com/containerd/nerdctl/blob/main/docs/gpu.md)
$ docker run --rm --gpus all nvidia/cuda:11.6.2-base-ubuntu20.04 nvidia-smi
ランタイムにGPUを使用するためには--gpus
フラグが必要になります。
参考: https://docs.docker.jp/config/containers/resource_constraints.html?highlight=gpu#gpu
さてこれで無事GPUを認識できていれば大丈夫です。あとはk8sを用意するだけです。
WSL上にk8sを建てる
初めてだとやや大変だと思いますが基本的には以下の手順です。今回は詳細は省きます。
参考: https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/, https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/
- prepare container runtime (今回はcontainerdを使用します)
- install kubeadm, kubelet, kubectl
- kubeadm init
- install cni (今回はweaveを使用します。)
適当なpodをデプロイしてみて動けばokです。今回はcontrol-planeの1ノードだけなのでpodがスケジュールされるようtaintを外すのを忘れないようにします。
nginxをデプロイしてみます。kubectl run nginx --image=nginx
NAMESPACE NAME READY STATUS RESTARTS AGE
default nginx 1/1 Running 0 78s
kube-system coredns-787d4945fb-2hzhm 1/1 Running 0 3m26s
kube-system coredns-787d4945fb-n4hsz 1/1 Running 0 3m26s
kube-system etcd-desktop-2uoplus 1/1 Running 1 3m35s
kube-system kube-apiserver-desktop-2uoplus 1/1 Running 1 3m34s
kube-system kube-controller-manager-desktop-2uoplus 1/1 Running 2 3m35s
kube-system kube-proxy-qn8lx 1/1 Running 0 3m27s
kube-system kube-scheduler-desktop-2uoplus 1/1 Running 2 3m35s
kube-system weave-net-d8hwd 2/2 Running 0 2m3s
okです。最後にKubernetes上でGPUを使用するための設定を行います。
GPUノードの準備
参考: https://kubernetes.io/docs/tasks/manage-gpus/scheduling-gpus/
shceduling-gpusのページに従って必要な準備をしていきます。
- install nvidia-container-toolkit (すでに終わっているので飛ばします)
- configure containerd (https://github.com/NVIDIA/k8s-device-plugin#configure-containerd)
- deploy gpu-device-plugin daemonset (https://github.com/NVIDIA/k8s-device-plugin#enabling-gpu-support-in-kubernetes)
deploy gpu device plugin Daemonset
今回はnvidiaのgpuを使用しているのでnvidiaのgpu device pluginをデプロイします。
$ kubectl create -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.13.0/nvidia-device-plugin.yml
logを見てみます。
$ kubectl logs nvidia-device-plugin-daemonset-vcklb
...
...
2023/02/25 08:44:36 Retreiving plugins.
2023/02/25 08:44:36 Detected NVML platform: found NVML library
2023/02/25 08:44:36 Detected non-Tegra platform: /sys/devices/soc0/family file not found
2023/02/25 08:44:36 No devices found. Waiting indefinitely.
No device foundになってます。。。。
もちろんgpu-podをdeployしてみても
Warning FailedScheduling 15s (x2 over 97s) default-scheduler 0/1 nodes are available: 1 Insufficient nvidia.com/gpu. preemption: 0/1 nodes are available: 1 No preemption victims found for incoming pod..
のようなエラーがでてきてしまいます。。
とりあえずnvidia-device-pluginのpodでnvidia-smiしてみると
$ kubectl exec nvidia-device-plugin-daemonset-vcklb -- nvidia-smi
Sat Feb 25 08:55:26 2023
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 525.89.02 Driver Version: 528.49 CUDA Version: N/A |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|===============================+======================+======================|
| 0 NVIDIA GeForce ... On | 00000000:01:00.0 On | N/A |
| 0% 43C P8 16W / 240W | 636MiB / 8192MiB | 1% Default |
| | | N/A |
+-------------------------------+----------------------+----------------------+
ちゃんと認識できてます。うーんdevice-pluginで何か設定する必要がありそうですが疲れてしまったのでいったんこれで良しとします。。。
ちなみにrunning-gpu-jobsのページにWARNING: if you don't request GPUs when using the device plugin with NVIDIA images all the GPUs on the machine will be exposed inside your container.
とあるようにresourceのrequest,limitを指定しなければpodは普通にスケジューリングされるので、もしそのノードにGPUがあれば一応GPUは使えます。
おわりに
解決策見つけ次第加筆します。もし原因がわかる・わかった方がいたら是非教えてください。
環境構築って大変。おわり。
追記 2023/03/28
どうやらこちらの記事にあるように、nvidia-device-plugingがWSLに対応していないのが原因のようでした : https://zenn.dev/rrrrrrryo/articles/0f86ca44b7044b
Discussion