Kubernetes(1.8.3)系列之GPU配置

Posted on 2017-12-20(星期三) 10:15 in Data

Kubernetes支持容器请求GPU资源(目前仅支持NVIDIA GPU),在深度学习等场景中有大量应用。

预先配置

  • Kubelet配置使用docker容器引擎(默认就是docker),其他容器引擎暂不支持该特性。
  • 在所有的Node上安装Nvidia驱动,包括NVIDIA Cuda Toolkit和cuDNN等。

    PS:如果使用的是nvidia/cuda的docker镜像的话,则只需要安装Nvidia的驱动即可,另外安装一下对应docker版本的Nvidia-docker工具(Nvidia-docker更新速度相对docker慢一些)。可参考 Nvidia-docker的作用, 在这里的作用简单来说就是提供了nvidia的一些命令和类库(cuda、)

  • 在各台拥有GPU资源的节点上的kubelet上开启--feature-gates=Accelerators=true

    [Unit]
    Description=Kubernetes Kubelet
    Documentation=https://github.com/GoogleCloudPlatform/kubernetes
    After=docker.service
    Requires=docker.service
    
    [Service]
    WorkingDirectory=/var/lib/kubelet
    ExecStart=/usr/local/bin/kubelet \
      --feature-gates=Accelerators=true \
      --cgroup-driver=cgroupfs \
      --hostname-override=192.168.1.189 \
      --pod-infra-container-image=192.168.1.184:5000/bigdata/rhel7/pod-infrastructure:v1.0.0 \
      --experimental-bootstrap-kubeconfig=/etc/kubernetes/bootstrap.kubeconfig \
      --kubeconfig=/etc/kubernetes/kubelet.kubeconfig \
      --cert-dir=/etc/kubernetes/ssl \
      --cluster_dns=10.254.0.2 \
      --cluster_domain=cluster.local. \
      --hairpin-mode promiscuous-bridge \
      --allow-privileged=true \
      --fail-swap-on=false \
      --serialize-image-pulls=false \
      --logtostderr=true \
      --max-pods=512 \
      --v=2
    
    [Install]
    WantedBy=multi-user.target
    

GPU 配置

同种型号的GPU

使用 alpha.kubernetes.io/nvidia-gpu 资源进行GPU指定:

apiVersion: v1
kind: Pod 
metadata:
  name: gpu-pod
spec: 
  containers: 
    - name: gpu-container-1
      image: gcr.io/google_containers/pause:2.0
      resources: 
        limits: 
          alpha.kubernetes.io/nvidia-gpu: 2 # requesting 2 GPUs
    - name: gpu-container-2
      image: gcr.io/google_containers/pause:2.0
      resources: 
        limits: 
          alpha.kubernetes.io/nvidia-gpu: 3 # requesting 3 GPUs

创建 Pod

$ kubectl create -f pod.yaml
pod "gpu-pod" created

注意:

  • GPU资源必须在resources.limits中请求,resources.requests中无效
  • 容器可以请求1个或多个GPU,不能只请求一部分
  • 多个容器之间不能共享GPU
  • 默认假设所有Node安装了相同型号的GPU,不同型号的设置方式接下来讨论

多种型号的GPU

如果集群Node中安装了多种型号的GPU,则可以使用Node Affinity来调度Pod到指定GPU型号的Node上。

首先,在集群初始化时,需要给Node打上GPU型号的标签:

NVIDIA_GPU_NAME=$(nvidia-smi --query-gpu=gpu_name --format=csv,noheader --id=0 | sed -e 's/ /-/g')
source /etc/default/kubelet
KUBELET_OPTS="$KUBELET_OPTS --node-labels='alpha.kubernetes.io/nvidia-gpu-name=$NVIDIA_GPU_NAME'"
echo "KUBELET_OPTS=$KUBELET_OPTS" > /etc/default/kubelet

然后,在创建Pod时设置Node Affinity

kind: pod
apiVersion: v1
metadata:
  annotations:
    scheduler.alpha.kubernetes.io/affinity: >
      {
        "nodeAffinity": {
          "requiredDuringSchedulingIgnoredDuringExecution": {
            "nodeSelectorTerms": [
              {
                "matchExpressions": [
                  {
                    "key": "alpha.kubernetes.io/nvidia-gpu-name",
                    "operator": "In",
                    "values": ["Tesla K80", "Tesla P100"]
                  }
                ]
              }
            ]
          }
        }
      }
spec:
  containers:
    -
      name: gpu-container-1
      resources:
        limits:
          alpha.kubernetes.io/nvidia-gpu: 2

配置完后,该pod会使用 Tesla K80Tesla P100

使用CUDA库

可以通过hostPath volume的形式将CUDA库文件传给容器:

kind: Pod
apiVersion: v1
metadata:
  name: gpu-pod
spec:
  containers:
  - name: gpu-container-1
    image: gcr.io/google_containers/pause:2.0
    resources:
      limits:
        alpha.kubernetes.io/nvidia-gpu: 1
    volumeMounts:
    - mountPath: /usr/local/nvidia/bin
      name: bin
    - mountPath: /usr/lib/nvidia
      name: lib
  volumes:
  - hostPath:
      path: /usr/lib/nvidia-375/bin
    name: bin
  - hostPath:
      path: /usr/lib/nvidia-375
    name: lib

kubernetes(1.8.3版本)自动分配GPU资源策略测试:

官网GPU说明:

  • Containers (and pods) do not share GPUs.
  • Each container can request one or more GPUs.
  • It is not possible to request a portion of a GPU.
  • Nodes are expected to be homogenous, i.e. run the same GPU hardware.

测试环境:

六个节点的集群,集群管理节点为单独一台机器,没有GPU,余下五个节点,有一个节点有四个GPU,其余四台机器均为各有一个GPU。GPU均为NVIDIA GeForce 1080 Ti。

结果:

  • 1.每个任务申请的GPU只能是在一台节点上;
  • 2.每个任务申请的GPU个数不能超过单台节点拥有的GPU个数;
  • 3.kubernetes会自动分配符合GPU申请个数的节点和GPU;
  • 4.可以指定在某台节点上分配GPU资源,但除了第一块GPU,其余GPU不可以自己指定;

------------------------------2017-12-21 补充

  • 5.当指定特权模式之后,任意GPU都可以指定了(可能还有别的方法可以实现)。

    在yaml文件中的containers项下配置打开特权模式:

    containers: 
    - name: tensorflow-py2 
      image: 192.168.1.184:5000/bigdata/tensorflow-gpu-py2:1.3.0-gpu
      securityContext:
        privileged: true
      workingDir: /ceph/docker/