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没有输出即禁用了。
- 安装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