仮想化通信

日本仮想化技術株式会社の公式エンジニアブログ

Jujuで構築するKubernetesでGPUを使うには

JujuでKubernetesをデプロイする方法については以前、次のように書きました。

tech.virtualtech.jp

では、今回は「Jujuで構築するKubernetesでGPUを使うには」と言う話を書きたいと思います。 と言っても割と簡単で、Kubernetes WorkerノードにNVIDIAのGPUを挿して、juju deploy kubernetesでドーンで終了です。

JujuでGPU対応Kubernetes環境を作る

前回の記事でも書いた通り、Jujuはアプリケーション単体の設定などが定義されているCharm、それを一つにまとめたBundleがあります。Kubernetes WorkerのCharmの設定一覧を見ると簡単に導入できる理由がわかると思います。

現在のKubernetes Workerのリビジョンは106が安定版なので、その設定は次のURLで確認できます(2018年3月28日現在)。

https://api.jujucharms.com/charmstore/v5/~containers/kubernetes-worker-106/archive/config.yaml

該当の部分を抜き出すとこれです。install-cudaのパラメーターがデフォルトでtrueになっています。このため、Kubernetes WorkerのホストにNVIDIAのGPUカードが接続されていると必要なGPUドライバーやCUDAなどがインストールされるわけです。

  "install-cuda":
    "type": "boolean"
    "default": !!bool "true"
    "description": |
      Install the CUDA binaries if capable hardware is present.

さて、DockerコンテナーでGPUを使うと言うと「NVIDIA Docker」を想像すると思います。実はKubernetesでGPUを取り扱う場合、NVIDIA Dockerは必須ではありません。JujuでKubernetesの環境を作った場合はGPU DriverとCUDAがインストールされるだけで、NVIDIA Dockerは自動的にインストールはされません。

アプリケーションの要件でNVIDIA Dockerが必要な場合はGPUが載ったKubernetes Workerノードにログインしてインストールする必要があります。juju sshコマンドでログインして、セットアップします。

github.com

GitHubサイトを確認すると、NVIDIA Dockerにはバージョン1と2が存在するのがわかります。バージョン1は開発終了しており、新しく導入するのであればバージョン2の導入をおススメします。

ところがQuick Startに従ってインストールしようとすると「docker-ceがインストールされていないので無理」といわれて詰みます。

% sudo apt-get install -y nvidia-docker2

JujuでKubernetes Workerを構築した場合、Ubuntuアーカイブのdocker.ioパッケージがインストールされます。nvidia-docker2をインストールするときに導入済み済みのDockerバージョンを指定するとうまくいきます。方法は次のページに書かれています。

github.com

まず、公開されているnvidia-docker2とnvidia-container-runtimeのバージョンを確認します。現在はnvidia-docker2はバージョン2.0.3、nvidia-container-runtimeは2.0.0が最新版のようです。

出力結果を見ればわかるように、Dockerのバージョンによって導入すべきパッケージが分かれていることがわかると思います。

% apt list -a nvidia-docker2 nvidia-container-runtime
Listing... Done
nvidia-container-runtime/xenial 2.0.0+docker18.03.0-1 amd64
nvidia-container-runtime/xenial 2.0.0+docker17.12.1-1 amd64
nvidia-container-runtime/xenial 2.0.0+docker17.12.0-1 amd64
nvidia-container-runtime/xenial 2.0.0+docker17.09.1-1 amd64
nvidia-container-runtime/xenial 2.0.0+docker17.09.0-1 amd64
nvidia-container-runtime/xenial 2.0.0+docker17.06.2-1 amd64
nvidia-container-runtime/xenial 2.0.0+docker17.03.2-1 amd64
nvidia-container-runtime/xenial 2.0.0+docker1.13.1-1 amd64
nvidia-container-runtime/xenial 2.0.0+docker1.12.6-1 amd64
...
nvidia-docker2/xenial 2.0.3+docker18.03.0-1 all
nvidia-docker2/xenial 2.0.3+docker17.12.1-1 all
nvidia-docker2/xenial 2.0.3+docker17.12.0-1 all
nvidia-docker2/xenial 2.0.3+docker17.09.1-1 all
nvidia-docker2/xenial 2.0.3+docker17.09.0-1 all
nvidia-docker2/xenial 2.0.3+docker17.06.2-1 all
nvidia-docker2/xenial 2.0.3+docker17.03.2-1 all
nvidia-docker2/xenial 2.0.3+docker1.13.1-1 all 
nvidia-docker2/xenial 2.0.3+docker1.12.6-1 all

Ubuntu 16.04.4でインストールされるdocker.ioは次のように実行すると1.13.1であることがわかります。

% apt list -a docker.io
Listing... Done
docker.io/xenial-updates,now 1.13.1-0ubuntu1~16.04.2 amd64 [installed]
docker.io/xenial 1.10.3-0ubuntu6 amd64

というわけで、次のようにバージョンを指定してインストールすれば良いわけです。

% sudo apt install -y nvidia-docker2=2.0.3+docker1.13.1-1 nvidia-container-runtime=2.0.0+docker1.13.1-1

ついでに関連するパッケージのバージョンを固定しておくと良いでしょう。

% sudo apt-mark hold docker.io nvidia-docker2 nvidia-container-runtime

GPU Podを作ろう

それでは早速、GPUが使えるPodを作ってみます。KubernetesのGPU Scheduleについては次のページにまとまっています。

kubernetes.io

ここに書かれているサンプルファイルをちょっと書き換えて、次のようなYAMLを書いてみます。

apiVersion: v1
kind: Pod
metadata:
  name: testpod
spec:
  restartPolicy: OnFailure
  containers:
    - name: nvidia-cuda
      image: nvidia/cuda:9.1-base
      tty: true
      resources:
        limits:
          alpha.kubernetes.io/nvidia-gpu: 1 # requesting 1 GPU
      volumeMounts:
        - name: bin
          mountPath: /usr/local/nvidia/bin
        - name: lib 
          mountPath: /usr/local/nvidia/lib
  volumes:
      - hostPath:
          path: /usr/lib/nvidia-390/bin
        name: bin
      - hostPath:
          path: /usr/lib/nvidia-390
        name: lib

volumesではKubernetes Workerホストにインストール済みのNVIDIAツールの実行ファイルと関連ライブラリーを指定しています(当然ながらバージョンを指定していますので、バージョンが変わればここの記述も変える必要があります。)。これを上のcontainersのvolumeMountsでマウントしています。

このYAMLをfirst-gpupod.ymlという名前で保存して次のように実行しましょう。 GPU Podが作成できます。

% kubectl create -f first-gpupod.yml
% kubectl get pod testpod
NAME      READY     STATUS    RESTARTS   AGE
testpod   1/1       Running   0          2m

% kubectl exec -it testpod nvidia-smi
Wed Mar 28 01:33:02 2018
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 390.30                 Driver Version: 390.30                    |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce GTX 1080    Off  | 00000000:01:00.0 Off |                  N/A |
| 27%   29C    P8    11W / 180W |      0MiB /  8119MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+

作成したPodは次のコマンドで削除できます。

% kubectl delete -f first-gpupod.yml

こんな形です。本日は以上です。 次回はChainerでGPUを使ってなにかやってみたいと思います。