kubernetes v1.23.6/Nvidia GPUと戯れる その2

[前回](https://qiita.com/yoshiono/items/4be595633d744e80ef7e)からの続きになります。

# 作業手順
以下となります。
1. 作業環境の準備
2. Nvidia CUDA Toolkit、docker、Nvidia Container Toolkit ←ココ
3. kubeadmでクラスター構築
4. helmとGPU Operator
5. IstioとMetalLB
6. Jupyterhub 

# 2. Nvidia CUDA Toolkit、docker、Nvidia Container Toolkit
- 全てのNodeでGPUを使用するコンテナを動作させることを想定しているので、これらの作業は全てのk8sノード(k8s01/02)で実施します。
    - k8sでNvidia GPUを使用するためには、Nvidia Container toolkitが必要で、そのためには、dockerとNVIDIAドライバを導入する必要があります。
    - NGC(Nvidia GPU Cloud)のコンテナイメージはGPU Operaterが前提となっており、GPU Operaterの前提は、Nvidia CUDA Toolkitとなっています。　
- 念のためにNvidia Container toolkitの[インストールガイド](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#supported-platforms)で自分の作業環境がNvidiaのSupported Platformに含まれることを確認します。
- 一連の作業手順の概要については[こちら](https://medium.com/nvidiajapan/nvidia-docker-%E3%81%A3%E3%81%A6%E4%BB%8A%E3%81%A9%E3%81%86%E3%81%AA%E3%81%A3%E3%81%A6%E3%82%8B%E3%81%AE-20-09-%E7%89%88-558fae883f44)を参考にします。結論として、作業手順は、以下です。「」は左記URLからの抜粋です。
  - ①NVIDIA ドライバのインストール
    - 「NVIDIA ドライバのオススメの方法 (だけど案外知られていない気がする方法) はエヌビディア提供の cuda-drivers パッケージを使うことです」
  - ②Docker のインストール
    - 「Docker 公式の便利スクリプトで、最新の安定版をすぐにインストールできます。」
  - ③NVIDIA Container Toolkit のインストール
    - 「各 Linux ディストリビューションでの nvidia-docker2 パッケージのインストール方法は、公式ドキュメントのインストールガイドを参照してください。」
- helmでGPU Operaterをインストールする際に、Nvidia Driverも、Nvidia Container toolkitも同時にインストールできるようですが、問題が発生した際に原因究明が複雑になるので、別々にインストールしています。

# 2.1 Nvidia CUDA Toolkit
- NVIDIA ドライバを導入するためのCUDA Toolkit(cuda-driversパッケージ)の実際のインストール手順は[こちら](https://developer.nvidia.com/cuda-downloads?target_os=Linux)です。OS、CPU、などを選択するとインストールスクリプトが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104507/a944bdd6-212e-a054-7cf8-8dd043921b29.png)
・こちらは作業結果。冗長なので適当に中略しています。
```OS: k8s01におけるcuda導入
root@k8s01:~/nvidia# 
root@k8s01:~/nvidia# wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/cuda-ubuntu2004.pin
--2022-04-29 22:13:00--  https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/cuda-ubuntu2004.pin
developer.download.nvidia.com (developer.download.nvidia.com) をDNSに問いあわせています... 152.195.19.142
developer.download.nvidia.com (developer.download.nvidia.com)|152.195.19.142|:443 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 190 [application/octet-stream]
`cuda-ubuntu2004.pin' に保存中
cuda-ubuntu2004.pin 100%[================================================================================>]     190  --.-KB/s    in 0s
2022-04-29 22:13:01 (5.36 MB/s) - `cuda-ubuntu2004.pin' へ保存完了 [190/190]
root@k8s01:~/nvidia# 
root@k8s01:~/nvidia# sudo mv cuda-ubuntu2004.pin /etc/apt/preferences.d/cuda-repository-pin-600
root@k8s01:~/nvidia# 
root@k8s01:~/nvidia# sudo apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/3bf863cc.pub
Executing: /tmp/apt-key-gpghome.WxPFNx29uc/gpg.1.sh --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/3bf863cc.pub
gpg: 鍵を'https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/3bf863cc.pub'から要求
gpg: 鍵A4B469963BF863CC: 公開鍵"cudatools <cudatools@nvidia.com>"をインポートしました
gpg: 処理数の合計: 1
gpg:               インポート: 1
root@k8s01:~/nvidia# sudo add-apt-repository "deb https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/ /"
取得:1 https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64  InRelease [1,575 B]
----------------------中略----------------------
取得:38 http://security.ubuntu.com/ubuntu focal-security/multiverse amd64 DEP-11 Metadata [2,464 B]
9,205 kB を 5秒 で取得しました (1,979 kB/s)
パッケージリストを読み込んでいます... 完了
root@k8s01:~/nvidia# 
root@k8s01:~/nvidia# sudo apt-get update
ヒット:1 http://jp.archive.ubuntu.com/ubuntu focal InRelease
ヒット:2 http://jp.archive.ubuntu.com/ubuntu focal-updates InRelease
ヒット:3 http://jp.archive.ubuntu.com/ubuntu focal-backports InRelease
ヒット:4 https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64  InRelease
ヒット:5 http://security.ubuntu.com/ubuntu focal-security InRelease
パッケージリストを読み込んでいます... 完了
root@k8s01:~/nvidia# 
root@k8s01:~/nvidia# sudo apt-get -y install cuda
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています
状態情報を読み取っています... 完了
----------------------中略----------------------
  vdpau-driver-all xserver-xorg-video-nvidia-510 zlib1g:i386
アップグレード: 0 個、新規インストール: 189 個、削除: 0 個、保留: 8 個。
2,709 MB のアーカイブを取得する必要があります。
この操作後に追加で 6,993 MB のディスク容量が消費されます。
取得:1 http://jp.archive.ubuntu.com/ubuntu focal-updates/main amd64 binutils-common amd64 2.34-6ubuntu1.3 [207 kB]
----------------------中略----------------------
取得:189 https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64  libnvidia-gl-510 510.47.03-0ubuntu1 [23.0 MB]
2,709 MB を 21分 7秒 で取得しました (2,138 kB/s)
パッケージからテンプレートを展開しています: 100%
パッケージを事前設定しています ...
以前に未選択のパッケージ binutils-common:amd64 を選択しています。
(データベースを読み込んでいます ... 現在 292524 個のファイルとディレクトリがインストールされています。)
.../000-binutils-common_2.34-6ubuntu1.3_amd64.deb を展開する準備をしています ...
binutils-common:amd64 (2.34-6ubuntu1.3) を展開しています...
----------------------中略----------------------
g++ (4:9.3.0-1ubuntu2) を設定しています ...
update-alternatives: /usr/bin/c++ (c++) を提供するために自動モードで /usr/bin/g++ を使います
build-essential (12.8ubuntu1.1) を設定しています ...
nvidia-dkms-510 (510.47.03-0ubuntu1) を設定しています ...
update-initramfs: deferring update (trigger activated)

A modprobe blacklist file has been created at /etc/modprobe.d to prevent Nouveau
from loading. This can be reverted by deleting the following file:
/etc/modprobe.d/nvidia-graphics-drivers.conf

A new initrd image has also been created. To revert, please regenerate your
initrd by running the following command after deleting the modprobe.d file:
`/usr/sbin/initramfs -u`

*****************************************************************************
*** Reboot your computer and verify that the NVIDIA graphics driver can   ***
*** be loaded.                                                            ***
*****************************************************************************

INFO:Enable nvidia
DEBUG:Parsing /usr/share/ubuntu-drivers-common/quirks/put_your_quirks_here
DEBUG:Parsing /usr/share/ubuntu-drivers-common/quirks/lenovo_thinkpad
DEBUG:Parsing /usr/share/ubuntu-drivers-common/quirks/dell_latitude
Loading new nvidia-510.47.03 DKMS files...
Building for 5.13.0-40-generic
Building for architecture x86_64
Building initial module for 5.13.0-40-generic
Done.

nvidia.ko:
Running module version sanity check.
 - Original module
   - No original module exists within this kernel
 - Installation
   - Installing to /lib/modules/5.13.0-40-generic/updates/dkms/

----------------------中略----------------------

nvidia-uvm.ko:
Running module version sanity check.
 - Original module
   - No original module exists within this kernel
 - Installation
   - Installing to /lib/modules/5.13.0-40-generic/updates/dkms/

depmod.....

DKMS: install completed.
cuda-nvcc-11-6 (11.6.124-1) を設定しています ...
----------------------中略----------------------
libxshmfence1:i386 (1.3-1) を設定しています ...
ca-certificates-java (20190405ubuntu1) を設定しています ...
head: '/etc/ssl/certs/java/cacerts' を 読み込み用に開くことが出来ません: そのようなファイルやディレクトリはありません
Adding debian:Secure_Global_CA.pem
Adding debian:DigiCert_Assured_ID_Root_G2.pem
----------------------中略----------------------
Adding debian:Amazon_Root_CA_1.pem
done.
libbsd0:i386 (0.10.0-1) を設定しています ...
----------------------中略----------------------
Updating certificates in /etc/ssl/certs...
0 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...

done.
done.
dbus (1.12.16-2ubuntu2.1) のトリガを処理しています ...
----------------------中略----------------------
initramfs-tools (0.136ubuntu6.7) のトリガを処理しています ...
update-initramfs: Generating /boot/initrd.img-5.13.0-40-generic
root@k8s01:~/nvidia# 
```

# 2.2 docker
- Docker本体の導入手順は、Dockerの[マニュアル](https://docs.docker.com/engine/install/ubuntu/)にも、Nvidiaの[マニュアル](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#docker)にも記載されています。両方ともDockerの convenience scriptによるthe latest stable release of Docker on Linuxのインストールなので、どちらの方法でも同じだと思います。
```OS:Nvidia公式マニュアルのDocker導入
curl https://get.docker.com | sh \
  && sudo systemctl --now enable docker
```
- Docker公式マニュアル
```OS:Docker公式のDocker導入
 curl -fsSL https://get.docker.com -o get-docker.sh
 sudo sh get-docker.sh
```

- 以下、Nvidiaのマニュアルに従った作業のログです。
```OS:Docker導入の出力
root@k8s01:~/nvidia# curl https://get.docker.com | sh \
>   && sudo systemctl --now enable docker
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 19100  100 19100    0     0  21058      0 --:--:-- --:--:-- --:--:-- 21035
# Executing docker install script, commit: 0221adedb4bcde0f3d18bddda023544fc56c29d1
+ sh -c apt-get update -qq >/dev/null
+ sh -c DEBIAN_FRONTEND=noninteractive apt-get install -y -qq apt-transport-https ca-certificates curl >/dev/null
+ sh -c curl -fsSL "https://download.docker.com/linux/ubuntu/gpg" | gpg --dearmor --yes -o /usr/share/keyrings/docker-archive-keyring.gpg
+ sh -c chmod a+r /usr/share/keyrings/docker-archive-keyring.gpg
+ sh -c echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu focal stable" > /etc/apt/sources.list.d/docker.list
+ sh -c apt-get update -qq >/dev/null
+ sh -c DEBIAN_FRONTEND=noninteractive apt-get install -y -qq --no-install-recommends docker-ce docker-ce-cli docker-compose-plugin docker-scan-plugin >/dev/null
+ version_gte 20.10
+ [ -z  ]
+ return 0
+ sh -c DEBIAN_FRONTEND=noninteractive apt-get install -y -qq docker-ce-rootless-extras >/dev/null
+ sh -c docker version
Client: Docker Engine - Community
 Version:           20.10.14
 API version:       1.41
 Go version:        go1.16.15
 Git commit:        a224086
 Built:             Thu Mar 24 01:48:02 2022
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.14
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.16.15
  Git commit:       87a90dc
  Built:            Thu Mar 24 01:45:53 2022
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.5.11
  GitCommit:        3df54a852345ae127d1fa3092b95168e4a88e2f8
 runc:
  Version:          1.0.3
  GitCommit:        v1.0.3-0-gf46b6ba
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

================================================================================

To run Docker as a non-privileged user, consider setting up the
Docker daemon in rootless mode for your user:

    dockerd-rootless-setuptool.sh install

Visit https://docs.docker.com/go/rootless/ to learn about rootless mode.


To run the Docker daemon as a fully privileged service, but granting non-root
users access, refer to https://docs.docker.com/go/daemon-access/

WARNING: Access to the remote API on a privileged Docker daemon is equivalent
         to root access on the host. Refer to the 'Docker daemon attack surface'
         documentation for details: https://docs.docker.com/go/attack-surface/

================================================================================

Synchronizing state of docker.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable docker
```

# 2.3 NVIDIA Container Toolkit

- NVIDIA Container Toolkitの導入手順は、Nvidia社の[マニュアル](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#installing-on-ubuntu-and-debian)に従います。
    - Nvidia container toolkitのインストールパッケージ名はnvidia-docker2であることがわかります。

```OS: コマンド
$ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \
      && 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/$distribution/libnvidia-container.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-docker2
$ sudo systemctl restart docker
```

- 以下、実際の作業結果です。
    - Nvidia CUDA Toolkit導入後、RebootしないとNvidiaドライバーは正常動作しません。これまでの作業で一度もRebootしていないので、nvidia-smiは失敗しています。reboot後、成功しています。
```OS:Nvidia Container Toolkitの導入
root@k8s01:~/nvidia# distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \
>       && 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/$distribution/libnvidia-container.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
deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://nvidia.github.io/libnvidia-container/stable/ubuntu18.04/$(ARCH) /
#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://nvidia.github.io/libnvidia-container/experimental/ubuntu18.04/$(ARCH) /
root@k8s01:~/nvidia# 
root@k8s01:~/nvidia# sudo apt-get update
ヒット:1 http://jp.archive.ubuntu.com/ubuntu focal InRelease
----------------------中略----------------------
ヒット:8 https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64  InRelease
20.2 kB を 2秒 で取得しました (12.5 kB/s)
パッケージリストを読み込んでいます... 完了
root@k8s01:~/nvidia# sudo apt-get install -y nvidia-docker2
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています
状態情報を読み取っています... 完了
以下のパッケージが自動でインストールされましたが、もう必要とされていません:
  libfwupdplugin1 linux-headers-5.13.0-30-generic linux-headers-5.13.0-35-generic linux-headers-5.13.0-37-generic linux-hwe-----------------------中略----------------------
以下のパッケージが新たにインストールされます:
  libnvidia-container-tools libnvidia-container1 nvidia-container-toolkit nvidia-docker2
アップグレード: 0 個、新規インストール: 4 個、削除: 0 個、保留: 7 個。
1,934 kB のアーカイブを取得する必要があります。
この操作後に追加で 7,730 kB のディスク容量が消費されます。
取得:1 https://nvidia.github.io/libnvidia-container/stable/ubuntu18.04/amd64  libnvidia-container1 1.9.0-1 [926 kB]
----------------------中略----------------------
取得:4 https://nvidia.github.io/libnvidia-container/stable/ubuntu18.04/amd64  nvidia-docker2 2.10.0-1 [5,532 B]
1,934 kB を 1秒 で取得しました (1,797 kB/s)
以前に未選択のパッケージ libnvidia-container1:amd64 を選択しています。
(データベースを読み込んでいます ... 現在 304964 個のファイルとディレクトリがインストールされています。)
----------------------中略----------------------
libc-bin (2.31-0ubuntu9.7) のトリガを処理しています ...
root@k8s01:~/nvidia# 
root@k8s01:~/nvidia# sudo systemctl restart docker
root@k8s01:~/nvidia# 
root@k8s01:~/nvidia# sudo docker run --rm --gpus all nvidia/cuda:11.0-base nvidia-smi
Unable to find image 'nvidia/cuda:11.0-base' locally
11.0-base: Pulling from nvidia/cuda
54ee1f796a1e: Pull complete
----------------------中略----------------------
155bc0332b0a: Pull complete
Digest: sha256:774ca3d612de15213102c2dbbba55df44dc5cf9870ca2be6c6e9c627fa63d67a
Status: Downloaded newer image for nvidia/cuda:11.0-base
docker: Error response from daemon: failed to create shim: OCI runtime create failed: container_linux.go:380: starting container process caused: process_linux.go:545: container init caused: Running hook #0:: error running hook: exit status 1, stdout: , stderr: nvidia-container-cli: initialization error: nvml error: driver not loaded: unknown.
root@k8s01:~/nvidia# 
root@k8s01:~/nvidia# reboot
```

・再起動後の出力結果です。無事、成功しています。k8s01でも同様です。
```OS:Containter Toolkitのreboot後の動作確認
Welcome to Ubuntu 20.04.4 LTS (GNU/Linux 5.13.0-40-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

7のアップデートはすぐに適用されます。
6 of these updates are standard security updates.
これらの追加アップデートを確認するには次を実行してください: apt list --upgradabl                                                                                                                                                             e

Your Hardware Enablement Stack (HWE) is supported until April 2025.


Last login: Fri Apr 29 22:14:20 2022 from 172.31.35.113
root@k8s02:~#
root@k8s02:~# sudo docker run --rm --gpus all nvidia/cuda:11.0-base nvidia-smi
Fri Apr 29 13:54:28 2022
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 510.47.03    Driver Version: 510.47.03    CUDA Version: 11.6     |
|-------------------------------+----------------------+----------------------+
| 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  Tesla M60           On   | 00000000:0B:00.0 Off |                  Off |
| N/A   34C    P8    14W / 150W |      3MiB /  8192MiB |      0%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+
|   1  Tesla M60           On   | 00000000:13:00.0 Off |                  Off |
| N/A   22C    P8    14W / 150W |      3MiB /  8192MiB |      0%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|    0   N/A  N/A      1215      G                                       3MiB |
|    1   N/A  N/A      1215      G                                       3MiB |
+-----------------------------------------------------------------------------+
root@k8s02:~#
```

次回に続きます。