K8S节点GPU虚拟化(vGPU)

vGPU实现方案

4paradigm提供了k8s-device-plugin,该插件基于NVIDIA官方插件(NVIDIA/k8s-device-plugin),在保留官方功能的基础上,实现了对物理GPU进行切分,并对显存和计算单元进行限制,从而模拟出多张小的vGPU卡。在k8s集群中,基于这些切分后的vGPU进行调度,使不同的容器可以安全的共享同一张物理GPU,提高GPU的利用率。此外,插件还可以对显存做虚拟化处理(使用到的显存可以超过物理上的显存),运行一些超大显存需求的任务,或提高共享的任务数。

部署

需要在节点上将nvidia runtime做为你的docker runtime预设值。我们将编辑docker daemon的配置文件,此文件通常在/etc/docker/daemon.json路径:

{
    "default-runtime": "nvidia",
    "runtimes": {
        "nvidia": {
            "path": "/usr/bin/nvidia-container-runtime",
            "runtimeArgs": []
        }
    }
    "default-shm-size": "2G"
}

虚拟化之前,在GPU节点启动一个GPU应用pod,通过nvidia-smi 查看GPU分配及使用情况。
pod资源请求:

    Limits:
      cpu:             4
      memory:          16Gi
      nvidia.com/gpu:  1
    Requests:
      cpu:             2
      memory:          8Gi
      nvidia.com/gpu:  1

pod内执行nvidia-smi

+-----------------------------------------------------------------------------+
| NVIDIA-SMI 460.91.03    Driver Version: 460.91.03    CUDA Version: 11.3     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  A10                 On   | 00000000:00:08.0 Off |                  Off |
|  0%   53C    P0    71W / 150W |   1475MiB / 24258MiB |      0%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
+-----------------------------------------------------------------------------+

可以看到此时占用A10节点整张卡显存 24Gi 。

关闭NVIDIA官方插件

关闭NVIDIA官方插件(NVIDIA/k8s-device-plugin)。

把nvidia-device-plugin ds描述文件移除即可,为安全可以移动到其它目录,如下移动到家目录做备份保存。

[root@gpua10_1 ~]# mv /etc/kubernetes/manifests/nvidia-device-plugin.yml .

如上操作后,原来的nvidia pod:

(base) ➜  ~ kubectl -n kube-system get po |grep nvidia                                                     
nvidia-device-plugin-gpua10_1            1/1     Running     0              5d

移除ds描述文件后,以上pod会消失。

启动4paradigm新的k8s-device-plugin

ds文件如下:

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:
      annotations:
        scheduler.alpha.kubernetes.io/critical-pod: ""
      labels:
        name: nvidia-device-plugin-ds
    spec:
      tolerations:
      - key: CriticalAddonsOnly
        operator: Exists
      - key: nvidia.com/gpu
        operator: Exists
        effect: NoSchedule
      priorityClassName: "system-node-critical"
      containers:
      - image: 4pdosc/k8s-device-plugin:latest
        # - image: m7-ieg-pico-test01:5000/k8s-device-plugin-test:v0.9.0-ubuntu20.04
        imagePullPolicy: Always
        name: nvidia-device-plugin-ctr
        args: ["--fail-on-init-error=false", "--device-split-count=6", "--device-memory-scaling=2", "--device-cores-scaling=1"]
        # args: ["--fail-on-init-error=false", "--device-split-count=3", "--device-memory-scaling=3", "--device-cores-scaling=1"]
        env:
        - name: PCIBUSFILE
          value: "/usr/local/vgpu/pciinfo.vgpu"
        - name: NVIDIA_MIG_MONITOR_DEVICES
          value: all
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop: ["ALL"]
            add: ["SYS_ADMIN"]
        volumeMounts:
          - name: device-plugin
            mountPath: /var/lib/kubelet/device-plugins
          - name: vgpu-dir
            mountPath: /usr/local/vgpu
          - mountPath: /tmp
            name: hosttmp
      volumes:
        - name: device-plugin
          hostPath:
            path: /var/lib/kubelet/device-plugins
        - name: vgpu-dir
          hostPath:
            path: /usr/local/vgpu
        - hostPath:
            path: /tmp
          name: hosttmp
      nodeSelector: 
        nvidia-vgpu: "on"
  • fail-on-init-error: 布尔类型, 预设值是true。当这个参数被设置为true时,如果装置插件在初始化过程遇到错误时程序会返回失败,当这个参数被设置为false时,遇到错误它会打印信息并且持续阻塞插件。持续阻塞插件能让装置插件即使部署在没有GPU的节点(也不应该有GPU)也不会抛出错误。这样你在部署装置插件在你的集群时就不需要考虑节点是否有GPU,不会遇到报错的问题。然而,这么做的缺点是如果GPU节点的装置插件因为一些原因执行失败,将不容易察觉。现在预设值为当初始化遇到错误时程序返回失败,这个做法应该被所有全新的部署采纳。
  • device-split-count: 整数类型,预设值是2。NVIDIA装置的分割数。对于一个总共包含N张NVIDIA GPU的Kubernetes集群,如果我们将device-split-count参数配置为K,这个Kubernetes集群将有K * N个可分配的vGPU资源。注意,我们不建议将NVIDIA 1080 ti/NVIDIA 2080 ti device-split-count参数配置超过5,将NVIDIA T4配置超过7,将NVIDIA A100配置超过15。
  • device-memory-scaling: 浮点数类型,预设值是1。NVIDIA装置显存使用比例,可以大于1(启用虚拟显存,实验功能)。对于有M​显存大小的NVIDIA GPU,如果我们配置device-memory-scaling参数为S,在部署了我们装置插件的Kubenetes集群中,这张GPU分出的vGPU将总共包含 S * M显存。每张vGPU的显存大小也受device-split-count参数影响。在先前的例子中,如果device-split-count参数配置为K,那每一张vGPU最后会取得 S * M / K 大小的显存。
  • device-cores-scaling: 浮点数类型,预设值与device-split-count数值相同。NVIDIA装置算力使用比例,可以大于1。如果device-cores-scaling​参数配置为S​ device-split-count参数配置为K,那每一张vGPU对应的一段时间内 SM 利用率平均上限为S / K。属于同一张物理GPU上的所有vGPU SM利用率总和不超过1。
  • enable-legacy-preferred: 布尔类型,预设值是false。对于不支持 PreferredAllocation 的kubelet(<1.9)可以设置为true,以更好的选择合适的设备,开启时,本插件需要有对pod的读取权限,可参看 legacy-preferred-nvidia-device-plugin.yml。对于 kubelet >= 1.9 时,建议关闭。

如上"--device-split-count=6", "--device-memory-scaling=2", 表示在原显存基础上扩充二倍切成六份使用,也就是24Gi*2/6=8Gi,虚拟化之后原GPU可以切成6份使用,每份占用显存8Gi,虚拟化之后多出的显存实际是用内存作显存使用,所以注意节点的内存大小(要留够节点正常运行所需的内存),不然会出现OOM的情况,在需要进行虚拟化的节点打上标签nvidia-vgpu: "on"即可。

部署以上ds,且节点打上标签后会出现:

(base) ➜  ~ kubectl -n kube-system get pod |grep nvidia
nvidia-device-plugin-daemonset-pm21x                      1/1     Running     0               3d12h

此时pod内再次执行nvidia-smi

+-----------------------------------------------------------------------------+
| NVIDIA-SMI 460.91.03    Driver Version: 460.91.03    CUDA Version: 11.3     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  NVIDIA A10          On   | 00000000:00:0A.0 Off |                    0 |
|  0%   43C    P0    68W / 150W |   4375MiB /  7676MiB |      0%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
+-----------------------------------------------------------------------------+

可以看到pod分配了8Gi的显存。

注意

以上是在nvidia版本NVIDIA-SMI 460.91.03 Driver Version: 460.91.03 CUDA Version: 11.3执行的操作。在升级到NVIDIA-SMI 515.105.01 Driver Version: 515.105.01 CUDA Version: 11.7 版本的时候遇到vGPU虚拟化不生效的问题,解决方案是:

  1. 升级libvgpu.so到最新
  2. 在server.go中添加/tmp/vgpulock文件权限。
os.MkdirAll("/tmp/vgpulock", 0777)
os.Chmod("/tmp/vgpulock", 0777)
response.Mounts = append(response.Mounts,
             &pluginapi.Mount{"containerPath": "/usr/local/vgpu/libvgpu.so",
                                "HostPath": "/usr/local/vgpu/libvgpu.so", ReadOnly: true},
 			&pluginapi.Mount{"containerPath": "/etc/ld.so.preload",
                                "HostPath": "/usr/local/vgpu/ld.so.preload", ReadOnly: true},
 			&pluginapi.Mount{"containerPath": "/usr/local/vgpu/pciinfo.vgpu",
                                "HostPath": os.Getenv("PCIBUSFILE"), ReadOnly: true},
 			&pluginapi.Mount{"containerPath": "/tmp/vgpulock",
                                "HostPath": "/tmp/vgpulock", ReadOnly: true},
<think>好的,用户让我介绍一下K8s深度学习,也就是Kubernetes在深度学习中的应用。首先,我需要回忆一下用户之前的对话历史,看看他们之前问过什么。之前他们询问了Jenkins的学习路径,可能对DevOps和持续集成有一定的了解,现在转向Kubernetes和深度学习的结合,可能是想了解如何利用Kubernetes来管理深度学习的工作负载。 接下来,我要确定用户的需求是什么。他们可能想知道Kubernetes在深度学习中的具体应用场景、优势,以及如何配置和管理深度学习任务。此外,用户可能对资源调度、分布式训练、GPU支持等方面感兴趣,因为这些是深度学习在Kubernetes上的关键点。 首先,我需要介绍Kubernetes的基本概念,但用户可能已经有一定的了解,所以可以简要带过,重点放在与深度学习的结合上。然后要分几个部分来展开:为什么用K8s做深度学习、核心功能、架构设计、部署流程、工具生态、挑战与解决方案,以及学习路径。 需要考虑用户可能的背景。他们可能是有一定技术基础的用户,比如开发者或DevOps工程师,想要将深度学习模型部署到生产环境中,或者管理大规模的训练任务。因此,内容需要详细但不过于基础,强调实际应用和最佳实践。 在组织内容时,要结构清晰,逐步深入。例如,先讲为什么选择K8s,然后核心功能,架构设计,部署流程,工具链,挑战,最后学习路径。每个部分需要用例子和具体的技术细节来支撑,比如使用Kubeflow进行流水线管理,GPU资源调度配置等。 还要注意用户可能遇到的常见问题,比如GPU资源不足时的自动扩缩容,如何监控资源使用情况,分布式训练的通信优化等,这些都需要在挑战与解决方案部分提到。 需要检查技术术语的准确性,比如Operator的概念,Kubeflow的组件,GPU插件的配置等,确保信息正确。同时,提供代码示例或配置片段,比如定义Pod资源限制的部分,这样用户可以直接参考应用。 最后,学习路径部分要给出逐步学习的建议,从基础到高级,包括官方文档、实践项目、社区资源等,帮助用户系统地掌握相关知识。同时,提醒用户关注社区动态,因为K8s和深度学习领域都在快速发展,保持更新很重要。 总结来说,回答需要覆盖K8s在深度学习中的关键应用,结合用户可能的技术背景,提供结构化的信息,实际案例,解决方案,以及学习资源,满足用户从入门到实践的需求。</think>### **Kubernetes(K8s)与深度学习结合指南** --- #### **1. 为什么选择 Kubernetes 进行深度学习?** - **核心优势**: - **弹性资源调度**:动态分配 GPU、CPU、内存等资源,应对计密集型任务。 - **分布式训练支持**:天然适配多节点并行训练(如 TensorFlow/PyTorch 分布式训练)。 - **大规模实验管理**:统一管理模型训练、超参优化、推理服务等全生命周期。 - **成本控制**:通过自动扩缩容(HPA)避免资源闲置。 - **典型场景**: - 分布式模型训练(单机多卡/多机多卡)。 - 超参数搜索(Hyperparameter Tuning)。 - 模型推理服务(高可用、自动扩缩容)。 - 多租户资源共享(隔离团队或用户的计环境)。 --- #### **2. Kubernetes 对深度学习的核心支持** | **功能** | **说明** | |------------------------|-------------------------------------------------------------------------| | **GPU 资源调度** | 通过 `nvidia-device-plugin` 插件暴露 GPU 资源,支持按需分配。 | | **分布式训练框架集成** | 原生支持 TensorFlow/PyTorch 的分布式通信(如 `AllReduce`)。 | | **任务队列管理** | 使用 `Job` 或 `CronJob` 定义训练任务,支持重试、超时控制。 | | **存储卷管理** | 持久化存储训练数据与模型(如 NFS、Ceph、云存储)。 | | **服务发现与负载均衡** | 通过 `Service` 和 `Ingress` 暴露推理服务,支持灰度发布和流量管理。 | --- #### **3. Kubernetes 深度学习架构设计** 1. **资源层**: - **GPU 虚拟化**:使用 NVIDIA GPU Operator 或 vGPU 技术(如 MIG)实现细粒度资源分割。 - **存储方案**: - 数据集:挂载高性能分布式存储(如 CephFS、Amazon EFS)。 - 中间结果:使用临时卷(`emptyDir`)。 - 模型持久化:对接对象存储(如 MinIO、S3)。 2. **任务调度层**: - **优先级与抢占**:通过 `PriorityClass` 确保高优先级任务优先获取资源。 - **自动扩缩容**:基于资源指标(GPU 利用率)触发扩缩容(需结合 Prometheus + KEDA)。 3. **训练与推理层**: - **分布式训练框架**: - **PyTorch**:使用 `torch.distributed` 和 `torch-elastic` 实现容错训练。 - **TensorFlow**:通过 `TF_CONFIG` 配置多 Worker 节点。 - **推理服务优化**: - 模型压缩(如 TensorRT)。 - 批处理(Batching)与缓存(Redis)。 --- #### **4. 深度学习任务部署流程** 1. **定义 Pod 资源需求**: ```yaml apiVersion: v1 kind: Pod metadata: name: pytorch-training spec: containers: - name: trainer image: pytorch/pytorch:latest resources: limits: nvidia.com/gpu: 2 # 申请 2 块 GPU memory: 32Gi ``` 2. **分布式训练示例(PyTorch)**: - 使用 `Job` 启动多个 Worker: ```yaml apiVersion: batch/v1 kind: Job metadata: name: pytorch-ddp-job spec: parallelism: 4 # 启动 4 个 Pod template: spec: containers: - name: worker image: pytorch-ddp-image command: ["python", "train.py"] env: - name: MASTER_ADDR value: "pytorch-ddp-job" # Headless Service 名称 ``` 3. **推理服务部署**: - 使用 `Deployment` 和 `Service`: ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: model-inference spec: replicas: 3 selector: matchLabels: app: model-inference template: spec: containers: - name: infer image: model-inference:v1 ports: - containerPort: 8080 --- apiVersion: v1 kind: Service metadata: name: model-service spec: selector: app: model-inference ports: - protocol: TCP port: 80 targetPort: 8080 type: LoadBalancer ``` --- #### **5. 深度学习工具链与生态** | **工具** | **用途** | |-------------------|-------------------------------------------------------------------------| | **Kubeflow** | 提供完整 ML 流水线(Pipeline)、超参优化(Katib)、模型服务(KFServing)。| | **NVIDIA GPU Operator** | 自动化部署 GPU 驱动、容器运行时、监控工具。 | | **Prometheus + Grafana** | 监控 GPU 利用率、训练任务状态。 | | **Seldon Core** | 将模型封装为微服务,支持 A/B 测试和模型解释。 | | **MLflow** | 实验追踪、模型版本管理,与 Kubernetes 集成部署。 | --- #### **6. 挑战与解决方案** 1. **GPU 资源争抢**: - **方案**: - 使用 `ResourceQuota` 限制命名空间资源总量。 - 基于时间片的共享调度(如 NVIDIA MPS)。 2. **分布式训练通信延迟**: - **方案**: - 选择高性能网络插件(如 Calico + RDMA)。 - 优化数据加载(预处理后缓存至内存)。 3. **模型版本与回滚**: - **方案**: - 使用 `Helm Chart` 管理推理服务版本。 - 通过 GitOps(如 Argo CD)实现声明式部署。 --- #### **7. 学习路径建议** 1. **基础阶段**: - 掌握 Kubernetes 核心概念(Pod/Deployment/Service/Volume)。 - 学习 GPU 资源调度(NVIDIA Device Plugin 配置)。 2. **实战阶段**: - 部署分布式 PyTorch 训练任务(参考 [Kubeflow Training Operator](https://www.kubeflow.org/docs/components/training/))。 - 使用 KFServing 部署推理服务(支持 Canary 发布和自动扩缩容)。 3. **进阶阶段**: - 优化 GPU 利用率(监控与调度策略调优)。 - 设计多租户深度学习平台(结合 Namespace 和 RBAC)。 4. **工具链集成**: - 结合 MLflow 追踪实验,使用 Airflow 或 Argo 编排流水线。 --- #### **8. 典型应用案例** - **自动驾驶模型训练**: - 场景:跨地域多节点训练 PB 级数据集。 - K8s 方案: - 使用 `Volcano` 调度器优化批量任务。 - 通过 `Fluid` 加速分布式存储数据访问。 - **在线推荐系统**: - 场景:实时推理服务需低延迟、高吞吐。 - K8s 方案: - 部署 `InferenceService`(KFServing)自动扩缩容。 - 使用 `Knative` 实现 Serverless 弹性伸缩。 --- ### **总结** Kubernetes 为深度学习提供了**弹性基础设施**和**自动化运维能**,核心价值在于统一管理训练与推理任务,最大化硬件利用率。学习重点应围绕 GPU 资源调度、分布式训练框架集成、推理服务优化展开。通过 Kubeflow 等工具链,可快速构建端到端的机器学习平台。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值