nVidia cotnainer toolkit - oomichi/try-kubernetes GitHub Wiki
公式GitHub: https://github.com/NVIDIA/nvidia-container-toolkit
背景
LLMA系アプリケーションのコンテナにGPUを使わせるため、nVidiaのcontainer-toolkitを調べる必要が出てきた。 まずは、公式GitHubを翻訳しつつ理解する。
NVIDIA Container Toolkit
本ツールキットはGPUによって加速されたコンテナをビルド、実行するためのものだ。 NVIDIA GPUを活用するためにコンテナの設定を自動化するコンテナランタイムライブラリとユーティリティで本ツールキットは構成されている。 製品ドキュメントにはアーキテクチャ概要、プラットフォームサポート、そしてインストレーションガイド、ユーザーガイドが含まれている。 製品ドキュメントは https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/index.html
Getting Startd
NVIDIA driverがホストシステムのLinuxディストリビューションにインストールされている必要がある。 NVIDIA driverは https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html を参考にインストール。 CUDA Toolkitはホストシステムにインストールされている必要はない。
NVIDIA Container Toolkit自体のインストラクションは https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html を参考。
課題
上記までのNVIDIA側の説明により、以下の疑問を持った。
- KubernetesではなくDocker上での実行を前提にしており、Kubernetesの場合はWorker nodeのホストOSにNVIDIA Driverをインストールしている必要がある。 AKSやEKSなどのマネージドKubernetesの場合、クラウドベンダはそのオプションを提供しているのか。
- DockerではなくPodmanを使った場合も問題なく本ツールキットを利用できるのか。
実作業メモ: Ubuntu 22.04, x86_64
公式ガイドを基にツールキットをインストール
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
&& curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list \
&& \
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit
ツールキットの設定: Docker, Containerd, CRI-O, Podmanがサポートされていると公式ドキュメントに書いてあるが、podmanを指定するとエラーになる。
$ sudo nvidia-ctk runtime configure --runtime=podman
ERRO[0000] unrecognized runtime 'podman'
podmanは高位ランタイムであり、下位ランタイムOCIを直接呼び出すため containerdは使わない。 よって他のオプション docker, containerd, cri-oはpodman用には指定できない。 (podmanはcontainerdを使っているのでは、と予想したが誤解だった)
$ nvidia-ctk --version
NVIDIA Container Toolkit CLI version 1.14.3
commit: 53b24618a542025b108239fe602e66e912b7d6e2
https://github.com/NVIDIA/nvidia-container-toolkit/tags を参考にすると最新タグは v1.14.3 なので最新版になっている。 よく読んだら https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html#configuring-podman に記載があった。
podmanを使う場合はCDI(Container Device Interface)を使うらしい。 CDIはCSIとかCNIと同じようにコンテナがOS機能(今回はデバイス)を使うためのものっぽい。 nVidia container toolkit のv1.12.0 から使えるようになった。 上記のように最新がv1.14.3なので比較的最近実装された機能。
以下、CDIの説明
CDI is an open specification for container runtimes that abstracts what
access to a device, such as an NVIDIA GPU, means, and standardizes access
across container runtimes. Popular container runtimes can read and process
the specification to ensure that a device is available in a container.
CDI simplifies adding support for devices such as NVIDIA GPUs because the
specification is applicable to all container runtimes that support CDI.
CDI説明
前提条件
- nVidia container toolkit をインストールする
- nVidia GPU driver をインストールする
手順
(これらの手順はホストOSで実行する?)
CDI specification fileを生成する。
$ sudo nvidia-ctk cdi generate --output=/etc/cdi/nvidia.yaml
上記のコマンドが公式サイトにあったが、実行してみたところ下記のエラーが発生した。
$ sudo nvidia-ctk cdi generate --output=/etc/cdi/nvidia.yaml
INFO[0000] Auto-detected mode as "nvml"
ERRO[0000] failed to generate CDI spec: failed to create device CDI specs: failed to initalize NVML: ERROR_LIBRARY_NOT_FOUND
多分、ホストOSに「nVidia GPU driver」がインストールできていない? 「nVidia GPU driver」のインストール方法を調べる。
nVidia GPU driverインストール
推奨ドライバを調べる。
$ sudo apt update -y
$ sudo apt install -y ubuntu-drivers-common alsa-utils
nVidia devicesが表示されるか確認する。
$ ubuntu-drivers devices
$
何も表示されないので、GPU無しのVMを使ってしまっているかもしれない。 当該のAzure VMをAzureダッシュボードで確認する。
VM sizeはStandard_D4ads_v5だった。Azure の説明は以下の通り。
Dasv5 シリーズおよび Dadsv5 シリーズは、AMD の第 3 世代 EPYCTM 7763v プロセッサを、最大 256 MB の
L3 キャッシュを備えたマルチスレッド構成で利用し、汎用ワークロードを実行するための顧客オプションを増やします。
これらの仮想マシンは、小規模から中規模のデータベース、低から中程度のトラフィックの Web サーバー、
アプリケーション サーバーなど、ほとんどのエンタープライズ ワークロードに関連する要件を満たすために、
CPU とメモリの組み合わせを提供します。
内容的にはGPUについては言及されていないので多分入っていない。 GPU搭載VMのSizeを調べてみる。 他のVMでSizeが異なるのは「Standard_NC24ads_A100_v4」だった。 これは日本リージョンでは展開されていないのか、ラインナップになかった。
近いものはncv4ではなく、ncv3だった。 https://learn.microsoft.com/ja-JP/azure/virtual-machines/ncv3-series
Standard_NC24s_v3 だと 24vCPUs、448GiBメモリ、4GPUs。これは高そう。。 Standard_NC6s_v3 で一時的に試してみるか。。
- Standard_NC6s_v3でも$2,233/月、かなり高額。。
- Standard_NC24ads_A100_v4は$3,485/月
Standard_NC24ads_A100_v4 VMで実行してみたところ、nvidia-driverが表示される。
$ sudo ubuntu-drivers devices
== /sys/devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0004:00/VMBUS:00/00000081-0001-0000-3130-444532304235/pci0001:00/0001:00:00.0 ==
modalias : pci:v000010DEd000020B5sv000010DEsd00001533bc03sc02i00
vendor : NVIDIA Corporation
manual_install: True
driver : nvidia-driver-525-server - distro non-free
driver : nvidia-driver-535-server-open - distro non-free recommended
driver : nvidia-driver-470-server - distro non-free
driver : nvidia-driver-525-open - distro non-free
driver : nvidia-driver-535-server - distro non-free
driver : nvidia-driver-535-open - distro non-free
driver : xserver-xorg-video-nouveau - distro free builtin
CDI設定ファイルを作成する。
$ sudo nvidia-ctk cdi generate --output=/etc/cdi/nvidia.yaml
INFO[0000] Auto-detected mode as "nvml"
...
INFO[0000] Generated CDI spec with version 0.5.0
生成されたデバイス名を確認する。
$ nvidia-ctk cdi list
INFO[0000] Found 2 CDI devices
nvidia.com/gpu=0
nvidia.com/gpu=all
既存のStandard_NC24ads_A100_v4 VMがUbuntu20.04だったので以下の手順でpodman をインストールする。(Ubuntu 22.04なら普通に apt install で podman をインストール可能)
$ export VERSION_ID=20.04
$ echo "deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_${VERSION_ID}/ /" | sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
$ wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/xUbuntu_${VERSION_ID}/Release.key -O- | sudo apt-key add -
$ sudo apt update
$ sudo apt install -y podman
podmanコマンドで GPUを使ったコンテナを起動する。
$ podman run --rm --device nvidia.com/gpu=all --security-opt=label=disable ubuntu nvidia-smi -L
Resolved "ubuntu" as an alias (/etc/containers/registries.conf.d/000-shortnames.conf)
Trying to pull docker.io/library/ubuntu:latest...
Getting image source signatures
Copying blob aece8493d397 done
Copying config e4c5895818 done
Writing manifest to image destination
Storing signatures
Error: stat nvidia.com/gpu=all: no such file or directory
エラー発生。 nVidia公式ドキュメント には下記の記述がある。
In the case of podman, for example, releases as of v4.1.0 include support for specifying CDI devices in the --device argument.
一方、利用中の podman は
$ podman --version
podman version 3.4.2
podman の最新は現在 v4.7.2 これをインストールする必要がある。
Ubuntu 22.04 では以下の手順で podman v4.5.1 をインストールできた。
$ curl -fsSL https://download.opensuse.org/repositories/devel:kubic:libcontainers:unstable/Debian_Testing/Release.key | gpg --dearmor | sudo tee /etc/apt/keyrings/devel_kubic_libcontainers_unstable.gpg > /dev/null
$ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/devel_kubic_libcontainers_unstable.gpg]\
https://download.opensuse.org/repositories/devel:kubic:libcontainers:unstable/Debian_Testing/ /" | sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:unstable.list > /dev/null
$ sudo apt-get update
$ sudo apt-get -y upgrade
$ sudo apt-get -y install podman
Ubuntu 20.04の場合、上記の手順でインストールしても podman コマンドが下記のようにエラー
$ podman --version
podman: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found (required by podman)
podman: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.33' not found (required by podman)
podman: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found (required by podman)
/etc/apt/sources.list に
deb http://security.ubuntu.com/ubuntu jammy-security main
を追加し、新しい glibc をインストールする。
sudo apt update
sudo apt install libc6
これにより、podman コマンドでエラーが出力されなくなった。
$ podman --version
podman version 4.5.1
この状態で GPU を指定して podman コマンドでコンテナ起動を実行したところ、エラーになった。
$ podman run --rm --device nvidia.com/gpu=all --security-opt=label=disable ubuntu nvidia-smi -L
/usr/bin/crun: /lib/x86_64-linux-gnu/libsystemd.so.0: version `LIBSYSTEMD_246' not found (required by /usr/bin/crun)
ERRO[0000] Removing container 5bf936022c5c523951360e353d20471ba60cf828fbf8765c5068d7aa3216634e from runtime after creation failed
Error: OCI runtime error: crun: /usr/bin/crun: /lib/x86_64-linux-gnu/libsystemd.so.0: version `LIBSYSTEMD_246' not found (required by /usr/bin/crun)
ここまでやった段階で「Ubuntu 20.04」で作業を継続するのは筋が悪そうな感じがしてきたので、Ubuntu 22.04 でVMを作り直し。作業を再開。
Ubuntu 22.04 VM で以下のように失敗。
$ podman run --rm --device nvidia.com/gpu=all --security-opt=label=disable ubuntu nvidia-smi -L
Resolved "ubuntu" as an alias (/etc/containers/registries.conf.d/shortnames.conf)
Trying to pull docker.io/library/ubuntu:latest...
Getting image source signatures
Copying blob aece8493d397 done
Copying config e4c5895818 done
Writing manifest to image destination
Storing signatures
Error: crun: cannot stat `/lib/x86_64-linux-gnu/libEGL_nvidia.so.545.23.06`: No such file or directory: OCI runtime attempted to invoke a command that was not found
/lib/x86_64-linux-gnu/libEGL_nvidia.so.545.23.08 が代わりに存在する。。
/etc/cdi/nvidia.yaml の内容が 545.23.06 になっている。 これを書き換えてみる。→ 少し前進
$ podman run --rm --device nvidia.com/gpu=all --security-opt=label=disable ubuntu nvidia-smi -L
Error: crun: cannot stat `/run/nvidia-persistenced/socket`: No such file or directory: OCI runtime attempted to invoke a command that was not found
/run/nvidia-persistenced/socket
ファイルは /etc/cdi/nvidia.yaml の下記の部分に含まれる。
これによると、ホストの /run/nvidia-persistenced/socket
をコンテナ内の /run/nvidia-persistenced/socket
にマッピングしているように見える。
- containerPath: /run/nvidia-persistenced/socket
hostPath: /run/nvidia-persistenced/socket
options:
- ro
- nosuid
- nodev
- bind
- noexec
少なくともホスト上はそのようなファイルがない。 このファイルに関係しそうなサービスが inactive になっている。
$ systemctl status nvidia-persistenced.service
○ nvidia-persistenced.service - NVIDIA Persistence Daemon
Loaded: loaded (/lib/systemd/system/nvidia-persistenced.service; enabled; vendor preset: enabled)
Active: inactive (dead) since Wed 2023-11-15 23:38:16 UTC; 2 days ago
Main PID: 21385 (code=exited, status=0/SUCCESS)
CPU: 4.476s
Nov 15 23:38:14 gpu-ubuntu-22 systemd[1]: Stopping NVIDIA Persistence Daemon...
Nov 15 23:38:14 gpu-ubuntu-22 nvidia-persistenced[21385]: Socket closed.
Nov 15 23:38:14 gpu-ubuntu-22 nvidia-persistenced[21385]: device 0001:00:00.0 - persistence mode disabled.
Nov 15 23:38:16 gpu-ubuntu-22 nvidia-persistenced[21385]: device 0001:00:00.0 - NUMA memory offlined.
Nov 15 23:38:16 gpu-ubuntu-22 nvidia-persistenced[21385]: PID file unlocked.
Nov 15 23:38:16 gpu-ubuntu-22 nvidia-persistenced[21385]: PID file closed.
Nov 15 23:38:16 gpu-ubuntu-22 nvidia-persistenced[21385]: Shutdown (21385)
Nov 15 23:38:16 gpu-ubuntu-22 systemd[1]: nvidia-persistenced.service: Deactivated successfully.
Nov 15 23:38:16 gpu-ubuntu-22 systemd[1]: Stopped NVIDIA Persistence Daemon.
Nov 15 23:38:16 gpu-ubuntu-22 systemd[1]: nvidia-persistenced.service: Consumed 4.476s CPU time.
マシン再起動後、active になった。
$ systemctl status nvidia-persistenced.service
● nvidia-persistenced.service - NVIDIA Persistence Daemon
Loaded: loaded (/lib/systemd/system/nvidia-persistenced.service; enabled; vendor preset: enabled)
Active: active (running) since Sat 2023-11-18 10:23:44 UTC; 1min 46s ago
Process: 806 ExecStart=/usr/bin/nvidia-persistenced --verbose (code=exited, status=0/SUCCESS)
Main PID: 807 (nvidia-persiste)
Tasks: 1 (limit: 265722)
Memory: 24.5M
CPU: 2.026s
CGroup: /system.slice/nvidia-persistenced.service
└─807 /usr/bin/nvidia-persistenced --verbose
Nov 18 10:23:42 gpu-ubuntu-22 systemd[1]: Starting NVIDIA Persistence Daemon...
Nov 18 10:23:42 gpu-ubuntu-22 nvidia-persistenced[807]: Verbose syslog connection opened
Nov 18 10:23:42 gpu-ubuntu-22 nvidia-persistenced[807]: Started (807)
Nov 18 10:23:42 gpu-ubuntu-22 nvidia-persistenced[807]: device 0001:00:00.0 - registered
Nov 18 10:23:44 gpu-ubuntu-22 nvidia-persistenced[807]: device 0001:00:00.0 - persistence mode enabled.
Nov 18 10:23:44 gpu-ubuntu-22 nvidia-persistenced[807]: device 0001:00:00.0 - NUMA memory onlined.
Nov 18 10:23:44 gpu-ubuntu-22 nvidia-persistenced[807]: Local RPC services initialized
Nov 18 10:23:44 gpu-ubuntu-22 systemd[1]: Started NVIDIA Persistence Daemon.
/run/nvidia-persistenced/socket
ファイルも存在する。
$ ls /run/nvidia-persistenced/socket
/run/nvidia-persistenced/socket
podman コマンドも成功した。
$ podman run --rm --device nvidia.com/gpu=all --security-opt=label=disable ubuntu nvidia-smi -L
GPU 0: NVIDIA A100 80GB PCIe (UUID: GPU-aa1b9613-0671-1a6f-a560-3dc6cb952c77)
$ echo $?
0