1.gpu直通方式

1-1v1.8之前的老版本:基于nvidia-docker实现(基本不用了,了解)

前期准备:1、nvidia driver 2、cuda 3、nvidia-docker

K8s 启动pod时指定参数,即可使用gpu

(1)alpha.kubernetes.io/nvidia-gpu 指定调用nvidia gpu的数量

(2)为了能让GPU容器运行起来,需要将Nvidia驱动和CUDA库文件指定到容器中。这里需要使用hostPath,您只需要将hostPath指定到/var/lib/nvidia-docker/volumes/nvidia_driver/384.98即可,并不需要指定多个bin和lib目录。

resources:
    limits:
        alpha.kubernetes.io/nvidia-gpu: 1
volumes:
    - hostPath:
        path: /usr/lib/nvidia-375/bin 
        name: bin
    - hostPath:
        path: /usr/lib/nvidia-375
        name: lib

K8s版本:v1.8、v1.9、v1.10、v1.11和v1.12

传统的alpha.kubernetes.io/nvidia-gpu即将在1.11版本中下线,和GPU相关的调度和部署的代码将彻底从主干代码中移除。

取而代之的是通过Extended Resource+Device Plugin两个Kubernetes的内置模块,外加由设备提供商实现的相应Device Plugin, 完成从设备的集群级别调度至工作节点,到设备与容器的实际绑定,1.10之后的版本默认开启deviceplugins。仅需配置limits,无需指定volumes了

    resources:

      limits:

        nvidia.com/gpu: 1

1-2、基于devicePlugins实现(重点)

根据官方说明,安装英伟达GPU plugin前必须安装好nvidia-docker2,但是docker19.0+版本又不需要安装nvidia-docker2了,所以我姑且试了一下,发现确实不需要安装nvidia-docker2,只需要配置/etc/docker/daemon.json文件,将默认运行时改成nvidia就可以了。(但如果你使用的是docker19.0以下的版本,还是老老实实安装官方教程走。)

K8s版本:v1.8、v1.9、v1.10、v1.11和v1.12

传统的alpha.kubernetes.io/nvidia-gpu在1.11版本中下线,和GPU相关的调度和部署的代码将彻底从主干代码中移除。取而代之的是通过Extended Resource+Device Plugin两个Kubernetes的内置模块,外加由设备提供商实现的相应Device Plugin, 完成从设备的集群级别调度至工作节点,到设备与容器的实际绑定,1.10之后的版本默认开启deviceplugins。

安装k8s前需要先禁用虚拟内存 swapoff –a,否则安装会出错

0、前提:安装好nvidia-driver驱动和支持的cuda,并禁用nouveau:lsmod | grep nouveau没有输出即禁用了。

  1. 安装nvidia-container-runtime(CentOS版本)
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | sudo tee /etc/yum.repos.d/nvidia-docker.repo
yum clean all
yum makecache
sudo yum install -y nvidia-container-toolkit nvidia-container-runtime

(Ubuntu版本:前面俩行命令都是一样的)

curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
apt-get update
apt-get install -y nvidia-container-toolkit nvidia-container-runtime
若出现’dpkg 被中断,您必须手工运行 sudo dpkg –configure -a解决此问题’:删除 rm /var/lib/dpkg/updates/* ,重新构建即可sudo apt-get update

PS:如果是docker19.3以下版本需要安装nvidia-docker2:

# 添加nvidia-docker2源
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
# 安装nvidia-docker2,重载Docker daemon configuration
yum install -y nvidia-docker2
sudo pkill -SIGHUP dockerd
1. 配置/etc/docker/daemon.json (centOS与unbuntu均是此目录,不存在需要手动创建)
# /etc/docker/daemon.json
{
    "default-runtime": "nvidia",
    "runtimes": {
        "nvidia": {
            "path": "/usr/bin/nvidia-container-runtime",
            "runtimeArgs": []
        }
    },
"registry-mirrors": ["https://3lz3ongc.mirror.aliyuncs.com"],
"live-restore": true
}
systemctl daemon-reload
systemctl restart docker

3、配置kubelet参数并启动deviceplugins(Kubernetes 1.10之前的版本,默认disable DevicePlugins,需要添加参数开启。1.10之后的版本无需添加kubelet参数,是默认开启的)

kubelet配置在文件/etc/sysconfig/kubelet中

增加配置:

KUBELET_EXTRA_ARGS=--fail-swap-on=false --cadvisor-port=4194 --feature-gates=DevicePlugins=true

重启服务:

systemctl daemon-reload

systemctl restart kubelet

kubectl命令使用时报错:The connection to the server 172.20.231.234:6443 was refused。Systemctl status kubelet查看是否还存活,journalctl -u kubelet 查看kubelet日志

4.创建daemonset(daemonset会在每个节点运行一个pod)

kubectl create -f - <<EOF
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: nvidia-device-plugin-daemonset
  namespace: kube-system
spec:
  selector:
    matchLabels:
      name: nvidia-device-plugin-ds
  updateStrategy:
    type: RollingUpdate
  template:
    metadata:
      # This annotation is deprecated. Kept here for backward compatibility
      # See https://kubernetes.io/docs/tasks/administer-cluster/guaranteed-scheduling-critical-addon-pods/
      annotations:
        scheduler.alpha.kubernetes.io/critical-pod: ""
      labels:
        name: nvidia-device-plugin-ds
    spec:
      tolerations:
      # This toleration is deprecated. Kept here for backward compatibility
      # See https://kubernetes.io/docs/tasks/administer-cluster/guaranteed-scheduling-critical-addon-pods/
      - key: CriticalAddonsOnly
        operator: Exists
      - key: nvidia.com/gpu
        operator: Exists
        effect: NoSchedule
      # 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.
      # See https://kubernetes.io/docs/tasks/administer-cluster/guaranteed-scheduling-critical-addon-pods/
      priorityClassName: "system-node-critical"
      containers:
      - image: nvidia/k8s-device-plugin:1.0.0-beta6
        name: nvidia-device-plugin-ctr
        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
EOF

5、查看GPU节点GPU卡数量

kubectl get nodes "-o=custom-columns=NAME:.metadata.name,GPU:.status.allocatable.nvidia\.com/gpu"

使用kubectl describe node也可查看资源。节点中gpu资源和cpu内存等一样,分配给pod使用后,其他pod无法再使用,资源不够pod是无法启动的

如果出现某个节点无法获取到gpu资源,需要从这些方面排查:

5.1查看一下 Device Plugin 的日志(即创建的daemonset日志,pod要部署到所有节点)

5.2检查Nvidia 的 runC 是否配置为 docker 默认 runC(运行时)

/etc/docker/daemon.json中"default-runtime": "nvidia", "runtimes": { "nvidia": {"path": "nvidia-container-runtime",  "runtimeArgs": []   } }  此配置即用于替换docker的默认runC

配置完使用docker info会看到相应的更改已生效。

Server Version: 18.09.6

Storage Driver: overlay

Cgroup Driver: cgroupfs

Runtimes: nvidia runc

Default Runtime: nvidia

Docker Root Dir: /data05

5.3检查Nvidia 驱动是否安装成功

6、测试k8s调度gpu:(ps:因为nvidia/cuda镜像是内置cuda的,所以需要指定版本和本机的匹配才行)

apiVersion: v1
kind: Pod
metadata:
  name: gpu-pod
spec:
  restartPolicy: Never
  containers:
  - image: nvidia/cuda:10.0-base
    name: cuda
    command: ["nvidia-smi"]
    resources:
      limits:
        nvidia.com/gpu: 1
kubectl create -f gpu-pod.yaml
kubectl logs gpu-pod   #查看是否有输入nvidia-msi信息

ps:注意k8s的gpu方案也是基于nvidia-docker的,docker19.03内置了。nvidia.com/gpu: 1分配gpu后,pod内默认是使用宿主机的nvidia驱动和cuda版本进行gpu调度所以pod内无需再安装cuda了节点中gpu资源和cpu内存等一样,分配给pod使用后,其他pod无法再使用,gpu资源不够了pod是无法启动的。

以上是Nvidia Gpu DevicePlugin:Nvidia 贡献的调度方案,这是最常用的调度方案;

除此之外还有GPU Share DevicePlugin:由阿里云服务团队贡献的 GPU 共享的调度方案,其目的在于解决用户共享 GPU 调度的需求

报错:CUDA error:out of memory。 原因:gpu显存不足。 一块gpu可以被好多进程使用,每个进程使用一部分现存。

在matlab中第一次创建gpuArray,或者调用gpuDevice()会慢那么一点,可是接下来再调用就很快了。因为第一次启动要加载很多gpu库。

2、Orion vGPU

没有将物理GPU直通进容器内部,不依赖于nvidia-docker

Ps:使用的时vgpu虚拟化技术,对gpu显卡需求版本较高,需高价格的显卡,由于资金问题,此方案未测试。

配置pod指定参数,启用gpu

用户配置POD的yaml文件应该包含如下的内容

resources:
     limits:
       virtaitech.com/gpu: 1
   env:
     - name : ORION_GMEM
       value : "4096"

上述表明该POD使用1个Orion的vGPU,每个vGPU的显存大小为4096MB