このエントリーをはてなブックマークに追加

AWS上のkubernetesでGPUを使う

ということで、今日は、AWS上のk8sでGPUを使ってみましょう。

事前に用意するもの

  1. kubernetes cluster (1.9.3で確認)
  2. kops (1.8.1で確認)

AMIの作成

099720109477/ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-server-20180222 (ami-06d9a360)のイメージを使ってEC2を用意します。イメージを作るだけなのでt2.microでもいいのですが、確認のためにp2.xlargeインスタンスを用意しましょう。あ、ストレージは16GBぐらいにしておくと安全です。8GBでは足りません。

ssh ubuntu@<ip address>して、以下のスクリプトを実行します。手作業で実行したのをscript形式にしたので、そのまま実行したらこけるかもしれませんので、適宜修正してください。

注意点は dockerのバージョンです。docker-ceではk8sが対応しておらずkopsがnodeの設定をできないので、docker-engine 1.13.1を指定します。また、nvidia-docker2のバージョン指定も気をつけます。install時に"nvidia-docker2=2.0.3+docker1.13.1-1"とdockerのバージョンも含めて指定してあげる必要があります。

とはいえ、そろそろdocker-ceでも動くようにはなるので、近いうちにバージョンの問題はなくなる可能性が高いです。

#!/usr/bin/bash

sudo apt-get update && sudo apt-get install -y build-essential

# install NVIDIA driver
wget http://jp.download.nvidia.com/XFree86/Linux-x86_64/390.25/NVIDIA-Linux-x86_64-390.25.run
sudo sh NVIDIA-Linux-x86_64-390.25.run --silent

# install CUDA toolkit
wget https://developer.nvidia.com/compute/cuda/9.1/Prod/local_installers/cuda_9.1.85_387.26_linux
sudo sh cuda_9.1.85_387.26_linux --silent --toolkit --no-man-page


# install nvidia-docker and docker-engine 1.13.1
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/debian9/amd64/nvidia-docker.list | \
  sudo tee /etc/apt/sources.list.d/nvidia-docker.list

sudo apt-get update && sudo apt-get install -y \
     apt-transport-https \
     ca-certificates \
     curl \
     gnupg2 \
     software-properties-common

echo 'deb https://apt.dockerproject.org/repo ubuntu-xenial main' | sudo tee /etc/apt/sources.list.d/docker.list

sudo apt-get update
sudo apt-get install -y "docker-engine=1.13.1-0~ubuntu-xenial"
sudo apt-get install -y "nvidia-docker2=2.0.3+docker1.13.1-1" "nvidia-container-runtime=2.0.0+docker1.13.1-1"

# add `-s=overlay2` to docker
sudo sed -i -e 's/fd:\/\//fd:\/\/ -s=overlay2/g' /lib/systemd/system/docker.service

# set default docker runtime to default using nvidia runtime
sudo tee /etc/docker/daemon.json <<EOF
{
    "default-runtime": "nvidia",
    "runtimes": {
        "nvidia": {
            "path": "/usr/bin/nvidia-container-runtime",
            "runtimeArgs": []
        }
    }
}
EOF

# restart
sudo pkill -SIGHUP dockerd
sudo systemctl restart docker.service

最後に

sudo docker run --rm nvidia/cuda nvidia-smi

してnvidia-dockerではなく、dockerコマンドでnvidia-smiが動くかどうか確認しましょう。確認がすんだら、docker pullされたnvidia/cudaのdocker イメージを消してAMIを作成しておきます。

GPUインスタンスの立ち上げ

準備したAMIをkops用のspec.imageに記述しつつ、kops用のresourceファイルを用意します。注意して欲しいところはspec.kubelet.featureGates.DevicePluginsを指定することです。これがないと、後のDeviceDriverがGPUを認識してくれません。

(念の為書いておくと、kops get ig nodes -oyamlすると、現在のnode設定をyamlで書き出してくれるのでそれを修正していきます)

apiVersion: kops/v1alpha2
kind: InstanceGroup
metadata:
  creationTimestamp: null
  labels:
    kops.k8s.io/cluster: gpu.alpaca.k8s.local
  name: gpu
spec:
  image: ami-1234569
  kubelet:
    featureGates:
      DevicePlugins: "true"
  machineType: p2.xlarge
  maxPrice: "1.0"
  maxSize: 1
  minSize: 1
  nodeLabels:
    kops.k8s.io/instancegroup: gpu
  role: Node
  subnets:
  - ap-northeast-1a

その後、

% kops create -f stg-gpu-nodes.yml
% kops update cluster gpu.alpaca.k8s.local --yes

でGPUインスタンスが立ち上がります。

DevicePluginのインストール

さて、次にKubernetesからGPUを扱うようにするために、Device Pluginを入れます。

kubectl create -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v1.9/nvidia-device-plugin.yml

daemon set として各nodeにインストールされます。

kubectl get nodes -oyaml | grep gpuとすると、nvidia.com/gpu: "1"と出てきたら成功です。(順番は関係ないとは思いますが、もしかしたら、再度gpu-nodeを作りなおしたほうがいいのかもしれません)

使ってみる

適当なpodを立ち上げてnvidia-smiを実行してみます。

apiVersion: v1
kind: Pod
metadata:
  name: gpu-pod
  namespace: stg
spec:
  nodeSelector:
    kops.k8s.io/instancegroup: gpu
  containers:
    - name: cuda-container
      image: nvidia/cuda
      resources:
        limits:
          nvidia.com/gpu: 1 # requesting 1 GPUs
      command:
        - "nvidia-smi"

無事実行できれば成功です。

参考文献