k8s クラスタからGPUを使用する方法について( gpu-operator)
本記事ざっくりと
k8sのgpuのためのセッティングについての項目が公式ドキュメントでは古かったので、nvidaのgpu-operatorを用いてgpuからpodを使用するためのセッティングを行いました。
この記事に記載されている方法を用いて設定すれば、k8s上でgpuを使用したタスクを実行できるようになります。
はじめに
おうちk8sをやっていて、kubeflowや機械学習タスクなどをk8sに行わせたい場合、k8sからGPUを使いたくなります。しかし、k8sからgpuを使用するためには特殊で複雑な設定が必要になります。しかし、「k8s gpu」などで出てくる公式のドキュメントは古く、ちょっと心配です(コンテナランタイムがdockerじゃないと出来ないって書いてあるし。。。)
本記事では、Nvidia の gpu-operator のドキュメントのインストール手順を説明しながら、私がつまづいた部分への打開策を備忘録も兼ねて書いていこうと思います。
前提条件
本記事の内容は、k8sクラスタのワーカーノードのどれか一つにGPUが一枚以上刺さっていることが前提条件です。
本記事の内容は以下の環境で行いました
- kubernetes: v1.21.1
- container runtime: cri-o
- ubuntu server: 20.04.5
- build tool: kubeadm
- GPU: GTX980
また、我が家のk8sクラスタの構成は以下の通りです
nodename | gpu | ||
---|---|---|---|
1 | ubuntu01 | 1 | |
2 | ubuntu02 | 0 | |
3 | ubuntu03 | 0 | control-plane |
手順
ここからが、実際の作業手順です
Helmのインストール
gpu-operator をインストールするためにk8s用パッケージマネージャーであるHelmをマスターノードにインストールします。
マスターノードにsshし、以下コマンドでhelmをインストールしてください
$ curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 \
&& chmod 700 get_helm.sh \
&& ./get_helm.sh
gpu-operatorのインストール
先ほどインストールしたHelmを用いて、gpu-operatorをインストールします
まず、nvidiaのhelm repositoryを追加します
$ helm repo add nvidia https://helm.ngc.nvidia.com/nvidia \
&& helm repo update
その後、実際にgpu-operatorをインストールしますが、ここからは実際の環境に応じてインストール方法が異なります。
既にGPUドライバが入っているPCや、CentOSを用いているPCなどにセッティングしたい場合は、公式のインストール手順をご覧ください。
以下に記載したコマンドは、私の環境である、GPUドライバなど何もインストールしてないubuntu serverへのインストール手順です。このコマンドを実行することで、gpu-operatorがデプロイされます。
$ helm install --wait --generate-name \
-n gpu-operator --create-namespace \
nvidia/gpu-operator
helmの実行が完了したら以下コマンドで、gpu-operatorの各podが正しくスケジューリングさてれいるかを確認します。もし以下のようになっていればインストールは完了です。
$ kubectl get pod -n gpu-operator
NAME READY STATUS RESTARTS AGE
gpu-feature-discovery-zz9rv 1/1 Running 0 5h44m
gpu-operator-1664607449-node-feature-discovery-master-679b6jqgh 1/1 Running 0 5h45m
gpu-operator-1664607449-node-feature-discovery-worker-994vg 1/1 Running 0 5h45m
gpu-operator-1664607449-node-feature-discovery-worker-d7nfk 1/1 Running 0 5h45m
gpu-operator-1664607449-node-feature-discovery-worker-jrplg 1/1 Running 0 5h45m
gpu-operator-1664607449-node-feature-discovery-worker-qwx6f 1/1 Running 0 5h45m
gpu-operator-1664607449-node-feature-discovery-worker-t6msd 1/1 Running 0 5h45m
gpu-operator-84d9f557c8-drxww 1/1 Running 0 5h45m
nvidia-container-toolkit-daemonset-t67lj 1/1 Running 0 5h44m
nvidia-cuda-validator-t6mgw 0/1 Completed 0 5h29m
nvidia-dcgm-exporter-wqm4z 1/1 Running 0 5h44m
nvidia-device-plugin-daemonset-nnsnr 1/1 Running 0 5h44m
nvidia-device-plugin-validator-q4fkr 0/1 Completed 0 5h29m
nvidia-driver-daemonset-22pc5 1/1 Running 0 5h44m
nvidia-operator-validator-zr22z 1/1 Running 0 5h43m
正しくpodが立ち上がらない場合
cri-oをコンテナランタイムとして使用している場合、helm installのみでは正しくpodが立ち上がらない問題が確認されています。具体的には以下のようになります。
$ kubectl get pod -n gpu-operator
gpu-feature-discovery-jd2jn 0/1 Init:0/1 0 43m
gpu-feature-discovery-vb9nk 0/1 Init:0/1 0 43m
nvidia-container-toolkit-daemonset-6flgq 1/1 Running 0 43m
nvidia-container-toolkit-daemonset-jnt62 1/1 Running 0 43m
nvidia-dcgm-b26rc 0/1 Init:0/1 0 43m
nvidia-dcgm-exporter-8tngv 0/1 Init:0/1 0 43m
nvidia-dcgm-exporter-kmtg6 0/1 Init:0/1 0 43m
nvidia-dcgm-r8qww 0/1 Init:0/1 0 43m
nvidia-device-plugin-daemonset-l4dsn 0/1 Init:0/1 0 43m
nvidia-device-plugin-daemonset-rhz62 0/1 Init:0/1 0 43m
nvidia-driver-daemonset-rfvvg 1/1 Running 0 43m
nvidia-driver-daemonset-wlqws 1/1 Running 0 43m
nvidia-operator-validator-l72z2 0/1 Init:CrashLoopBackOff 13 (41s ago) 43m
nvidia-operator-validator-vzh9c 0/1 Init:CrashLoopBackOff 13 (44s ago) 43m
この場合は、GPUが入っているnodeにsshで接続し、cri-oの設定ファイルを変更することで解決します。
具体的には、GPUが入っているPCの/etc/crio/crio.conf
に以下の行を追加します。
[crio.runtime]
hooks_dir=["/run/containers/oci/hooks.d"]
上の行を追加したら、sudo systemctl restart crio
でcri-oをリスタートしてください。5分から10分経ち、再びkubectl get pod -n gpu-operator
で確認すれば、全てのPODが「Runnning」か「Completed」になっていると思います。
これで設定は完了です。
GPUを使用できるか確認
では、実際にGPUを使用して計算をしてみます。
以下のコマンドを叩き、GPUでベクトル演算をさせます
$ cat << EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: cuda-vectoradd
spec:
restartPolicy: OnFailure
containers:
- name: cuda-vectoradd
image: "nvidia/samples:vectoradd-cuda11.2.1"
resources:
limits:
nvidia.com/gpu: 1
EOF
上記manifestのspec.containers.resources.limitsでgpuを指定していることがわかります。
logを確認してみます
$ kubectl logs cuda-vectoradd
[Vector addition of 50000 elements]
Copy input data from the host memory to the CUDA device
CUDA kernel launch with 196 blocks of 256 threads
Copy output data from the CUDA device to the host memory
Test PASSED
Done
実際に計算されているみたいですね。成功です!!
では次にpodの中からnvida-smiを確認してみましょう
以下コマンドで適当なpodを作成します
$ cat << EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
name: tensorflow-gpu
spec:
containers:
- name: tensorflow-gpu
image: tensorflow/tensorflow:latest-gpu
command: ["/bin/sleep"]
args: ["3600"]
resources:
limits:
nvidia.com/gpu: 1
EOF
作れたかどうか確認
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
tensorflow-gpu 1/1 Running 0 25s
ちゃんと作れたみたいなのでshellに入り、nvidia-smiしてみようと思います。いつも思うけどtensorflowのcontainerをrunすると出てくるのかっこいいですよね。
$ kubectl exec -it tensorflow-gpu -- /bin/bash
________ _______________
___ __/__________________________________ ____/__ /________ __
__ / _ _ \_ __ \_ ___/ __ \_ ___/_ /_ __ /_ __ \_ | /| / /
_ / / __/ / / /(__ )/ /_/ / / _ __/ _ / / /_/ /_ |/ |/ /
/_/ \___//_/ /_//____/ \____//_/ /_/ /_/ \____/____/|__/
root@tensorflow-gpu:/# nvidia-smi
Sat Oct 1 13:19:13 2022
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 515.48.07 Driver Version: 515.48.07 CUDA Version: 11.7 |
|-------------------------------+----------------------+----------------------+
| 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 Off | N/A |
| 28% 36C P8 13W / 180W | 1MiB / 4096MiB | 0% Default |
| | | N/A |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=============================================================================|
| No running processes found |
+-----------------------------------------------------------------------------+
はい。nvida-smiもちゃんと出てきていますね!
終わりに
今回の記事では、gpuドライバなどを自動管理してくれるnvida gpu-operatorをおうちk8sクラスタにデプロイしました。このクラスタで、tensorflowを用いた学習などを行う場合は、cudaのバージョンと合ったtensorflowを用いなければならなかったりと、実用にはもう一工夫必要になります。
もし、需要がありましたら、kubeflowからgpuを使用することができるnotebookの作成などの記事も作成していきたいと思います。
以上!nvidia gpu-operatorのセットアップと確認でした。
最後まで読んでいただきありがとうございます。
参考にさせていただきた記事
Discussion