K8s集群gpu支持(直通和vgpu)

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

参考:https://gitee.com/teacherandchang/orion

猜你喜欢

转载自blog.csdn.net/qq_42152032/article/details/131342108