Kubernetes-nvidia-docker 2によるGPUリソースの使用


目次
一.Nvidia-docker
二.Nvidia-docker2
1.nvidia-docker 2のインストール
2.nvidia-gpu-pluginインストール
3.コンテナでTensorFlowを実行する

一.Nvidia-docker


nvidia-dockerはGPUが使えるdockerで、Dockerに基づいてパッケージ化されています
これまで、nvidia-dockerが廃止された2つの大きな安定バージョンが発表されていますが、今回は簡単に紹介します.
nvidia-dockerはDockerのパッケージとして独立したdaemonを実行する必要がありますが、実際にはVolume Pluginであり、nvidia-dockerは専用のVolume Driverを実現しています.このDriverでVolumeを作成すると、宿主の駆動バージョンに自動的に対応し、透過が必要なファイルを収集してディレクトリの下に統一し、直接このディレクトリをコンテナに転送すればいいです.
yum install nvidia-docker-1.0.1-1.x86_64.rpm

systemctl enable nvidia-docker

systemctl start nvidia-docker

#   384.90          
docker volume create --name=nvidia_driver_384.90 -d nvidia-docker

ボリュームを作成したらdocker volume inspect nvidia_driver_384.90は、/var/lib/nvidia-docker/volumes/nvidia_に転送する必要があるファイルが収集されていることを発見します.driver/384.90では、多くのシンボルリンクとハードリンクがあります.最後にコンテナを作成するときは、次のdocker runコマンドラインパラメータを使用すると、駆動、CUDAをコンテナに透過することができます.
--volume=nvidia_driver_384.90:/usr/local/nvidia:ro --volume=/usr/local/cuda/lib64:/usr/local/cuda/lib64:ro -e LD_LIBRARY_PATH=/usr/local/cuda/lib64/:/usr/local/nvidia/lib:/usr/local/nvidia/lib64

二.Nvidia-docker2


nvidia-docker 2はruntimeであり、dockerとの互換性が向上します.

1.nvidia-docker 2のインストール


nvidia-docker 2はdockerのバージョンに依存しており、私の環境は以下の通りです.
[root@k8s-node1 ~]# uname -a
Linux k8s-node1 4.17.6-1.el7.elrepo.x86_64 #1 SMP Wed Jul 11 17:24:30 EDT 2018 x86_64 x86_64 x86_64 GNU/Linux

[root@k8s-node1 ~]# cat /etc/redhat-release 
CentOS Linux release 7.4.1708 (Core)

[root@k8s-node1 ~]# docker version
Client:
 Version:           18.06.1-ce
 API version:       1.38
 Go version:        go1.10.3
 Git commit:        e68fc7a
 Built:             Tue Aug 21 17:23:03 2018
 OS/Arch:           linux/amd64
 Experimental:      false

Server:
 Engine:
  Version:          18.06.1-ce
  API version:      1.38 (minimum version 1.12)
  Go version:       go1.10.3
  Git commit:       e68fc7a
  Built:            Tue Aug 21 17:25:29 2018
  OS/Arch:          linux/amd64
  Experimental:     false
# Add the package repositories
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | \
  sudo tee /etc/yum.repos.d/nvidia-docker.repo

# Install nvidia-docker2 and reload the Docker daemon configuration
sudo yum install -y nvidia-docker2

インストール後、新しいDocker Runtimeを構成する必要があります.また、デフォルトのRuntimeをnvidiaに設定する必要があります.
[root@k8s-node1 ~]# cat /etc/docker/daemon.json 
{
    "default-runtime": "nvidia",
    "runtimes": {
        "nvidia": {
            "path": "/usr/bin/nvidia-container-runtime",
            "runtimeArgs": []
        }
    }
}

その後dockerを再起動
systemctl restart docker

docker情報の表示
[root@k8s-node1 ~]# docker info
Containers: 49
 Running: 47
 Paused: 0
 Stopped: 2
Images: 84
Server Version: 18.06.1-ce
Storage Driver: overlay2
 Backing Filesystem: xfs
 Supports d_type: true
 Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: bridge host macvlan null overlay
 Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog
Swarm: inactive
Runtimes: nvidia runc
Default Runtime: nvidia #   runtime   nvidia
...
...

ミラーを使用したテスト
# Test nvidia-smi with the latest official CUDA image
docker run --runtime=nvidia --rm nvidia/cuda:9.0-base nvidia-smi

2.nvidia-gpu-pluginインストール


GPUリソースをkubernetesでスケジューリングするにはnvidia-gpu-pluginをインストールする必要があります.daemonsetsで導入できます.
[root@k8s-node1 ~]# cat nvidia-gpu-plugin.yaml 
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: nvidia-gpu-plugin
  namespace: kube-system
  labels:
    k8s-app: nvidia-gpu-plugin
    version: "1.10"
spec:
  selector:
    matchLabels:
      k8s-app: nvidia-gpu-plugin
      version: "1.10"
  template:
    metadata:
      # Mark this pod as a critical add-on; when enabled, the critical add-on scheduler
      # reserves resources for critical add-on pods so that they can be rescheduled after
      # a failure.  This annotation works in tandem with the toleration below.
      annotations:
        scheduler.alpha.kubernetes.io/critical-pod: ""
      labels:
        k8s-app: nvidia-gpu-plugin
        version: "1.10"
    spec:
      tolerations:
      # Allow this pod to be rescheduled while the node is in "critical add-ons only" mode.
      # This, along with the annotation above marks this pod as a critical add-on.
      - key: CriticalAddonsOnly
        operator: Exists
      containers:
      - image: nvidia-gpu-plugin:1.10
        name: nvidia-gpu-plugin
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop: ["ALL"]
        volumeMounts:
          - name: device-plugin
            mountPath: /var/lib/kubelet/device-plugins
      volumes:
        - name: device-plugin
          hostPath:
            path: /var/lib/kubelet/device-plugins

リソースの表示
[root@k8s-node1 ~]# kubectl --namespace=kube-system get daemonsets nvidia-gpu-plugin 
NAME                DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
nvidia-gpu-plugin   2         2         2       2            2                     6d17h
[root@k8s-node1 ~]# 
[root@k8s-node1 ~]# 
[root@k8s-node1 ~]# kubectl --namespace=kube-system get pod | grep nvidia-gpu-plugin
nvidia-gpu-plugin-vv5zh                               1/1     Running   0          6d17h
nvidia-gpu-plugin-z8f8c                               1/1     Running   0          6d17h

nvidia-gpu-plugin作成後、k 8 s nodeノードを表示すると、gpuリソースが提供されていることがわかります.
[root@k8s-node1 ~]# kubectl get node k8s-node1 -ojson | jq '.status.allocatable'
{
  "cpu": "32",
  "ephemeral-storage": "680077411227",
  "hugepages-1Gi": "0",
  "hugepages-2Mi": "0",
  "memory": "65762860Ki",
  "nvidia.com/gpu": "2", #    2 gpu      
  "pods": "110"
}

GPUリソースを含むPodの作成
[root@k8s-node1 example]# cat nginx-pod.yaml 
apiVersion: v1
kind: Pod
metadata:
  labels:
    k8s-app: nginx-pod
  name: nginx-pod
spec:
  containers:
  - image: nginx:latest
    imagePullPolicy: Always
    name: nginx
    ports:
    - containerPort: 80
      name: nginx
      protocol: TCP
    resources:
      limits:
        nvidia.com/gpu: "1"

[root@k8s-node1 example]# kubectl create -f nginx-pod.yaml 
pod/nginx-pod created

コンテナに入ってみるとnginx podにGPUリソースが割り当てられていることがわかります
[root@k8s-node1 example]# kubectl exec -it nginx-pod bash
root@nginx-pod:/# nvidia-smi 
Tue May 28 02:56:52 2019       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 410.57                 Driver Version: 410.57                    |
|-------------------------------+----------------------+----------------------+
| 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 108...  Off  | 00000000:04:00.0 Off |                  N/A |
| 25%   27C    P8     8W / 250W |      0MiB / 11178MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+

3.コンテナでTensorFlowを実行する


コンテナミラー作成
GPUのtensorflowは、指定されたモデルでのコンパイル性能が最適である必要があります.コンパイル方法の参考:https://blog.csdn.net/iov_aaron/article/details/90268597
私のtensorflowは1.12バージョンで、ミラーはnvidiaベースのnvidia/cuda:10.0-cudn 7-runtime-centos 7ミラーです(https://gitlab.com/nvidia/cuda/tree/centos7/10.0)
[root@aidevops tensorflow-gpu-1.12.0]# cat Dockerfile 
FROM nvidia/cuda:10.0-cudnn7-runtime-centos7
USER root
WORKDIR /root

COPY scripts /root/scripts
COPY sshconfig/* /etc/ssh/
COPY jupyterconfig /root/.jupyter

## SSH
RUN yum install -y openssh openssh-clients openssh-server && \
    ssh-keygen -t rsa -P '' -f /etc/ssh/ssh_host_rsa_key && \
    ssh-keygen -t ecdsa -P '' -f /etc/ssh/ssh_host_ecdsa_key && \
    ssh-keygen -t ed25519 -P '' -f /etc/ssh/ssh_host_ed25519_key

# OpenCV
RUN yum install opencv-devel -y

# User Tools
RUN yum install vim python-imaging -y

# Jupyter
RUN yum install -y python-setuptools gcc python-devel && \
    easy_install pip==9.0.1 && \
    pip install tornado==4.5.3 graphviz==0.8.1 requests==2.18.4 && \
    pip install notebook-5.2.2-py2.py3-none-any.whl

# Tensorflow
RUN pip install tensorflow-1.12.0-cp27-cp27mu-linux_x86_64.whl

# Clean
RUN yum clean all && rm -rf /var/cache/yum*

CMD ["/root/scripts/start.sh"]

ミラー作成後、このミラー起動コンテナを使用してtensorflowアプリケーションを正常に実行
 
問題:
Tensorflowを使用したトレーニング・タイムズエラー:kernel version 418.18 does not match DSO version 410.58.0
nvidia/cuda:10.0-cudnn 7-runtime-centos 7ミラーにインストールされているdriverは410.58ですが、ホストホストにインストールされているdriverは418.18です.
物理マシンのドライバをアンインストールし、410.57を再インストールしました(410.58は見つかりません.410.57バージョンのドライバのみが見つかりました:http://de.download.nvidia.com/XFree86/Linux-x86_64/410.57/NVIDIA-Linux-x86_64-410.57.run)
その後正常に動作