Docker Enterprise の Kubernetes で NVIDIA GPUノードを利用する。 #docker #mirantis #kubernetes #k8s
この記事は1年以上前に投稿されました。情報が古い可能性がありますので、ご注意ください。
本ブログは Mirantis社のblog記事「NVIDIA GPU Nodes for Docker Enterprise Kubernetes」の翻訳記事です。
NVIDIA GPUサポートで、機械学習、データ解析、メディア処理など複雑なワークロードを加速します。
Docker Enterprise 3.1に含まれている Kubernetes 1.17を利用することで、GPUに対応した Workerノードを Kubernetesクラスタに簡単に追加して利用できます。簡単な手順で GPU の設定が可能です。
一度設定をしてしまえば、 設定したノードを Docker Kubernetes Service が自動的に GPU対応ノードとして認識し、アプリケーションは deployment の Tag で指定する事によりGPU対応ノードを利用します。
この機能を利用することでデータセンター(およびデスクトップ)用の NVIDIA GPU ボードの普及や、パブリッククラウドプロバイダによる GPU ハードウェアを搭載した仮想マシンのオプションの拡大に対応できます。
このような昨今のGPU の計算能力の入手し易さに合わせて、コンテナレベルでの強力なGPUサポート(例えばコンテナ化された TensorFlow など)の追加によって、AI や、機械学習、データ解析からゲームまで、今後増加する新しいビジネスモデルに対応したアプリケーションの構築を可能にしています。
一方、Kubernetes を利用することにより、比較的高価なGPUリソースの共有が可能になります。また、必要に応じてクラウドベースの GPUノードを構成して利用することも容易になります。そのため高額になりがちな GPUノードの費用を削減できます。
では、さっそく始めましょう。
GPU利用のポイント
現在、GPU機能はLinuxのみでサポートされています。しかし、それには互換性のあるNVIDIAハードウェアも幅広く含まれています。考慮すべきことは、実行しようとしているアプリケーションが手元のハードウェアを利用できるかどうかということです。ほとんどのアプリケーション基板(Tensorflow Dockerコンテナなど)は、NVIDIAデータセンターGPUアーキテクチャにアクセスできます。
しかし、コンシューマ側のデプロイを目的とした分散コンピューティングプロジェクト(例えば、K8s-fah のようなコミュニティの貢献のおかげで Kubernetes 上にもデプロイ可能な Folding at Home など)は、Amazon G2 や P3、その他の GPU を搭載したインスタンスタイプが利用している Tesla M60 や V100 などのGPU ではうまく動作しないかもしれません。問題は技術的な互換性ではありません。FAHワークロードが家庭用のグラフィックカードで実行するように構成されているため、システムが優先的にこれらのデバイスにワークユニットを配布してしまい、ボランティアで提供されたクラウドGPUがアイドル状態になってしまう可能性があるからです。
これらすべてのことは、ワークロードが実行されるGPUハードウェアに着目して、慎重にワークロードを準備することが重要であることを意味します。
正しいベースイメージを選択しなければなりませんし、実行させるコンテナにインストールされたワークロードが物理GPUへアクセスできるようになる前に、DockerfileにNVIDIA Container Toolkitやその他の設定を追加する必要があります。
TensorFlow Dockerのワークフローは、GPUサポートなしのコンテナでアプリをビルドしてデバッグし、その後、GPUサポートに変更して本番環境にデプロイできるという点で優れています。一般的に、GPUに依存したアプリケーションをコンテナ化することには大きなメリットがあります。実際、コンテナ化することにより外部依存性を最小限に抑えることができるため、試験環境での結果の再現性を高めるのにも役立ちます。
Docker Kubernetes用のGPUノードを設定する
Docker Enterprise KubernetesクラスタでGPUノードを利用するための準備は、通常のWorkerノードとしてクラスタに追加するようにノードを設定することから始まります。その後、ノードをそのまま利用するか、GPUドライバをインストールしてGPUノードとして利用するのかを選択します。
これから、Ubuntu Linux 18.04をインストールしたWorkerノードをGPUノードとしてDocker Enterpriseクラスタに追加するための設定手順を紹介します。他のOSやバージョンのレシピはドキュメントを参照してください。
前提として Docker Enterprise EngineとUCPをインストールする前にホストをアップデートしてください(最新のカーネルが必須です)。次のステップは、依存関係のあるパッケージを確認することです。Ubuntu 18.04の場合は、pkg-config(NVIDIAがビルドやその他のコンポーネントを見つけるために使用するアプリケーション)をインストールする必要があります。
sudo apt install pkg-config
次に、ビルドツールとlinux-headersをインストールします。
sudo apt-get install -y gcc make curl linux-headers-$(uname -r)
次に、i2c_core と ipmi_msghandler カーネルモジュールが適切に配置されていることを確認してください。これらはCPUとGPU間の通信を管理するために必要になります。
sudo modprobe -a i2c_core ipmi_msghandler
そして、再起動時にモジュールをリロードするように設定します。
echo -e "i2c_core\nipmi_msghandler" | sudo tee /etc/modules-load.d/nvidia.conf
そして、以降の作業で利用するコマンドのプレフィックスを設定し、適切な場所にNVIDIAドライバのディレクトリを作成し、NVIDIAの設定ファイルを更新し、ライブラリへのリンクを更新します。
NVIDIA_OPENGL_PREFIX=/opt/kubernetes/nvidia sudo mkdir -p $NVIDIA_OPENGL_PREFIX/lib echo "${NVIDIA_OPENGL_PREFIX}/lib" | sudo tee /etc/ld.so.conf.d/nvidia.conf sudo ldconfig
次に、現在のドライバのバージョンを設定します。
NVIDIA_DRIVER_VERSION=440.59
curlを使ってドライバの実行ファイルをダウンロードして、nvidia.runとして保存します。
curl -LSf https://us.download.nvidia.com/XFree86/Linux-x86_64/${NVIDIA_DRIVER_VERSION}/NVIDIA-Linux-x86_64-${NVIDIA_DRIVER_VERSION}.run -o nvidia.run
そして、ドライバをインストールします。
sudo sh nvidia.run --opengl-prefix="${NVIDIA_OPENGL_PREFIX}"
ドライバアプリは、インストールを完了する前に次の様ないくつかの質問をします。
NVIDIA 32ビットドライバをインストールしますか?(答えはおそらくノーです)
変更されたライブラリを解決するツール ( Xorg ) を持っていないので、イントールに失敗した場合は Xorg の dev ツールをインストールする必要があると警告が出るかもしれません。(答えは OK です。これについては心配しないでください。)
再起動時にNVIDIA Xドライバをロードするように設定を更新しますか?(答えはおそらくYESです)
ライブラリをインストールしたら、専用のデバイスファイルを作成する NVIDIA カーネルモジュールをロードする設定ファイルを作成します。
sudo tee /etc/systemd/system/nvidia-modprobe.service << END [Unit] Description=NVIDIA modprobe [Service] Type=oneshot RemainAfterExit=yes ExecStart=/usr/bin/nvidia-modprobe -c0 -u [Install] WantedBy=multi-user.target END
その後、モジュールを有効にして起動します。
sudo systemctl enable nvidia-modprobe sudo systemctl start nvidia-modprobe
最後に、nvidia-persistencedデーモンサービスを設定します。
sudo tee /etc/systemd/system/nvidia-persistenced.service << END [Unit] Description=NVIDIA Persistence Daemon Wants=syslog.target [Service] Type=forking PIDFile=/var/run/nvidia-persistenced/nvidia-persistenced.pid Restart=always ExecStart=/usr/bin/nvidia-persistenced --verbose ExecStopPost=/bin/rm -rf /var/run/nvidia-persistenced [Install] WantedBy=multi-user.target END
有効化して起動します。
sudo systemctl enable nvidia-persistenced sudo systemctl start nvidia-persistenced
この時点でまだ対象のGPUノードをDocker Enterprise に追加出来ていない場合には、UCPのUIからクラスタにノードを追加するために必要な「docker join」コマンドを取得し、これをGPUノードのコマンドラインにコピーして、GPUノードを追加してください。
Docker Entepriseのオーケストレーション設定により、GPUノードがKubernetesワーカーとして追加されます。すでに KubernetesのGPUデバイスプラグインが組み込まれているので、追加ノードがGPUノードであることをDashboard上で確認出来ます。
Test Deployment
テスト用のイメージをDocker Hubに登録してあります。これを利用してkubectlでテストデプロイを実行します。以下をコマンドラインに直接貼り付けるか、YAML部分をファイルとして保存して編集後に apply してください。イメージは、プラットフォームにアクセスして利用可能なGPUハードウェアの情報をログに記録するプログラムが含まれています。
kubectl apply -f- <<EOF apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: run: gpu-test name: gpu-test spec: replicas: 1 selector: matchLabels: run: gpu-test template: metadata: labels: run: gpu-test spec: containers: - command: - sh - -c - "deviceQuery && sleep infinity" image: mirantis/gpu-example:cuda-10.2 name: gpu-test resources: limits: nvidia.com/gpu: "1" EOF
クラスタに複数の GPU または GPU ノードが利用可能な場合は、replicaの数を変更して Pod を増やすことができます。Pod は、記載された replica 数に応じて GPU ノードにのみスケジューリングされます。サポートする GPU 容量を超える数の Pod をスケジュールしようとすると、"Insufficient nvidia.com/gpu. "という注釈付きの FailedScheduling エラーが発生します。
Pod とその状態をリストアップします。
$ kubectl get pods NAME READY STATUS RESTARTS AGE gpu-test-747d746885-hpv74 1/1 Running 0 14m
次のコマンドでログを表示します。
kubectl logs < Podの名前 >
最後に次のコマンドを入力して、デプロイメントを削除します。
kubectl delete deployment gpu-test
今後の予定
これで GPU の準備が整いました。現在、機械学習ツールを試しています。近々、従来型 (Xeonなど) の (v)CPU 対 GPU での比較用のトレーニング演習のベンチマークの結果をお伝えできる予定です。
Docker Enterprise 3.1 の新機能について知りたい場合は、Docker Enterprise 3.1 正式リリース! もご覧ください。