<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Jimmy Song – 数据平面技术</title><link>https://jimmysong.io/zh/book/gpu-infra/data-plane/</link><description>Recent content in 数据平面技术 on Jimmy Song</description><generator>Hugo -- gohugo.io</generator><language>zh</language><managingEditor>Jimmy Song</managingEditor><webMaster>Jimmy Song</webMaster><follow_challenge><feedId>51621818828612637</feedId><userId>59800919738273792</userId></follow_challenge><lastBuildDate>Sat, 10 Jan 2026 10:45:55 +0800</lastBuildDate><atom:link href="https://jimmysong.io/zh/book/gpu-infra/data-plane/index.xml" rel="self" type="application/rss+xml"/><item><title>数据平面谱系：切分、虚拟化与隔离机制大全</title><link>https://jimmysong.io/zh/book/gpu-infra/data-plane/data-plane-taxonomy/</link><pubDate>Tue, 30 Dec 2025 05:01:33 +0000</pubDate><author>Jimmy Song</author><guid>https://jimmysong.io/zh/book/gpu-infra/data-plane/data-plane-taxonomy/</guid><description>系统梳理 MIG/vGPU/时间片/配额/显存策略等机制的根本差异，并建立对比基线。</description><content:encoded>
&lt;blockquote&gt;
&lt;p&gt;真正理解 GPU 共享，先要看清数据平面的“谱系”，而不是陷入口水战。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="本章要解决什么"&gt;本章要解决什么&lt;/h2&gt;
&lt;p&gt;在 GPU 场景中，“共享”常常被误解为单一能力：要么能共享，要么不能共享。实际上，&lt;strong&gt;共享是一组数据平面机制的组合&lt;/strong&gt;，涉及设备发现与暴露、资源单位的切分方式、隔离与 QoS（Quality of Service，服务质量）的实现位置，以及容器运行时/驱动栈的具体落地方式。&lt;/p&gt;
&lt;p&gt;因此，本章不直接比较具体项目（如 HAMi、MIG、GPU Operator、GPUStack 等），而是先给出一张“数据平面谱系”——将所有 GPU 共享手段归类为可验证的机制集合。后续每个项目章节都只是把“它用了哪些机制、补了哪些治理能力”回填到这张谱系里，避免陷入口号之争。&lt;/p&gt;
&lt;h2 id="数据平面与控制面的边界"&gt;数据平面与控制面的边界&lt;/h2&gt;
&lt;p&gt;理解数据平面与控制面的分工，是分析 GPU 共享机制的基础。&lt;/p&gt;
&lt;p&gt;Kubernetes 的设备扩展机制（Device Plugin，设备插件）决定了一个基本事实：&lt;strong&gt;kubelet 的 Device Manager 负责把“可用设备”暴露为可调度资源，并在 &lt;code&gt;Allocate&lt;/code&gt; 阶段做设备侧准备；但它并不定义“更细粒度资源单位、隔离与 QoS”应该如何实现&lt;/strong&gt;。这使得更细粒度的共享天然倾向于下沉到数据平面实现。&lt;/p&gt;
&lt;p&gt;在前面的 &lt;a href="../k8s-device-model/"&gt;Kubernetes 资源模型&lt;/a&gt;一章中可以看到，Kubernetes 的语义天然更接近“整卡/离散设备”而不是“连续可分的 CPU”。&lt;/p&gt;
&lt;p&gt;进一步，Kubernetes DRA（Dynamic Resource Allocation，动态资源分配）把“设备分配的对象”从扩展资源升级为更可表达的 &lt;code&gt;DeviceClass/ResourceClaim&lt;/code&gt;，使“按属性筛选、按声明分配、可共享 claim”等模式更自然。但 DRA 仍然不替你解决隔离机制本身：隔离强度、资源单位、干扰与计量，依然由数据平面决定。&lt;/p&gt;
&lt;p&gt;本书的基本坐标系如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;控制面&lt;/strong&gt;：处理队列、配额、优先级、公平性、准入与编排策略。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;数据平面&lt;/strong&gt;：处理设备发现/暴露、切分与虚拟化、隔离与 QoS、可观测与计量，以及运行时注入（mount/env/hooks/CDI 等）。&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class="mx-auto text-center"&gt;
&lt;img src="https://assets.jimmysong.io/images/book/gpu-infra/data-plane-taxonomy/control-plane-data-plane.svg" data-img="https://assets.jimmysong.io/images/book/gpu-infra/data-plane-taxonomy/control-plane-data-plane.svg" alt="图 1: Kubernetes GPU 共享：数据平面 vs 控制面边界" data-caption="图 1: Kubernetes GPU 共享：数据平面 vs 控制面边界"
width="1507"
height="1763"
loading="lazy" decoding="async" class="image-loading"
onload="this.classList.remove('image-loading'); this.classList.add('image-loaded');"
onerror="handleImageError(this); this.classList.remove('image-loading');"&gt;
&lt;figcaption&gt;图 1: Kubernetes GPU 共享：数据平面 vs 控制面边界&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="数据平面谱系从强隔离硬切分到软约束过量订阅"&gt;数据平面谱系：从&amp;quot;强隔离硬切分&amp;quot;到&amp;quot;软约束过量订阅&amp;quot;&lt;/h2&gt;
&lt;p&gt;所有“GPU 共享”机制可以粗略放在一条谱系线上：从&lt;strong&gt;硬切分（强隔离、单位离散）&lt;strong&gt;逐步走向&lt;/strong&gt;软约束/过量订阅（灵活，但隔离依赖实现与负载行为）&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;下图以谱系轴展示常见 GPU 数据平面机制的相对位置与交付层关系。&lt;/p&gt;
&lt;figure class="mx-auto text-center"&gt;
&lt;img src="https://assets.jimmysong.io/images/book/gpu-infra/data-plane-taxonomy/data-plane-taxonomy-spectrum.svg" data-img="https://assets.jimmysong.io/images/book/gpu-infra/data-plane-taxonomy/data-plane-taxonomy-spectrum.svg" alt="图 2: GPU 数据平面谱系" data-caption="图 2: GPU 数据平面谱系"
width="1503"
height="1123"
loading="lazy" decoding="async" class="image-loading"
onload="this.classList.remove('image-loading'); this.classList.add('image-loaded');"
onerror="handleImageError(this); this.classList.remove('image-loading');"&gt;
&lt;figcaption&gt;图 2: GPU 数据平面谱系&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;下面按照“机制原语”进行分类（不是按项目），并分别介绍其核心特征和适用场景。&lt;/p&gt;
&lt;h3 id="独占baseline整卡分配--pass-through"&gt;独占（Baseline）：整卡分配 / Pass-through&lt;/h3&gt;
&lt;p&gt;作为所有对比的基线，Pod/容器独占一整张 GPU。这种方式的优点是性能与故障域最清晰；缺点是利用率在推理、小 batch、间歇任务上通常较低。它本质上不提供“共享”，但会作为后续实验的基线参照（吞吐、P99、显存碎片、稳定性）。&lt;/p&gt;
&lt;h3 id="硬切分partitionmig-这类硬件级资源单元化"&gt;硬切分（Partition）：MIG 这类“硬件级资源单元化”&lt;/h3&gt;
&lt;p&gt;MIG（Multi-Instance GPU，多实例 GPU）的关键价值不是“能分”，而是&lt;strong&gt;把 GPU 的关键路径拆成多个具有更强隔离边界的硬件实例&lt;/strong&gt;。以 NVIDIA 官方定义，MIG 让每个实例在内存系统关键路径上具备独立隔离：包括 crossbar 端口、L2 cache bank、memory controller 与 DRAM 地址总线等，从而得到更可预测的吞吐与延迟。&lt;/p&gt;
&lt;p&gt;这类硬切分机制的典型特征包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;资源单位离散&lt;/strong&gt;：获得的是一组固定规格的 slice/instance，而不是任意比例。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;隔离强度高&lt;/strong&gt;：至少在显存带宽/缓存等关键资源上更可控。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;动态调整成本高&lt;/strong&gt;：切分/重配通常需要运维动作，甚至影响同卡其他实例的生命周期与排空策略。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;兼容性好&lt;/strong&gt;：对上层框架基本透明（“像一张小 GPU”）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;适用场景：多租户推理、对 P99 敏感、需要更强“性能可预测性与故障隔离”的场景。&lt;/p&gt;
&lt;h3 id="介导虚拟化mediated--vgpu以-mdevvgpu-为代表的多虚拟设备"&gt;介导虚拟化（Mediated / vGPU）：以 mdev/vGPU 为代表的“多虚拟设备”&lt;/h3&gt;
&lt;p&gt;vGPU（Virtual GPU，虚拟 GPU）以及 Linux 里的介导设备（mediated device, mdev）思路，是通过虚拟化层将一块物理 GPU 呈现为多个“虚拟 GPU 设备”。这类机制常见于虚拟机（VM, Virtual Machine）场景，也可扩展到容器，但工程复杂度显著提升。NVIDIA 官方 vGPU 文档将其定义为一种图形/计算虚拟化平台，使多台 VM 可同时访问同一块物理 GPU。&lt;/p&gt;
&lt;p&gt;这类机制的典型特征：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;资源单位通常离散&lt;/strong&gt;（按 profile/类型划分），但比 MIG 更“软件化”。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;隔离与 QoS 依赖实现&lt;/strong&gt;：隔离边界通常弱于硬切分，但比纯时间片更可控（取决于实现与硬件能力）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;运维与许可复杂&lt;/strong&gt;：驱动栈、宿主/来宾驱动、虚拟化层集成、部分场景下商业许可等，会使“可部署性”成为主要约束。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;适用场景：强虚拟化/VM 优先的企业环境、需要 VM 级隔离边界、或已有既定 vGPU 栈的组织。&lt;/p&gt;
&lt;h3 id="时间片time-slicing在同一物理-gpu-上交错运行多个工作负载"&gt;时间片（Time-Slicing）：在同一物理 GPU 上交错运行多个工作负载&lt;/h3&gt;
&lt;p&gt;时间片共享的核心是&lt;strong&gt;过量订阅（oversubscription）&lt;/strong&gt;：多个 Pod/容器被调度到同一张 GPU 上，由驱动/插件在执行层面交错运行。NVIDIA GPU Operator 明确提供了 time-slicing 的配置路径，本质是通过设备插件的扩展能力实现“共享访问”。&lt;/p&gt;
&lt;p&gt;需要特别强调，时间片与 MIG 的差异非常明显。部分平台文档也指出，MIG 提供内存与故障隔离，而时间片并不具备同等强度的隔离，更多是为了提升利用率，适配轻量推理/预处理等场景。&lt;/p&gt;
&lt;p&gt;这类机制的典型特征：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;资源单位“看起来可分”&lt;/strong&gt;（可以声明更多份额），但隔离往往较弱。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;性能与尾延迟不确定&lt;/strong&gt;：尤其在显存压力、kernel launch 冲突、PCIe 抖动等情况下，P99 往往是首要风险点。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;动态灵活&lt;/strong&gt;：适合快速提高利用率，但需要强观测与强准入策略来收敛风险。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;适用场景：轻量推理、容忍干扰、以利用率为先且有完善观测/限流/准入的场景。&lt;/p&gt;
&lt;h3 id="进程级协作共享cuda-mps-这类协作式多进程并发"&gt;进程级协作共享：CUDA MPS 这类“协作式多进程并发”&lt;/h3&gt;
&lt;p&gt;MPS（Multi-Process Service，多进程服务）是 NVIDIA 提供的一种 CUDA API 兼容实现，通过客户端 - 服务端架构让多个进程更高效地共享 GPU 的执行资源。该机制常用于 HPC（High Performance Computing，高性能计算）/MPI 等场景，以利用 Hyper-Q 能力。&lt;/p&gt;
&lt;p&gt;这类机制的典型特征：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;更像“并发执行效率优化”而非“资源治理”&lt;/strong&gt;：改善多进程并发的利用方式，但并不天然提供“多租户隔离语义”。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;适配负载类型&lt;/strong&gt;：对某些 workload 显著收益，但对推理/多租户治理不一定直接等价。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;工程落点微妙&lt;/strong&gt;：经常出现在数据平面方案的“内部实现”中，而不是用户显式选择的产品特性。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;适用场景：协作式多进程计算、HPC/训练类并发模式；在平台侧更常作为内部优化手段。&lt;/p&gt;
&lt;h3 id="容器设备暴露与注入机制cdi-让怎么把设备交付给容器更标准化"&gt;容器设备暴露与注入机制：CDI 让“怎么把设备交付给容器”更标准化&lt;/h3&gt;
&lt;p&gt;无论你使用 MIG、vGPU 还是时间片，最终都要回答一个问题：&lt;strong&gt;设备如何以一致、可审计、可组合的方式注入到容器运行时&lt;/strong&gt;。NVIDIA Container Toolkit 已支持生成 CDI（Container Device Interface，容器设备接口）规范，用于标准化“容器如何使用设备”的描述。&lt;/p&gt;
&lt;p&gt;这不是隔离机制本身，但它影响方案的可落地性：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;能否把设备注入从“运行时魔法参数”变成“声明式、可审计、可复制的交付单元”。&lt;/li&gt;
&lt;li&gt;能否在多种运行时/编排方式中复用同一套设备交付逻辑。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="五维对比基线把概念争论变成可回填的矩阵"&gt;五维对比基线：把概念争论变成可回填的矩阵&lt;/h2&gt;
&lt;p&gt;为了便于后续章节统一对比，下面给出一张五维对比表，涵盖主流机制的资源单位、隔离强度、性能损耗、动态调整成本和兼容性等维度。&lt;/p&gt;
&lt;p&gt;表格用于对比各类 GPU 共享机制的核心特征：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;机制类型&lt;/th&gt;
&lt;th&gt;资源单位&lt;/th&gt;
&lt;th&gt;隔离强度&lt;/th&gt;
&lt;th&gt;性能损耗/干扰&lt;/th&gt;
&lt;th&gt;动态调整成本&lt;/th&gt;
&lt;th&gt;兼容性/落地复杂度&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;独占（整卡）&lt;/td&gt;
&lt;td&gt;整卡&lt;/td&gt;
&lt;td&gt;最高&lt;/td&gt;
&lt;td&gt;最稳定&lt;/td&gt;
&lt;td&gt;低&lt;/td&gt;
&lt;td&gt;最简单&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;硬切分（MIG）&lt;/td&gt;
&lt;td&gt;离散实例&lt;/td&gt;
&lt;td&gt;高（硬件路径隔离）&lt;/td&gt;
&lt;td&gt;较稳定&lt;/td&gt;
&lt;td&gt;中 - 高&lt;/td&gt;
&lt;td&gt;较好&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;vGPU/mdev&lt;/td&gt;
&lt;td&gt;离散 profile/虚拟设备&lt;/td&gt;
&lt;td&gt;中 - 高（依实现）&lt;/td&gt;
&lt;td&gt;中（依实现）&lt;/td&gt;
&lt;td&gt;中&lt;/td&gt;
&lt;td&gt;高（栈复杂）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;时间片&lt;/td&gt;
&lt;td&gt;份额/过量订阅（时间片）&lt;/td&gt;
&lt;td&gt;低 - 中&lt;/td&gt;
&lt;td&gt;干扰显著（看负载）&lt;/td&gt;
&lt;td&gt;低&lt;/td&gt;
&lt;td&gt;中（需策略兜底）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MPS&lt;/td&gt;
&lt;td&gt;非显式单位&lt;/td&gt;
&lt;td&gt;低（偏效率优化）&lt;/td&gt;
&lt;td&gt;依负载而定&lt;/td&gt;
&lt;td&gt;低&lt;/td&gt;
&lt;td&gt;中（对模型/作业形态敏感）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CDI（交付层）&lt;/td&gt;
&lt;td&gt;设备交付单元&lt;/td&gt;
&lt;td&gt;不定义隔离&lt;/td&gt;
&lt;td&gt;不直接影响&lt;/td&gt;
&lt;td&gt;低&lt;/td&gt;
&lt;td&gt;降低集成碎片&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figcaption class="text-center mb-3"&gt;
表 1: GPU 共享机制五维对比基线
&lt;/figcaption&gt;
&lt;h2 id="组合规律端到端方案通常是控制面治理--数据面机制--观测计量"&gt;组合规律：端到端方案通常是“控制面治理 + 数据面机制 + 观测计量”&lt;/h2&gt;
&lt;p&gt;理解数据平面谱系后，端到端方案的组合就会更清晰：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;先确定资源单位&lt;/strong&gt;：整卡 / MIG / vGPU / 时间片份额。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;再补齐治理能力&lt;/strong&gt;：队列、配额、公平性、准入、优先级（控制面）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;最后用观测与计量闭环&lt;/strong&gt;：否则“共享”只是在赌负载行为（后续《观测与计量》《验收与容量》会详细展开）。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="本章小结与下一步阅读建议"&gt;本章小结与下一步阅读建议&lt;/h2&gt;
&lt;p&gt;通过本章梳理，你可以更系统地理解 GPU 共享的底层机制和工程落点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;如果你追求“可声明、可治理、可验收”的共享，第一步不是选项目，而是先落到谱系上，明确你要的隔离强度与资源单位。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MIG 与时间片不是同一类问题的不同实现&lt;/strong&gt;：它们的隔离语义与风险曲线完全不同。&lt;/li&gt;
&lt;li&gt;Kubernetes 的设备扩展能力（Device Plugin / DRA）解决“如何让调度器看到设备”，但不替你解决“如何切分与隔离”。&lt;/li&gt;
&lt;li&gt;如果你发现团队在争论“谁更强”，建议把争论强制落到上面的五维矩阵里：只讨论机制与可验证指标，不讨论口号。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;下一章将从谱系切入“硬切分”的代表机制——MIG，并用实验验证隔离与干扰的边界条件。&lt;/p&gt;
&lt;h2 id="总结"&gt;总结&lt;/h2&gt;
&lt;p&gt;本章从数据平面谱系的角度，系统梳理了 GPU 共享机制的多样性与复杂性。通过对比不同机制的特征与适用场景，为后续章节深入探讨具体机制奠定了基础。理解这些基础知识后，读者可以更有针对性地选择和优化适合自己需求的 GPU 共享方案。&lt;/p&gt;
&lt;h2 id="参考文献"&gt;参考文献&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins/" target="_blank" rel="noopener"&gt;Device Plugins - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/scheduling-eviction/dynamic-resource-allocation/" target="_blank" rel="noopener"&gt;Dynamic Resource Allocation - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.nvidia.com/datacenter/tesla/mig-user-guide/introduction.html" target="_blank" rel="noopener"&gt;Introduction — NVIDIA Multi-Instance GPU User Guide - docs.nvidia.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.nvidia.com/vgpu/latest/grid-vgpu-user-guide/index.html" target="_blank" rel="noopener"&gt;Virtual GPU Software User Guide - docs.nvidia.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/gpu-sharing.html" target="_blank" rel="noopener"&gt;Time-Slicing GPUs in Kubernetes — NVIDIA GPU Operator - docs.nvidia.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.nvidia.com/deploy/mps/index.html" target="_blank" rel="noopener"&gt;Multi-Process Service - docs.nvidia.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/cdi-support.html" target="_blank" rel="noopener"&gt;Support for Container Device Interface - docs.nvidia.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.nvidia.com/datacenter/tesla/mig-user-guide/" target="_blank" rel="noopener"&gt;MIG User Guide - docs.nvidia.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>MIG：强隔离的资源单位与运维代价</title><link>https://jimmysong.io/zh/book/gpu-infra/data-plane/mig/</link><pubDate>Tue, 30 Dec 2025 05:02:43 +0000</pubDate><author>Jimmy Song</author><guid>https://jimmysong.io/zh/book/gpu-infra/data-plane/mig/</guid><description>聚焦 MIG 的工程事实：强隔离的来源、离散单位的约束、重配置成本与调度耦合。</description><content:encoded>
&lt;blockquote&gt;
&lt;p&gt;MIG 的本质是用硬件级隔离换取可预测性，但离散资源单位和重配置成本也带来了新的工程挑战。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="mig-解决的到底是什么问题"&gt;MIG 解决的到底是什么问题&lt;/h2&gt;
&lt;p&gt;在真实的在线推理/多租户平台里，GPU 的主要矛盾往往不是“能不能共享”，而是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;共享后能否给出稳定的尾延迟（P95/P99）与吞吐承诺&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;共享后是否能避免跨租户干扰（noisy neighbor）&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;是否能做“可验收”的资源交付（SLA/QoS）&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;MIG 的设计动机就是把“一张卡”划分为多个&lt;strong&gt;彼此隔离的实例&lt;/strong&gt;，每个实例拥有独立的高带宽显存、缓存与计算资源，从而获得更可预测的性能与 QoS。&lt;/p&gt;
&lt;p&gt;这也是为什么 MIG 常被用于：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;多租户推理服务（尤其是对尾延迟敏感的场景）&lt;/li&gt;
&lt;li&gt;共享研发集群（不同团队并行试验但需要隔离）&lt;/li&gt;
&lt;li&gt;需要较强&amp;quot;资源边界&amp;quot;的 MLOps 平台&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class="mx-auto text-center"&gt;
&lt;img src="https://assets.jimmysong.io/images/book/gpu-infra/data-plane/mig/mig-instance-partition-zh.svg" data-img="https://assets.jimmysong.io/images/book/gpu-infra/data-plane/mig/mig-instance-partition-zh.svg" alt="图 1: MIG 多实例 GPU 架构" data-caption="图 1: MIG 多实例 GPU 架构"
width="1505"
height="1103"
loading="lazy" decoding="async" class="image-loading"
onload="this.classList.remove('image-loading'); this.classList.add('image-loaded');"
onerror="handleImageError(this); this.classList.remove('image-loading');"&gt;
&lt;figcaption&gt;图 1: MIG 多实例 GPU 架构&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="关键概念实例离散-profile-与几何形状"&gt;关键概念：实例、离散 Profile 与“几何形状”&lt;/h2&gt;
&lt;p&gt;MIG 在概念上至少要分清两层：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;GPU Instance（GI）&lt;/strong&gt;：可以理解为“显存 + 一部分 GPU 资源”的大切片边界。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Compute Instance（CI）&lt;/strong&gt;：在 GI 内进一步划出可执行计算的单位（具体实现细节随架构/代际演进而变化）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;你不需要在本章穷尽 GI/CI 的所有细节，但必须形成一个直觉：&lt;strong&gt;MIG 的资源单位不是连续可调的，而是预定义的离散档位（profiles）&lt;/strong&gt;。这意味着：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;你可以得到强隔离，但只能在若干固定档位中选；&lt;/li&gt;
&lt;li&gt;你会遇到“内部碎片”（例如需要 9GB 显存但只能用 10GB 档位）；&lt;/li&gt;
&lt;li&gt;你会遇到“组合碎片”（某个节点上 MIG profile 的组合不再适配新工作负载）。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;一个常见误区是把 MIG 当成&amp;quot;GPU 的 cgroup&amp;quot;。事实恰好相反：MIG 更像把一张卡变成一个&lt;strong&gt;离散设备池&lt;/strong&gt;，每个实例是一个&amp;quot;新设备&amp;quot;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure class="mx-auto text-center"&gt;
&lt;img src="https://assets.jimmysong.io/images/book/gpu-infra/data-plane/mig/gi-ci-hierarchy-zh.svg" data-img="https://assets.jimmysong.io/images/book/gpu-infra/data-plane/mig/gi-ci-hierarchy-zh.svg" alt="图 2: GI/CI 层次关系" data-caption="图 2: GI/CI 层次关系"
width="1507"
height="1184"
loading="lazy" decoding="async" class="image-loading"
onload="this.classList.remove('image-loading'); this.classList.add('image-loaded');"
onerror="handleImageError(this); this.classList.remove('image-loading');"&gt;
&lt;figcaption&gt;图 2: GI/CI 层次关系&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="为什么说-mig-是强隔离"&gt;为什么说 MIG 是“强隔离”&lt;/h2&gt;
&lt;p&gt;多数软件级共享方案（time-slicing、进程级复用、显存软限制、MPS 等）最终都绕不开一个问题：&lt;strong&gt;隔离强度依赖实现细节与负载行为&lt;/strong&gt;，一旦负载模式变化，干扰就会暴露在尾延迟上。&lt;/p&gt;
&lt;p&gt;MIG 的核心优势在于：它把“隔离”下沉到了硬件层，把一张 GPU 分成多个&lt;strong&gt;完全隔离&lt;/strong&gt;的实例，每个实例拥有自己的显存分区、缓存与计算核心。&lt;/p&gt;
&lt;p&gt;你可以把它视为三类隔离的组合：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;显存隔离&lt;/strong&gt;：显存是第一约束，隔离能显著降低 OOM 与抢占式抖动的外溢。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;缓存/片上资源隔离&lt;/strong&gt;：降低跨租户争抢带来的长尾。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;计算资源隔离&lt;/strong&gt;：减少“同卡不同进程”互相挤占 SM 的不确定性。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这些特性共同指向一个结论：&lt;strong&gt;MIG 适合&amp;quot;把可预测性当成第一原则&amp;quot;的平台型场景。&lt;/strong&gt;&lt;/p&gt;
&lt;figure class="mx-auto text-center"&gt;
&lt;img src="https://assets.jimmysong.io/images/book/gpu-infra/data-plane/mig/isolation-comparison-zh.svg" data-img="https://assets.jimmysong.io/images/book/gpu-infra/data-plane/mig/isolation-comparison-zh.svg" alt="图 3: 隔离方案对比：软件 vs 硬件" data-caption="图 3: 隔离方案对比：软件 vs 硬件"
width="1505"
height="1271"
loading="lazy" decoding="async" class="image-loading"
onload="this.classList.remove('image-loading'); this.classList.add('image-loaded');"
onerror="handleImageError(this); this.classList.remove('image-loading');"&gt;
&lt;figcaption&gt;图 3: 隔离方案对比：软件 vs 硬件&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="代价一资源单位离散带来的碎片与弹性边界"&gt;代价一：资源单位离散带来的碎片与弹性边界&lt;/h2&gt;
&lt;p&gt;MIG 允许把 GPU 分成最多若干个实例（以代际/型号为准），但它不是任意分配，而是按照固定 profile 组合。&lt;/p&gt;
&lt;p&gt;这带来两个直接后果：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;资源匹配是离散优化问题&lt;/strong&gt;：调度从“填箱（bin packing）”进一步变成“带 profile 约束的填箱”。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;弹性变差&lt;/strong&gt;：当你的负载形态频繁变化，MIG 的 profile 组合很可能需要重配；而重配本身就是强运维动作（见下一节）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="典型碎片模式"&gt;典型碎片模式&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;内部碎片&lt;/strong&gt;：申请略高于某档位阈值导致整体浪费。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;组合碎片&lt;/strong&gt;：节点上剩余的实例组合无法拼出新任务需要的 profile（即使总剩余显存看起来足够）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;集群碎片&lt;/strong&gt;：不同节点的 MIG“几何形状”不一致，导致队列层面长期排队与倾斜。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;因此，MIG 更适合：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;工作负载形态相对稳定（例如固定几类模型推理）&lt;/li&gt;
&lt;li&gt;你愿意用&lt;strong&gt;节点池分层&lt;/strong&gt;消化异构（把不同 MIG geometry 放在不同 nodepool）&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class="mx-auto text-center"&gt;
&lt;img src="https://assets.jimmysong.io/images/book/gpu-infra/data-plane/mig/fragmentation-examples-zh.svg" data-img="https://assets.jimmysong.io/images/book/gpu-infra/data-plane/mig/fragmentation-examples-zh.svg" alt="图 4: 碎片化问题：离散档位的代价" data-caption="图 4: 碎片化问题：离散档位的代价"
width="1505"
height="1221"
loading="lazy" decoding="async" class="image-loading"
onload="this.classList.remove('image-loading'); this.classList.add('image-loaded');"
onerror="handleImageError(this); this.classList.remove('image-loading');"&gt;
&lt;figcaption&gt;图 4: 碎片化问题：离散档位的代价&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="代价二重配置是运维动作且与调度强耦合"&gt;代价二：重配置是运维动作，且与调度强耦合&lt;/h2&gt;
&lt;p&gt;在 Kubernetes 语境下，这是 MIG 的最大“隐藏成本”。&lt;/p&gt;
&lt;p&gt;以 NVIDIA GPU Operator 的 MIG 支持为例：其 MIG Manager 在配置 GPU 的 MIG 模式或 geometry 时，&lt;strong&gt;要求被配置的 GPU 上没有用户工作负载在运行&lt;/strong&gt;；在一些云环境里甚至可能需要重启节点，因此往往需要先 cordon/drain。&lt;/p&gt;
&lt;p&gt;这意味着：&lt;strong&gt;MIG 的几何形状不是一个可以随业务波动频繁调整的弹性旋钮&lt;/strong&gt;。你一旦把“动态重配”当成常规手段，就会把平台稳定性拖入运维地狱：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;需要编排停机窗口或迁移机制&lt;/li&gt;
&lt;li&gt;需要在队列/调度层面协调重配时机&lt;/li&gt;
&lt;li&gt;需要清晰的“重配触发条件”与回滚策略&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="正确姿势把-mig-当成预切分设备池"&gt;正确姿势：把 MIG 当成“预切分设备池”&lt;/h3&gt;
&lt;p&gt;更现实的工程策略是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;按 nodepool 预设 MIG geometry&lt;/strong&gt;，将其当成“节点属性”&lt;/li&gt;
&lt;li&gt;通过标签/taint/affinity 把不同工作负载导向合适的几何池&lt;/li&gt;
&lt;li&gt;由控制面（队列、配额、优先级）来做治理，而不是靠频繁改几何来追逐短期利用率&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="kubernetes-集成资源语义与暴露策略"&gt;Kubernetes 集成：资源语义与暴露策略&lt;/h2&gt;
&lt;p&gt;Kubernetes 的扩展资源（extended resources）天然更接近“设备分配”，而不是“可分配的连续度量”。这与 MIG 的“实例就是设备”非常契合：MIG 实例可以被暴露为独立资源类型，由调度器做整数分配。&lt;/p&gt;
&lt;p&gt;在 Kubernetes 中最常见的暴露方式是 NVIDIA k8s-device-plugin。它支持通过 &lt;code&gt;MIG_STRATEGY&lt;/code&gt; 决定如何在节点上暴露 MIG 设备：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;none&lt;/code&gt;：不区分 MIG 与否，仍以 &lt;code&gt;nvidia.com/gpu&lt;/code&gt; 暴露整卡&lt;/li&gt;
&lt;li&gt;&lt;code&gt;single&lt;/code&gt;：只暴露 MIG 设备（并要求节点上的 MIG 配置一致性更强）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mixed&lt;/code&gt;：同时暴露整卡与 MIG 设备（更灵活，但治理复杂度更高）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;你在本书后续章节会看到：&lt;strong&gt;“mixed 能力”经常被误用&lt;/strong&gt;——它会让资源目录更丰富，但也会让配额、计量与公平性更难解释。除非你有明确的治理模型，否则更推荐以 nodepool 隔离的方式管理“整卡池 vs MIG 池”。&lt;/p&gt;
&lt;p&gt;如果你把 GPU 共享方案放回本书的控制面地图，MIG 的定位非常清晰：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;数据平面：硬切分 + 强隔离&lt;/li&gt;
&lt;li&gt;控制面：把每个 MIG 实例当成独立设备，做队列/配额/优先级治理&lt;/li&gt;
&lt;li&gt;端到端：适合&amp;quot;可声明、可验收&amp;quot;的资源交付，而不是追求极限的细粒度弹性&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class="mx-auto text-center"&gt;
&lt;img src="https://assets.jimmysong.io/images/book/gpu-infra/data-plane/mig/k8s-mig-integration-zh.svg" data-img="https://assets.jimmysong.io/images/book/gpu-infra/data-plane/mig/k8s-mig-integration-zh.svg" alt="图 5: Kubernetes MIG 集成架构" data-caption="图 5: Kubernetes MIG 集成架构"
width="1507"
height="1584"
loading="lazy" decoding="async" class="image-loading"
onload="this.classList.remove('image-loading'); this.classList.add('image-loaded');"
onerror="handleImageError(this); this.classList.remove('image-loading');"&gt;
&lt;figcaption&gt;图 5: Kubernetes MIG 集成架构&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="hands-on用你的两台-a100mig-开关建立直觉"&gt;Hands-on：用你的两台 A100（MIG 开/关）建立直觉&lt;/h2&gt;
&lt;p&gt;你当前环境非常适合做一组“对照实验”：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;机器 1：A100，MIG Disabled（整卡共享只能依赖软件方案）&lt;/li&gt;
&lt;li&gt;机器 2：A100，MIG Enabled（硬切分、多实例隔离）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;建议把本章的 hands-on 目标定义为三件事：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;确认资源单位变化&lt;/strong&gt;：从 1 张 GPU 变成 N 个 MIG 设备&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;确认 K8s 暴露语义&lt;/strong&gt;：Pod 以“设备数量”申请 MIG profile&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;确认隔离收益与边界&lt;/strong&gt;：干扰是否显著降低、但 profile 是否带来碎片与重配成本&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;下面给出一个最小操作路径，便于读者复现。具体命令可在 Lab 章节展开。&lt;/p&gt;
&lt;h3 id="在-mig-节点上确认-mig-设备枚举"&gt;在 MIG 节点上确认 MIG 设备枚举&lt;/h3&gt;
&lt;p&gt;可以通过如下命令列举 MIG 设备和实例：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 机器 2（MIG Enabled）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nvidia-smi -L
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nvidia-smi mig -lgi &lt;span class="c1"&gt;# 列出 GPU instances&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nvidia-smi mig -lci &lt;span class="c1"&gt;# 列出 compute instances（如适用）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;观察点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;输出中是否出现多个 MIG 设备条目（每个条目是一个“新设备”）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="在-kubernetes-中暴露-mig-资源"&gt;在 Kubernetes 中暴露 MIG 资源&lt;/h3&gt;
&lt;p&gt;如果你使用 NVIDIA device plugin / GPU Operator，核心是选定 MIG 暴露策略（&lt;code&gt;single&lt;/code&gt; 或 &lt;code&gt;mixed&lt;/code&gt;），并让节点上报对应资源。&lt;/p&gt;
&lt;p&gt;常见的现象是：Node 的 &lt;code&gt;Capacity/Allocatable&lt;/code&gt; 会出现类似 &lt;code&gt;nvidia.com/mig-&amp;lt;profile&amp;gt;&lt;/code&gt; 的资源项（profile 具体命名依赖实现与配置）。&lt;/p&gt;
&lt;h3 id="用一个最小-pod-验证按-mig-设备分配"&gt;用一个最小 Pod 验证“按 MIG 设备分配”&lt;/h3&gt;
&lt;p&gt;以下 YAML 用于验证 Pod 能否按 MIG 设备分配：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Pod&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;mig-smoke-test&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;restartPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Never&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;cuda&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;nvidia/cuda:12.4.1-base-ubuntu22.04&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;bash&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;-lc&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;nvidia-smi &amp;amp;&amp;amp; sleep 3600&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 这里的资源名需要替换成你集群实际暴露的 MIG profile&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 例如 nvidia.com/mig-1g.5gb: 1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;nvidia.com/mig-&amp;lt;profile&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;观察点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pod 是否被调度到 MIG 节点&lt;/li&gt;
&lt;li&gt;容器内 &lt;code&gt;nvidia-smi&lt;/code&gt; 看到的设备是否是 MIG instance&lt;/li&gt;
&lt;li&gt;同一张卡上并行跑多个相同 profile 的 Pod 时，是否表现出更稳定的尾延迟（在后续 Lab 用基准测量）&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="把-mig-回填到决策轴矩阵"&gt;把 MIG 回填到“决策轴矩阵”&lt;/h2&gt;
&lt;p&gt;你可以把 MIG 在本书决策轴中先填一个“默认结论”，后续再用实验数据修正：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;资源单位&lt;/strong&gt;：离散（profile 驱动），可作为独立设备暴露&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;隔离强度&lt;/strong&gt;：强（硬件隔离，QoS 更可预测）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;性能损耗/干扰&lt;/strong&gt;：干扰显著降低；但不同 profile 的绝对性能上限受切分约束&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;运维重配置成本&lt;/strong&gt;：高（改模式/几何通常要求无用户负载，可能需 cordon/drain，部分环境需重启）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;兼容性/侵入性&lt;/strong&gt;：对应用相对透明（像“拿到一块小 GPU”），但对平台治理模型要求更高&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;异构扩展路径&lt;/strong&gt;：适合用 nodepool/标签把几何形状固化为“节点属性”&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="总结"&gt;总结&lt;/h2&gt;
&lt;p&gt;MIG 不是“通用 GPU 共享”的终点，而是一个非常清晰的工程选择：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;当你的首要目标是&lt;strong&gt;隔离与可预测性&lt;/strong&gt;：MIG 常是最省心的硬件路径。&lt;/li&gt;
&lt;li&gt;当你的首要目标是&lt;strong&gt;极致弹性与细粒度分配&lt;/strong&gt;：MIG 的离散 profile 与重配成本会成为结构性瓶颈。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在本书后续章节，我们会用同一组决策轴去对比：MIG、HAMi（软件级 vGPU/共享）、以及 time-slicing 等机制，并在你的两台 A100 环境上做可复现实验，把“直觉判断”变成“可验收结论链”。&lt;/p&gt;
&lt;h2 id="参考资料"&gt;参考资料&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.nvidia.com/datacenter/tesla/pdf/MIG_User_Guide.pdf" target="_blank" rel="noopener"&gt;NVIDIA MIG 用户指南 - docs.nvidia.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.nvidia.com/en-us/technologies/multi-instance-gpu/" target="_blank" rel="noopener"&gt;NVIDIA Multi-Instance GPU 技术介绍 - nvidia.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/gpu-operator-mig.html" target="_blank" rel="noopener"&gt;NVIDIA GPU Operator MIG 官方文档 - docs.nvidia.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>HAMi：可声明共享的虚拟化数据平面</title><link>https://jimmysong.io/zh/book/gpu-infra/data-plane/hami/</link><pubDate>Tue, 30 Dec 2025 05:01:54 +0000</pubDate><author>Jimmy Song</author><guid>https://jimmysong.io/zh/book/gpu-infra/data-plane/hami/</guid><description>从数据平面视角拆解 HAMi，聚焦细粒度资源单位、共享治理、隔离与兼容性的工程权衡及适用场景。</description><content:encoded>
&lt;blockquote&gt;
&lt;p&gt;让 GPU 共享成为可声明、可治理的工程能力，而非“能跑就行”的经验主义。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="hami-的一句话定位"&gt;HAMi 的一句话定位&lt;/h2&gt;
&lt;p&gt;HAMi 是一个面向 Kubernetes 的 GPU 虚拟化与切分数据平面。它致力于将“GPU 共享”从经验主义的“能跑”提升为工程语义上的“可声明、可调度、可治理”。HAMi 的核心并非重写调度器，而是将 GPU 的可用资源单位从“整卡整数”扩展为“可切分的份额（core/memory 等）”，并将这些份额暴露为 Kubernetes 可理解的资源请求与分配路径。&lt;/p&gt;
&lt;h2 id="为什么-hami-必须出现在数据平面"&gt;为什么 HAMi 必须出现在数据平面&lt;/h2&gt;
&lt;p&gt;Kubernetes 对设备类资源的默认语义是“整数、不可超卖、调度时做计数”。这套模型非常适合网卡、FPGA、整卡 GPU，但对于可共享、可切分且隔离与干扰复杂的 GPU，会自然推向两种极端：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;要么&lt;/strong&gt;继续整卡分配，把利用率问题交给业务侧自己排队；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;要么&lt;/strong&gt;把共享做成容器内自觉，但无法声明与治理，难以实现队列、配额、优先级等上层策略闭环。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;HAMi 的选择是：&lt;strong&gt;在不要求应用改代码的前提下&lt;/strong&gt;，将“共享”做成数据平面能力，并把更细粒度的资源表达暴露为 Kubernetes 可调度资源。&lt;/p&gt;
&lt;h2 id="组件视图hami-是一条分配链路"&gt;组件视图：HAMi 是一条“分配链路”&lt;/h2&gt;
&lt;p&gt;理解 HAMi 最好的方式，是将其视为一条从“声明”到“生效”的分配链路。典型链路可拆为四层（实现细节随版本演进，但职责基本稳定）：&lt;/p&gt;
&lt;p&gt;在介绍各层职责前，先说明：每一层都围绕资源声明、调度、兑现与观测展开，形成完整的治理闭环。&lt;/p&gt;
&lt;p&gt;下图概括 HAMi 从声明到兑现的分配链路与治理闭环。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;HAMi 分配链路示意图&lt;/strong&gt;：展示从节点侧发现与汇报、调度侧绑定与落位、容器内资源控制到观测与计量的完整四层架构。每一层都围绕资源声明、调度、兑现与观测展开，形成完整的治理闭环。Device Plugin 负责声明，Scheduler 负责落位，容器内控制层负责兑现，监控负责将兑现程度转化为可运维数据。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure class="mx-auto text-center"&gt;
&lt;img src="https://assets.jimmysong.io/images/book/gpu-infra/data-plane/hami/hami-allocation-chain.svg" data-img="https://assets.jimmysong.io/images/book/gpu-infra/data-plane/hami/hami-allocation-chain.svg" alt="图 1: HAMi 分配链路" data-caption="图 1: HAMi 分配链路"
width="1763"
height="461"
loading="lazy" decoding="async" class="image-loading"
onload="this.classList.remove('image-loading'); this.classList.add('image-loaded');"
onerror="handleImageError(this); this.classList.remove('image-loading');"&gt;
&lt;figcaption&gt;图 1: HAMi 分配链路&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;节点侧发现与汇报（Device Plugin 侧）&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;负责发现 GPU，并将“可分配资源”汇报给 Kubelet/调度器可见的资源视图。&lt;/li&gt;
&lt;li&gt;与默认整卡模型相比，HAMi 会把物理 GPU 映射为可被多 Pod 共享的更细粒度资源单元，并暴露相应资源名（如 core / memory 维度）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;调度侧绑定与落位（Scheduler 扩展/策略侧）&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;负责将“请求”落到具体哪张卡、哪类卡、哪组份额。&lt;/li&gt;
&lt;li&gt;关键在于将拓扑、碎片、同卡干扰等数据平面约束转化为调度可见的约束条件。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;容器内资源控制（HAMi-core / vGPU 控制层）&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;负责让“声明的份额”在容器内尽可能生效。例如对 core 份额采用 time-slicing 实现配额效果，并解释为何在 &lt;code&gt;nvidia-smi&lt;/code&gt; 里看到的利用率会波动。&lt;/li&gt;
&lt;li&gt;工程实现上，通常通过拦截 CUDA Runtime 与 Driver 之间的调用链路实现控制与计量（产物多以注入动态库形式出现）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;观测与计量（vGPUmonitor / metrics 导出）&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;负责将“共享后到底谁占了多少”转化为 Prometheus 可抓取的指标，形成治理闭环的基础数据。计量缺失意味着无法计费、无法做容量评估，也无法做 SLO。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;你可以将这条链路概括为：&lt;strong&gt;Device Plugin 负责声明，Scheduler 负责落位，容器内控制层负责兑现，监控负责将兑现程度转化为可运维数据。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="资源表达从整卡到可声明共享的关键语义"&gt;资源表达：从&amp;quot;整卡&amp;quot;到&amp;quot;可声明共享&amp;quot;的关键语义&lt;/h2&gt;
&lt;p&gt;HAMi 的工程收益，核心在于引入了更细粒度的资源表达方式，使 Kubernetes 调度与上层控制面能够&amp;quot;看到&amp;quot;你真正需要的资源。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;HAMi 资源表达示意图&lt;/strong&gt;：对比传统整卡分配模型和 HAMi 可声明共享模型，展示如何通过 GPU 份额（虚拟 GPU/slice）、Core 份额（nvidia.com/gpucores）和 Memory 份额（nvidia.com/gpumem）实现显存与 core 份额可声明，使&amp;quot;同卡复用&amp;quot;更可控。图中还包含 Pod 资源声明示例 YAML。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure class="mx-auto text-center"&gt;
&lt;img src="https://assets.jimmysong.io/images/book/gpu-infra/data-plane/hami/hami-resource-expression.svg" data-img="https://assets.jimmysong.io/images/book/gpu-infra/data-plane/hami/hami-resource-expression.svg" alt="图 2: HAMi 资源表达：从整卡到可声明共享" data-caption="图 2: HAMi 资源表达：从整卡到可声明共享"
width="1745"
height="1395"
loading="lazy" decoding="async" class="image-loading"
onload="this.classList.remove('image-loading'); this.classList.add('image-loaded');"
onerror="handleImageError(this); this.classList.remove('image-loading');"&gt;
&lt;figcaption&gt;图 2: HAMi 资源表达：从整卡到可声明共享&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;典型做法是让 Pod 在资源请求里同时声明：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;GPU 份额（虚拟 GPU / slice）&lt;/strong&gt;：让一张物理卡可被多个 Pod 分配。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;core 份额（如 &lt;code&gt;nvidia.com/gpucores&lt;/code&gt;）&lt;/strong&gt;：用 time-slicing 近似实现计算份额控制。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;memory 份额（如 &lt;code&gt;nvidia.com/gpumem&lt;/code&gt;）&lt;/strong&gt;：将“显存第一约束”显式化，避免仅按整卡计数导致的资源错配与碎片放大。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这里有一个重要边界需明确：&lt;strong&gt;“可声明”不等于“强隔离”&lt;/strong&gt;。HAMi 在 core 维度更接近“可控的时间片分配”；在显存维度则更接近“配额化的分配与失败策略（超额时的表现）”。因此，HAMi 提供的是“比整卡更强的治理语义”，而非类似 MIG（Multi-Instance GPU, Multi-Instance GPU）那样的硬切分级别隔离。&lt;/p&gt;
&lt;h2 id="关键取舍hami-解决的是运维问题不是物理隔离问题"&gt;关键取舍：HAMi 解决的是“运维问题”，不是“物理隔离问题”&lt;/h2&gt;
&lt;p&gt;从工程视角看，HAMi 的核心价值不在于“能否共享”，而在于是否让以下问题具备可操作性：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;可声明：把共享从“隐性行为”变成“显式契约”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;有了契约，才有治理。HAMi 的资源表达让你能在 YAML 里明确声明：需要多少 core、多少显存、是否允许与别人同卡。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;可调度：把碎片与落位变成系统责任&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;资源单位变细后，碎片必然增多。HAMi 的价值之一，是让“碎片管理/落位策略”进入调度责任域，而非留给业务侧碰运气。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;可观测：共享后的 P99 才是问题本体&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;GPU 共享的难点不在平均吞吐，而在尾延迟与抖动。HAMi 通过监控与计量组件，将共享后的使用情况导出为指标，为后续“验收与容量”章节铺路。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;可协同：为 Volcano/Kueue 提供“可用的资源语义”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Volcano/Kueue 解决队列、配额、公平性、优先级、准入与抢占等控制面问题；HAMi 解决“节点 GPU 能怎样切分、切完如何落位、如何兑现”的数据平面问题。两者叠加，才能形成完整的 GPU 资源运维系统。&lt;/p&gt;
&lt;h2 id="适用场景与反模式"&gt;适用场景与反模式&lt;/h2&gt;
&lt;p&gt;在实际应用中，HAMi 更适合以下场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;多租户推理、批量小模型推理：显存与 core 份额可声明，使“同卡复用”更可控。&lt;/li&gt;
&lt;li&gt;研发/测试/POC 环境：需要快速提升 GPU 利用率，并积累计量与基线数据。&lt;/li&gt;
&lt;li&gt;平台化团队：可将 HAMi 语义与企业内部队列/配额体系打通，形成治理闭环。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;需要谨慎的场景或需额外验收门槛：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;强隔离/强确定性 SLO 的关键在线业务：如需接近物理级隔离（尤其尾延迟敏感），建议优先考虑 MIG 或整卡池化。&lt;/li&gt;
&lt;li&gt;对驱动/运行时链路极其敏感的生产环境：任何“容器内拦截/注入”方案都要求完善升级验证、兼容性矩阵与故障回滚机制。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="如何把-hami-放进本书的决策轴"&gt;如何把 HAMi 放进本书的“决策轴”&lt;/h2&gt;
&lt;p&gt;你可以用以下结论，将 HAMi 快速回填到“决策轴矩阵”中（后续实验章节会用数据验证）：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;资源单位&lt;/strong&gt;：从整卡扩展到 core/mem 份额与共享 slice。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;隔离强度&lt;/strong&gt;：总体偏“软隔离/工程约束”，非硬切分。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;动态调整成本&lt;/strong&gt;：通常低于 MIG（无需重切分设备），但依赖控制链路与策略配置成熟度。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;性能与干扰&lt;/strong&gt;：平均吞吐通常可接受，关键在 P99 与干扰控制，需要用 Lab 体系验收。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可观测与计量&lt;/strong&gt;：具备导出指标的路径，是实现运维闭环的重要加分项。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;兼容性/侵入性&lt;/strong&gt;：对应用代码侵入低（无需改代码），但对运行时/驱动链路与运维流程有要求。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="总结"&gt;总结&lt;/h2&gt;
&lt;p&gt;HAMi 的本质是将 GPU 共享变成工程语义的虚拟化数据平面。它让资源可以被声明、调度、计量，从而让控制面（如 Volcano、Kueue）有机会将队列、配额、优先级等治理能力落到 GPU 这一类复杂资源上。HAMi 并不承诺 MIG 级别的强隔离，而是用更低的重配置成本与更强的运维语义，换取更高的整体利用率与可治理性。&lt;/p&gt;
&lt;p&gt;下一章“生态放置”将把 HAMi、MIG、Volcano、Kueue 及典型推理/训练栈放入同一张拼装图，明确每一层的职责，避免“用数据平面能力替代控制面治理”的常见误区。&lt;/p&gt;
&lt;h2 id="参考文献"&gt;参考文献&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Project-HAMi/HAMi" target="_blank" rel="noopener"&gt;GitHub - Project-HAMi/HAMi: Heterogeneous AI Computing Virtualization Middleware(Project under CNCF) - github.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://project-hami.io/docs/userguide/nvidia-device/examples/allocate-device-core/?utm_source=chatgpt.com" target="_blank" rel="noopener"&gt;Allocate device core resource - project-hami.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://koordinator.sh/docs/next/user-manuals/device-scheduling-gpu-share-with-hami?utm_source=chatgpt.com" target="_blank" rel="noopener"&gt;Device Scheduling - GPU Share With HAMi - koordinator.sh&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>DRA：Kubernetes 设备资源分配的下一代 API</title><link>https://jimmysong.io/zh/book/gpu-infra/data-plane/dra/</link><pubDate>Sun, 19 Apr 2026 00:00:00 +0000</pubDate><author>Jimmy Song</author><guid>https://jimmysong.io/zh/book/gpu-infra/data-plane/dra/</guid><description>深入分析 DRA 的架构动机、API 机制与设计取舍，理解它如何从 Device Plugin 的 Allocate 黑盒走向可声明、可推理的资源分配。</description><content:encoded>
&lt;blockquote&gt;
&lt;p&gt;DRA 的核心价值不是“替代 Device Plugin”，而是把设备分配从节点本地的 Allocate 黑盒推进到控制面可见、可审计、可组合的资源 API。这个转变对 GPU 调度体系的影响是结构性的。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;在前面 &lt;a href="../../fundamentals/k8s-device-model/"&gt;Kubernetes 设备资源模型&lt;/a&gt;中已经看到，Device Plugin 的 Advertise→Bind→Allocate 模型把设备分配的全部决策权下沉到了 kubelet 本地，调度器只知道“这个节点有 N 块设备”，不知道设备的具体属性、参数和分配策略。DRA（Dynamic Resource Allocation，动态资源分配）正是为解决这一结构性缺陷而生的，它已在 Kubernetes v1.35 进入 GA（Stable）阶段。&lt;/p&gt;
&lt;p&gt;本文不重复 DRA 的快速入门，而是聚焦三个层面：Device Plugin 的根本局限在哪里、DRA 的 API 设计做了哪些取舍、以及它对 GPU 调度体系的长远影响。&lt;/p&gt;
&lt;h2 id="device-plugin-的三个结构性问题"&gt;Device Plugin 的三个结构性问题&lt;/h2&gt;
&lt;p&gt;Device Plugin 的设计初衷是“让厂商能接入异构设备”，这个目标它完成得很好。但随着 GPU 平台化程度加深，三个结构性问题逐渐暴露。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;参数化请求无法表达。&lt;/strong&gt; Pod spec 里 &lt;code&gt;nvidia.com/gpu: 1&lt;/code&gt; 只能声明“我要一块 GPU”，无法表达“我要一块带 40GB 显存的 H100，启用 MIG profile 4g.40gb”。调度器在选节点时，只能判断“节点上有没有至少一块 GPU”，不能判断“有没有满足我具体参数的 GPU”。所有参数化逻辑都被推迟到 kubelet 的 Allocate 阶段，这意味着调度器可能把 Pod 放到一个设备参数不匹配的节点上，分配失败后 Pod 才会 CrashLoopBackOff。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;分配过程对控制面不透明。&lt;/strong&gt; Device Plugin 的 Allocate 调用发生在 kubelet 本地，不走 API Server。调度器、准入控制器、审计日志都看不到“具体哪块设备分配给了哪个 Pod”。这对多租户平台来说是治理盲区——你无法在控制面回答“这台 H100 上的 4 个 Pod 分别占了哪几个 MIG 实例”这类问题，只能 SSH 到节点上查。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;设备生命周期与 Pod 耦合。&lt;/strong&gt; Device Plugin 没有独立的“设备分配”对象。分配随着 Pod 创建而发生，随着 Pod 删除而释放。如果你需要预先分配设备（比如在训练任务启动前先锁住 GPU）、或者让多个 Pod 共享同一块设备的特定资源份额，Device Plugin 的模型不直接支持，只能靠厂商自行实现私有方案。&lt;/p&gt;
&lt;p&gt;这三个问题的根源是同一个：Device Plugin 把“设备选择与分配”做成了节点侧的本地实现，而不是控制面的一等资源对象。&lt;/p&gt;
&lt;h2 id="dra-的核心设计四个-api-对象"&gt;DRA 的核心设计：四个 API 对象&lt;/h2&gt;
&lt;p&gt;DRA 引入了四个 &lt;code&gt;resource.k8s.io/v1&lt;/code&gt; API 组下的核心对象，各自承担不同的职责。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ResourceSlice：设备信息的发布通道。&lt;/strong&gt; DRA 驱动在集群中创建和管理 ResourceSlice，向调度器暴露节点上的设备信息——包括设备属性（型号、显存、拓扑）、可用容量以及哪些节点可以访问这些设备。调度器通过扫描 ResourceSlice 来回答“哪个节点有满足条件的设备”这个问题。ResourceSlice 替代了 Device Plugin 中“通过 gRPC 向 kubelet 广告设备”的那一步，把设备信息从节点本地提升到了集群可见的 API 对象。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;DeviceClass：管理员定义的设备类别。&lt;/strong&gt; DeviceClass 类似 StorageClass 的设计思路——管理员或驱动定义“一类设备的分配策略”，包括匹配哪些设备、使用哪个驱动、分配模式（独占还是共享）等。Pod 不直接指定“我要某某型号的 GPU”，而是引用一个 DeviceClass，由 DeviceClass 的规则来决定具体匹配哪些设备。这把“设备选择策略”从 Pod spec 中解耦出来，集中到了集群治理层面。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ResourceClaim：设备分配的一等对象。&lt;/strong&gt; 这是 DRA 与 Device Plugin 最根本的区别。ResourceClaim 是一个标准的 Kubernetes 资源对象，代表“对特定设备的分配请求”。当调度器找到一个匹配的设备时，它会更新 ResourceClaim 的 status 字段，记录分配结果。整个分配过程经过 API Server，可以被审计、被观测、被其他控制器引用。ResourceClaim 支持两种使用方式：直接创建让多个 Pod 共享同一份设备分配，或者通过 ResourceClaimTemplate 为每个 Pod 自动生成独立的 Claim。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ResourceClaimTemplate：自动化生成的模板。&lt;/strong&gt; 当每个 Pod 需要独立的设备分配时（这是大多数情况），用 ResourceClaimTemplate 可以自动为每个 Pod 生成 ResourceClaim，其生命周期与 Pod 绑定。Pod 删除时自动清理对应的 Claim，避免资源泄漏。&lt;/p&gt;
&lt;p&gt;这四个对象的设计意图很清晰：把设备分配从&amp;quot;节点本地的 gRPC 调用&amp;quot;提升到&amp;quot;控制面的标准 API 对象&amp;quot;。Device Plugin 的 Allocate 黑盒变成了可审计的 ResourceClaim 状态变更。&lt;/p&gt;
&lt;figure class="mx-auto text-center"&gt;
&lt;img src="https://assets.jimmysong.io/images/book/gpu-infra/data-plane/dra/dra-api-objects.svg" data-img="https://assets.jimmysong.io/images/book/gpu-infra/data-plane/dra/dra-api-objects.svg" alt="图 1: DRA 四个核心 API 对象" data-caption="图 1: DRA 四个核心 API 对象"
width="1305"
height="1383"
loading="lazy" decoding="async" class="image-loading"
onload="this.classList.remove('image-loading'); this.classList.add('image-loaded');"
onerror="handleImageError(this); this.classList.remove('image-loading');"&gt;
&lt;figcaption&gt;图 1: DRA 四个核心 API 对象&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="调度流程对比device-plugin-vs-dra"&gt;调度流程对比：Device Plugin vs DRA&lt;/h2&gt;
&lt;p&gt;理解两个模型的差异，最直接的方式是对比调度流程。&lt;/p&gt;
&lt;p&gt;Device Plugin 的流程是三步闭环：驱动通过 gRPC 向 kubelet 广告设备（Advertise），调度器根据整数计数做节点选择（Bind），kubelet 调用驱动的 Allocate 完成交付。调度器在 Bind 阶段只能看到“节点上有 N 块设备”这个标量信息，具体分配决策完全在 Allocate 阶段才发生。&lt;/p&gt;
&lt;p&gt;DRA 的流程在此基础上增加了两个关键步骤。驱动先通过 ResourceSlice 发布设备信息（包括属性和容量），调度器在选节点时就可以基于设备属性做过滤——比如“这个节点的 GPU 显存够不够”、“是不是 H100”、“MIG profile 是否匹配”。找到匹配节点后，调度器更新 ResourceClaim 的 allocation 状态，再完成 Pod 绑定。分配结果通过 API Server 持久化，而不是在 kubelet 本地一闪而过。&lt;/p&gt;
&lt;p&gt;这个差异看起来只是多走了几步 API，但对平台治理的影响是根本性的。调度器第一次有了设备属性层面的决策能力，而不是只能&amp;quot;赌 Allocate 阶段不会失败&amp;quot;。分配结果第一次变成了可审计的 API 对象，而不是节点本地的瞬时状态。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;维度&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Device Plugin&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;DRA&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;调度器能看到的设备信息&lt;/td&gt;
&lt;td&gt;整数计数（&lt;code&gt;nvidia.com/gpu: 8&lt;/code&gt;）&lt;/td&gt;
&lt;td&gt;多维属性（显存、型号、拓扑、容量）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;分配可见性&lt;/td&gt;
&lt;td&gt;kubelet 本地 gRPC，不可审计&lt;/td&gt;
&lt;td&gt;经 API Server，ResourceClaim 可审计&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;设备生命周期&lt;/td&gt;
&lt;td&gt;与 Pod 耦合，Pod 删除即释放&lt;/td&gt;
&lt;td&gt;ResourceClaim 独立，可预先分配和共享&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;参数化能力&lt;/td&gt;
&lt;td&gt;无，只能声明整数数量&lt;/td&gt;
&lt;td&gt;CEL 表达式过滤设备属性&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;设备共享&lt;/td&gt;
&lt;td&gt;厂商私有实现&lt;/td&gt;
&lt;td&gt;ResourceClaim 天然支持多 Pod 引用&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;设计类比&lt;/td&gt;
&lt;td&gt;类似静态 PV&lt;/td&gt;
&lt;td&gt;类似 StorageClass + PVC 的声明式模型&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figcaption class="text-center mb-3"&gt;
表 1: Device Plugin vs DRA 核心差异
&lt;/figcaption&gt;
&lt;h2 id="架构演变从-classic-dra-到-structured-parameters"&gt;架构演变：从 Classic DRA 到 Structured Parameters&lt;/h2&gt;
&lt;p&gt;DRA 的架构本身也经历了一次重要的角色反转，这一点直接影响你理解 DRA 的方式。&lt;/p&gt;
&lt;p&gt;最初 KEP-3063 定义了“Classic DRA”，引入了控制面控制器和 ResourceClaim/DeviceClass 的基本框架。后来 KEP-4381 引入了 Structured Parameters（结构化参数），允许用 CEL 表达式对设备属性做精细过滤。随着 Structured Parameters 的成熟，两个 KEP 的角色发生了反转：&lt;strong&gt;KEP-4381 现在定义基础功能&lt;/strong&gt;，&lt;strong&gt;KEP-3063 变成了扩展&lt;/strong&gt;。也就是说，结构化调度是 DRA 的主流路径，Classic DRA 的控制面控制器反而成了可选的向后兼容层。&lt;/p&gt;
&lt;p&gt;这个反转的含义是：DRA 的设计重心从“让 ResourceClaim 在控制面流转”变成了“让调度器基于结构化参数做更智能的设备选择”。CEL 表达式可以表达“我要显存大于 40GB 的 GPU”、“我要支持 NVLink 的双卡配置”这类条件，调度器在选节点时就能精确匹配，而不是事后补救。&lt;/p&gt;
&lt;h2 id="dra-没有解决什么"&gt;DRA 没有解决什么&lt;/h2&gt;
&lt;p&gt;DRA 解决的是“设备分配的可表达性和可观测性”，但有几件明确不做的事情。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;DRA 不定义隔离机制。&lt;/strong&gt; MIG 的硬件级隔离、vGPU 的虚拟化切分、时间片复用——这些仍然是数据平面的责任。DRA 让你更容易声明“我要一个 MIG 4g.40gb 的实例”，但隔离本身仍然由底层硬件和驱动提供。在前面的 &lt;a href="../data-plane-taxonomy/"&gt;数据平面谱系&lt;/a&gt;一章中已经讨论过，隔离强度和资源单位是数据平面的核心交付，DRA 只是把“请求这些能力”的过程标准化了。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;DRA 不替代调度策略。&lt;/strong&gt; 队列管理、优先级抢占、配额控制——这些仍然是 Volcano/Kueue 的领地。DRA 和 Kueue 有天然的合作点（Kueue 可以基于 ResourceClaim 做队列感知的设备分配），但 DRA 本身不包含调度策略语义。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;DRA 不支持抢占。&lt;/strong&gt; 截至 Kubernetes v1.35，DRA 资源不支持 Pod 预占。一个低优先级 Pod 占用的设备不会被高优先级 Pod 抢走，高优先级 Pod 只能等待设备释放。这对严格 SLA 场景是一个需要注意的限制。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;与 Device Plugin 的过渡期共存。&lt;/strong&gt; DRA 和 Device Plugin 在同一个集群中可以共存。同一个节点上的设备可以一部分通过 Device Plugin 暴露（作为 Extended Resource），另一部分通过 DRA 的 ResourceSlice 暴露。但这种共存增加了运维复杂度，平台需要决定迁移节奏和边界。&lt;/p&gt;
&lt;h2 id="对-gpu-调度体系的长远影响"&gt;对 GPU 调度体系的长远影响&lt;/h2&gt;
&lt;p&gt;DRA GA 之后，它对 GPU 基础设施的影响主要体现在三个方向。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;参数化调度成为可能。&lt;/strong&gt; 这是 DRA 最直接的价值。在 Device Plugin 时代，调度器选节点的依据是“这个节点有几块 GPU”；DRA 时代，调度器可以基于显存容量、MIG profile、互联拓扑、设备健康状态等多维属性做选择。结合 &lt;a href="../../fundamentals/decision-axes/"&gt;决策轴&lt;/a&gt;一章的框架，DRA 直接强化了“粒度”和“兼容性”两个维度的表达能力。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;设备共享有了标准的 API 层。&lt;/strong&gt; DRA 的 ResourceClaim 天然支持设备共享——多个 Pod 可以引用同一个 ResourceClaim。结合 v1.34 引入的 Consumable Capacity（可消费容量）特性，驱动可以声明设备的可分配容量（比如一块 80GB 的 GPU 可以被多个 Claim 按需切分），调度器负责确保所有 Claim 的容量之和不超过总量。这为 GPU 共享提供了一条标准化的路径，而不依赖各家厂商的私有实现。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;异构芯片的统一接入层。&lt;/strong&gt; GPU、TPU、NPU、DPU 的接入在 Device Plugin 时代各自为政——每个厂商实现自己的 plugin，API 语义不统一。DRA 通过 ResourceSlice + DeviceClass + CEL 表达式提供了一套统一的设备描述和匹配框架。异构芯片的厂商只需要实现 DRA 驱动、发布 ResourceSlice，就可以接入 Kubernetes 的标准调度流程。这对前面 &lt;a href="../../fundamentals/heterogeneous-accelerators/"&gt;异构加速器全景&lt;/a&gt;一章讨论的多芯片协同架构是一个重要的基础设施支撑。&lt;/p&gt;
&lt;h2 id="从-device-plugin-迁移到-dra"&gt;从 Device Plugin 迁移到 DRA&lt;/h2&gt;
&lt;p&gt;对于已经在生产环境使用 Device Plugin 的团队，迁移不需要一步到位。&lt;/p&gt;
&lt;p&gt;短期（当前）：DRA 和 Device Plugin 可以共存。可以在部分节点上启用 DRA 驱动做灰度验证，同时保持 Device Plugin 在其余节点上运行。&lt;/p&gt;
&lt;p&gt;中期（验证期）：选择合适的场景先迁移。参数化需求强的场景（MIG profile 选择、显存容量匹配、异构芯片混合部署）是 DRA 最能体现价值的切入点。纯整卡独占的场景，Device Plugin 仍然够用。&lt;/p&gt;
&lt;p&gt;长期（全面迁移）：当 DRA 驱动的成熟度和生态覆盖度足够时，Device Plugin 会逐步退化为向后兼容层。各主流 GPU 厂商已经在推进 DRA 驱动的实现（NVIDIA 的 CDI-based DRA driver 已进入 beta 阶段，AMD 的 ROCm DRA driver 在 alpha 阶段），生态追赶速度取决于厂商投入和社区 adoption。&lt;/p&gt;
&lt;p&gt;迁移的核心判断标准很简单：你是否需要在调度阶段表达“我要什么样的设备”，而不仅仅是“我要几块设备”。如果答案是“是”，DRA 就值得认真评估。&lt;/p&gt;
&lt;h2 id="总结"&gt;总结&lt;/h2&gt;
&lt;p&gt;DRA 的本质是把 Kubernetes 的设备资源分配从“节点本地黑盒”推进到“控制面可见的一等 API”。它解决了 Device Plugin 的三个结构性问题——参数化请求、分配透明度、生命周期解耦——同时明确地把隔离机制和调度策略留给数据平面和控制面各自处理。对 GPU 平台来说，DRA 不是锦上添花，而是让“异构、参数化、可治理”的设备调度从可能变为可行的基础设施前提。&lt;/p&gt;
&lt;h2 id="参考文献"&gt;参考文献&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/scheduling-eviction/dynamic-resource-allocation/" target="_blank" rel="noopener"&gt;Dynamic Resource Allocation - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/3063-dynamic-resource-allocation" target="_blank" rel="noopener"&gt;KEP-3063: Dynamic Resource Allocation - github.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/4381-dra-structured-parameters" target="_blank" rel="noopener"&gt;KEP-4381: DRA Structured Parameters - github.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/blog/2025/09/18/kubernetes-v1-34-dra-consumable-capacity/" target="_blank" rel="noopener"&gt;Kubernetes v1.34: DRA Consumable Capacity - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.aks.azure.com/2025/11/17/dra-devices-and-drivers-on-kubernetes" target="_blank" rel="noopener"&gt;Delve into DRA, devices, and drivers on Kubernetes - Azure AKS Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-device-management-with-dra-dynamic-resource-allocation" target="_blank" rel="noopener"&gt;Kubernetes Device Management with DRA - Google Cloud Blog&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item></channel></rss>