【NVIDIA】NVIDIA k8s-device-plugin v0.19.3 系统级架构分析

发布时间:2026/7/25 22:42:24
【NVIDIA】NVIDIA k8s-device-plugin v0.19.3 系统级架构分析 NVIDIA k8s-device-plugin v0.19.3 系统级架构分析分析对象: github.com/k8s-device-plugin-0.19.3代码语言: Go (116个非vendor Go文件)分析日期: 2026-07-25目录项目整体架构整体设计思路整体运行流程子模块/功能模块划分模块调用关系主流程详解1. 项目整体架构1.1 项目定位NVIDIA k8s-device-plugin 是 NVIDIA 官方开发的 Kubernetes 设备插件用于将 NVIDIA GPU 资源暴露给 Kubernetes 集群中的容器化工作负载。它实现了 Kubernetes Device Plugin APIgRPC与 Kubelet 交互完成 GPU 设备的发现、分配和健康监控。1.2 架构分层项目采用五层架构设计自上而下分别为层级名称目录核心职责L1入口层cmd/4个可执行程序入口CLI解析、启动控制L2核心服务层internal/plugin,internal/lm,internal/watchgRPC设备插件服务、标签管理、文件/信号监控L3资源管理层internal/rm,internal/cdi,internal/imex,internal/flags设备资源管理、CDI规格生成、IMEX通道、K8s客户端L4设备抽象层internal/resource,internal/cuda,internal/mig,internal/vgpu,internal/infoNVML/CUDA/VFIO设备抽象、CGo绑定、MIG工具、vGPU检测L5配置层api/config/v1/统一配置结构体、标志定义、资源共享策略1.3 关键设计特征多入口单仓库4个独立的main()入口共享同一套 internal 包策略模式设备发现支持auto/nvml/tegra三种策略运行时自动选择工厂模式plugin.New()、resource.NewManager()、cdi.New()均采用函数式选项工厂接口驱动ResourceManager、Manager、Device、Interface、Labeler等核心抽象均为接口功能选项模式广泛使用WithXxx()风格的 Functional Options回退机制FallbackToNullOnInitError提供 Init 失败时的 Null 回退2. 整体设计思路2.1 核心设计原则Kubernetes Device Plugin Protocol 优先所有设计围绕 Kubernetes Device Plugin gRPC API 展开实现ListAndWatch、Allocate、GetPreferredAllocation、PreStartContainer四个核心RPC。多平台兼容通过info.ResolvePlatform()自动检测运行平台NVML/WSL/Tegra选择对应的设备发现策略和资源管理器实现。设备共享支持支持两种GPU共享策略Time-Slicing时间片共享通过Replicas创建带注释的设备IDMPS (Multi-Process Service)通过MPS控制守护进程实现真正的GPU共享CDI (Container Device Interface) 集成支持cdi-annotations和cdi-cri两种设备列表策略通过 nvidia-container-toolkit 生成CDI规格文件。配置统一管理单一Config结构体覆盖所有配置项支持 YAML 文件、CLI 标志、环境变量三种配置来源优先级CLI 环境变量 配置文件。2.2 数据模型Config ├── Flags (CommandLineFlags) │ ├── MigStrategy: none | single | mixed │ ├── DeviceDiscoveryStrategy: auto | nvml | tegra │ ├── Plugin (PluginCommandLineFlags) │ │ ├── DeviceListStrategy: envvar | volume-mounts | cdi-annotations | cdi-cri │ │ └── DeviceIDStrategy: uuid | index │ └── GFD (GFDCommandLineFlags) ├── Resources (GPUs MIGs, Pattern → Name 映射) ├── Sharing (TimeSlicing MPS, ReplicatedResources) └── Imex (ChannelIDs Required)3. 整体运行流程3.1 nvidia-device-plugin 启动流程main() ├── CLI 解析 (urfave/cli/v2) ├── watch.Files(kubeletSocketDir) // 监控kubelet socket目录 ├── watch.Signals(SIGHUP, SIGINT, ...) // 监控OS信号 └── start() 事件循环 └── startPlugins() ├── loadConfig() // 加载配置 ├── spec.DisableResourceNamingInConfig() ├── validateFlags() // 验证标志 ├── rm.AddDefaultResourcesToConfig() // 添加默认资源 ├── GetPlugins() // 获取插件集合 │ ├── imex.GetChannels() // 获取IMEX通道 │ ├── resolveStrategy() // 解析发现策略 │ ├── cdi.New() // 创建CDI处理器 │ ├── plugin.New() // 创建插件实例 │ └── cdiHandler.CreateSpecFile() // 生成CDI规格文件 └── 遍历插件 → p.Start(kubeletSocket) ├── Serve() // 启动gRPC服务 ├── Register() // 注册到Kubelet └── go rm.CheckHealth() // 启动健康检查3.2 运行时事件循环select { case -restartTimeout: → goto restart // 重启插件 case event : -watcher.Events: // kubelet socket重建 → goto restart case err : -watcher.Errors: // 文件系统错误 → log case s : -sigs: // OS信号 SIGHUP → goto restart 其他 → goto exit }3.3 gpu-feature-discovery 启动流程main() ├── CLI 解析 └── start() 循环 ├── loadConfig() ├── resource.NewManager() // 创建资源管理器 ├── vgpu.NewVGPULib() // 创建vGPU库 ├── lm.NewOutputer() // 创建标签输出器 └── gfd.run() ├── lm.NewLabelers() // 构建标签器链 ├── labelers.Labels() // 生成标签 ├── labelOutputer.Output() // 输出标签 └── 等待 sleepInterval 或信号4. 子模块/功能模块划分4.1 入口模块 (cmd/)核心作用: 提供4个独立的可执行程序入口各自负责CLI解析、配置加载和生命周期管理。子模块文件核心函数/方法职责nvidia-device-pluginmain.go,root.go,plugin-manager.gomain(),start(),startPlugins(),GetPlugins(),resolveStrategy(),root.tryResolveLibrary()主设备插件入口管理gRPC插件生命周期gpu-feature-discoverymain.gomain(),start(),gfd.run(),removeOutputFile()GPU特征发现定期生成节点标签config-managermain.gomain(),start(),continuouslySyncConfigChanges(),updateConfig(),signalProcess()监听Node标签动态更新配置文件并发SIGHUPmps-control-daemonmain.go,mps/*.go,mount/*.gomain(),start(),startDaemons(),Daemon.Start(),Daemon.Stop(),Daemon.EchoPipeToControl()MPS控制守护进程管理4.2 Plugin 模块 (internal/plugin/)核心作用: 实现Kubernetes Device Plugin gRPC接口管理设备列表、分配和健康监控。关键类型与函数:类型/函数文件职责nvidiaDevicePluginserver.go核心结构体实现pluginapi.DevicePluginServerInterfaceapi.go插件接口:Devices(),Start(),Stop()New()factory.go工厂函数创建插件实例列表Optionsoptions.goFunctional Options:WithCDIHandler,WithConfig等Start()server.go启动gRPC服务并注册到KubeletServe()server.gogRPC服务循环含崩溃重启Register()server.go向Kubelet注册设备插件ListAndWatch()server.go返回设备列表并监控健康状态Allocate()server.go核心: 设备分配入口getAllocateResponse()server.go构建分配响应CDI/EnvVar/Mounts/DeviceSpecsGetPreferredAllocation()server.go返回优选设备分配方案ValidateRequest()通过rm验证分配请求合法性mpsOptionsmps.goMPS共享配置管理4.3 Resource Manager 模块 (internal/rm/)核心作用: 管理GPU/MIG设备的枚举、分配算法、健康检查和副本管理。关键类型与函数:类型/函数文件职责ResourceManager(Interface)rm.go资源管理接口resourceManagerrm.go基础实现nvmlResourceManagernvml_manager.goNVML平台实现含健康检查Devicedevices.go设备模型: ID, Paths, Index, Replicas, HealthDevicesdevices.gomap[string]*Device集合操作DeviceMapdevice_map.goResourceName → Devices映射AnnotatedIDdevices.go带副本编号的设备ID:UUID::replicadistributedAlloc()allocate.go均衡分配算法副本设备均匀分布alignedAlloc()nvml_manager.goGPU拓扑对齐分配使用gpuallocatorcheckHealth()health.goXID错误事件监控ValidateRequest()rm.go请求验证共享资源限制AddDefaultResourcesToConfig()rm.go添加默认GPU/MIG资源模式NewNVMLResourceManagers()nvml_manager.go创建NVML资源管理器集合NewTegraResourceManagers()tegra_manager.go创建Tegra资源管理器集合deviceMapBuilderdevice_map.go设备映射构建器updateDeviceMapWithReplicas()device_map.go应用共享副本配置4.4 Resource 设备抽象模块 (internal/resource/)核心作用: 提供统一的设备管理接口封装 NVML、CUDA、VFIO 三种设备后端。关键类型与函数:类型/函数文件职责Manager(Interface)types.go设备管理接口:Init,GetDevices,GetDriverVersionDevice(Interface)types.go设备接口:IsMigEnabled,GetAttributes,GetNameNewManager()factory.go工厂函数根据策略创建ManagernvmlLibnvml-lib.goNVML Manager实现cudaLibcuda-lib.goCUDA Manager实现Tegra平台vfioLibsysfs-lib.goVFIO Manager实现sysfs PCI设备nullnull.go空实现回退用withFallBackfallback.goInit失败自动回退到NullnvmlDevicenvml-device.goNVML设备实现nvmlMigDevicenvml-mig-device.goMIG设备实现cudaDevicecuda-device.goCUDA设备实现vfioDevicesysfs-device.goVFIO设备实现4.5 CDI 模块 (internal/cdi/)核心作用: 生成 Container Device Interface (CDI) 规格文件支持容器运行时自动注入GPU设备。关键类型与函数:类型/函数文件职责Interfaceapi.goCDI接口:CreateSpecFile,QualifiedName,AdditionalDevicescdiHandlercdi.goCDI处理器实现New()cdi.go工厂函数创建CDI处理器CreateSpecFile()cdi.go生成CDI JSON规格文件到/var/run/cdi/QualifiedName()cdi.go生成CDI设备名:vendor/class/idAdditionalDevices()cdi.go返回额外CDI设备GDS/MOFED/GDRCopygetRootTransformer()cdi.go驱动根路径转换器nullnull.go空实现无CDI时使用csvFilesForRoot()cdi.goTegra CSV文件路径解析Optionsoptions.goWithDriverRoot,WithDeviceIDStrategy等4.6 Label Manager 模块 (internal/lm/)核心作用: 为GPU Feature Discovery (GFD) 生成节点标签包括驱动版本、CUDA版本、MIG能力、共享策略等。关键类型与函数:类型/函数文件职责Labeler(Interface)labeler.go标签器接口:Labels() (Labels, error)Labelslabels.gomap[string]string标签集合NewLabelers()labeler.go创建标签器集合Merge()labeler.go合并多个标签器NewDeviceLabeler()nvml.go创建设备标签器newVersionLabeler()nvml.go驱动/CUDA版本标签newMigCapabilityLabeler()nvml.goMIG能力标签newSharingLabeler()nvml.go共享策略标签NewResourceLabeler()resource.go资源标签GPU数量、内存等NewVGPULabeler()vgpu.govGPU标签NewTimestampLabeler()timestamp.go时间戳标签NewOutputer()output.go创建标签输出器ToFile/toWriteroutput.go文件/标准输出nodeFeatureObjectoutput.goNFD NodeFeature CR 输出4.7 Config 模块 (api/config/v1/)核心作用: 统一配置管理覆盖CLI标志、资源模式、共享策略、IMEX通道。关键类型与函数:类型/函数文件职责Configconfig.go顶层配置结构体NewConfig()config.go从CLI/ENV/文件构建配置parseConfig()config.goYAML/JSON解析DisableResourceNamingInConfig()config.go禁用资源重命名Flags/CommandLineFlagsflags.goCLI标志定义PluginCommandLineFlagsflags.go插件专属标志GFDCommandLineFlagsflags.goGFD专属标志Resources/Resourceresources.goGPU/MIG资源模式匹配ResourcePatternresources.go通配符模式:*→.*Sharingsharing.go共享策略: TimeSlicing MPSReplicatedResourcesreplicas.go副本资源配置DeviceListStrategiesstrategy.go设备列表策略集合NewDeviceListStrategies()strategy.go创建策略集合AnyCDIEnabled()/AllCDIEnabled()strategy.goCDI策略检查Imeximex.goIMEX通道配置Duration/DurationValueduration.go自定义Duration类型4.8 MPS Control Daemon 模块 (cmd/mps-control-daemon/)核心作用: 管理NVIDIA MPS (Multi-Process Service) 守护进程实现GPU共享。关键类型与函数:类型/函数文件职责Manager/managermanager.goMPS管理器NewDaemons()/New()manager.go创建Daemon集合Daemondaemon.goMPS守护进程实例Daemon.Start()daemon.go启动MPS守护 (nvidia-cuda-mps-control)Daemon.Stop()daemon.go停止MPS守护Daemon.AssertHealthy()daemon.go健康检查Daemon.EchoPipeToControl()daemon.go通过管道发送命令setComputeMode()daemon.go设置GPU计算模式 (EXCLUSIVE_PROCESS)mpsDevicedevice.goMPS设备验证 (assertReplicas, maxClients)Rootroot.goMPS根路径管理 (PipeDir, LogDir, ShmDir)logTailerlog-tailer.go日志跟踪mount-shm.gomount/SHM挂载4.9 辅助模块模块目录核心作用关键函数/类miginternal/mig/MIG设备信息查询和设备路径解析DeviceInfo,GetMigCapabilityDevicePaths(),GetDevicesMap(),GetAllMigDevices()vgpuinternal/vgpu/vGPU PCI设备检测和厂商能力解析Interface,Lib,Device,Info,NewVGPULib(),NewNvidiaPCILib()imexinternal/imex/IMEX通道设备发现和注入Channel,Channels,GetChannels()watchinternal/watch/文件系统和OS信号监控Files(),Signals()cudainternal/cuda/CGo CUDA绑定 (libcuda.so.1)Init(),Shutdown(),Device,cuInit,cuDeviceGet,cuDeviceGetAttribute,cuDeviceTotalMemflagsinternal/flags/Kubernetes客户端和节点配置KubeClientConfig,NodeConfig,NewClientSets()infointernal/info/版本信息GetVersionString(),GetVersionParts()dependenciesinternal/dependencies/依赖记录编译时—5. 模块调用关系5.1 模块间依赖关系矩阵main plugin rm cdi resource config lm mig vgpu imex watch cuda flags info main (ndp) - ✓ ✓ . . ✓ . . . ✓ ✓ . ✓ ✓ main (gfd) - . . . ✓ ✓ ✓ . ✓ . ✓ . ✓ ✓ main (mps) - . ✓ . . ✓ . . . . ✓ . . ✓ main (config-mgr) - . . . . . . . . . . . . ✓ plugin . - ✓ ✓ . ✓ . . . ✓ . . . . rm . . - . ✓ ✓ . ✓ . . . . . . cdi . . . - . . . . . ✓ . . . . resource . . . - - . . . . . . ✓ . . lm . . ✓ . ✓ ✓ - . ✓ . . . ✓ .5.2 数据流向5.2.1 设备发现数据流config.Config (Resources/Flags) ↓ rm.NewNVMLResourceManagers() / NewTegraResourceManagers() ↓ NewDeviceMap(devicelib, config, platform) ↓ (VisitDevices / VisitMigDevices) deviceMapBuilder.buildGPUDeviceMap() / buildMigDeviceMap() ↓ (Pattern matching: ResourcePattern.Matches(name)) DeviceMap (ResourceName → Devices) ↓ (updateDeviceMapWithReplicas - if sharing enabled) DeviceMap with replicated AnnotatedIDs ↓ resourceManager{config, resource, devices} ↓ nvidiaDevicePlugin{rm: resourceManager}5.2.2 设备分配数据流Kubelet → Allocate(request) ↓ 遍历 ContainerRequests ↓ rm.ValidateRequest(AnnotatedIDs) ↓ uniqueDeviceIDsFromAnnotatedDeviceIDs() ↓ (根据 DeviceListStrategies) ├── CDI: cdiHandler.QualifiedName() → annotations/cdiDevices ├── EnvVar: NVIDIA_VISIBLE_DEVICES uuid1,uuid2 ├── VolumeMounts: /var/run/nvidia-container-devices/id └── DeviceSpecs: /dev/nvidia* (if PassDeviceSpecs) ↓ ContainerAllocateResponse ↓ Kubelet → 容器运行时5.2.3 标签生成数据流 (GFD)config.Config ↓ resource.NewManager(infolib, nvmllib, devicelib, config) ↓ resource.Manager → manager.GetDevices() → []Device ↓ lm.NewLabelers(manager, vgpu, config) ├── newVersionLabeler() → nvidia.com/cuda.driver-version.* ├── newMigCapabilityLabeler() → nvidia.com/mig.capable ├── newSharingLabeler() → nvidia.com/mps.* ├── NewResourceLabeler() → nvidia.com/gpu.count, nvidia.com/gpu.memory.* ├── NewVGPULabeler() → nvidia.com/vgpu.* └── migStrategyLabeler() → nvidia.com/mig.strategy ↓ lm.Merge(labelers...).Labels() ↓ lm.Outputer.Output(labels) ├── ToFile: /etc/kubernetes/node-feature-discovery/features.d/gfd └── NodeFeature CR: NFD API5.3 健康检查数据流rm.CheckHealth(stop, unhealthy) ↓ (nvmlResourceManager.checkHealth) nvml.EventSetCreate() ↓ 遍历设备 → gpu.RegisterEvents(XidCriticalError | ECC errors, eventSet) ↓ eventSet.Wait(5000ms) 循环 ↓ XID事件 → 匹配 parentToDeviceMap → 标记 Unhealthy ↓ plugin.health channel → ListAndWatch.Send() → Kubelet6. 主流程详解6.1 Allocate 完整流程Allocate()是设备插件最核心的RPC当Kubelet调度GPU Pod时调用。// 1. Kubelet调用 Allocate(AllocateRequest)func(plugin*nvidiaDevicePlugin)Allocate(ctx,reqs)(*AllocateResponse,error){for_,req:rangereqs.ContainerRequests{// 2. 验证请求plugin.rm.ValidateRequest(req.DevicesIds)// 3. 构建分配响应response:plugin.getAllocateResponse(req.DevicesIds)// 4. 根据策略填充响应// 4a. CDI策略 → annotations 或 cdiDevices// 4b. EnvVar策略 → NVIDIA_VISIBLE_DEVICES// 4c. VolumeMounts策略 → /var/run/nvidia-container-devices// 4d. PassDeviceSpecs → /dev/nvidia* 设备节点// 5. MPS额外处理// → CUDA_MPS_PIPE_DIRECTORY, pipe/shm mounts// 6. IMEX通道注入// → NVIDIA_IMEX_CHANNEL_IDS env var// 7. 可选功能// → NVIDIA_GDRCOPY, NVIDIA_GDS, NVIDIA_MOFED env vars}returnresponses}6.2 设备发现策略选择resolveStrategy(auto, infolib): infolib.ResolvePlatform() ├── PlatformNVML → nvml ├── PlatformWSL → nvml (WSL用同一策略) └── PlatformTegra → tegra6.3 资源管理器创建plugin.New(ctx, infolib, nvmllib, devicelib, opts...) ↓ o.getResourceManagers() ├── strategy nvml: │ nvmllib.Init() │ NewNVMLResourceManagers(infolib, nvmllib, devicelib, config) │ ├── NewDeviceMap(devicelib, config, platform) │ │ ├── buildGPUDeviceMap() → VisitDevices → Pattern match │ │ └── buildMigDeviceMap() → VisitMigDevices → Pattern match │ └── 遍历 DeviceMap → 创建 nvmlResourceManager │ └── strategy tegra: NewTegraResourceManagers(config) ├── buildTegraDeviceMap(config) └── 遍历 → 创建 resourceManager6.4 MIG 策略处理策略行为none忽略MIG设备只暴露完整GPUsingle所有GPU必须配置相同的MIGMIG设备映射到nvidia.com/gpumixedGPU和MIG设备分别暴露MIG设备映射到nvidia.com/mig-profile6.5 设备共享Time-Slicingconfig.Sharing.TimeSlicing: Resources: [{Name: nvidia.com/gpu, Replicas: 4}] ↓ updateDeviceMapWithReplicas() ↓ 原始设备 UUID → 4个带注释的ID: UUID::0, UUID::1, UUID::2, UUID::3 ↓ Kubelet看到4倍数量的设备 ↓ ValidateRequest: 共享资源最多请求1个 ↓ distributedAlloc: 均衡分配副本6.6 MPS 共享config.Sharing.MPS: Resources: [{Name: nvidia.com/gpu, Replicas: 4}] ↓ mps-control-daemon 启动 ↓ Daemon.Start(): nvidia-smi -c EXCLUSIVE_PROCESS (设置独占进程模式) nvidia-cuda-mps-control -d (启动MPS守护) set_default_device_pinned_mem_limit (设置内存限制) set_default_active_thread_percentage (设置线程百分比) ↓ plugin.Allocate(): response.Envs[CUDA_MPS_PIPE_DIRECTORY] pipeDir response.Mounts: pipe目录 shm目录附录A. 文件统计类别文件数说明非vendor Go文件116核心项目代码入口程序4nvidia-device-plugin, gfd, config-manager, mps-control-daemoninternal包15plugin, rm, cdi, resource, lm, mig, vgpu, imex, watch, cuda, flags, info, dependenciesapi包1config/v1测试文件~15单元测试 e2e测试vendor依赖~50go-nvlib, go-nvml, go-gpuallocator, nvidia-container-toolkit, k8s libsB. 关键外部依赖依赖用途go-nvlib/pkg/nvlib/deviceNVML设备库封装go-nvlib/pkg/nvlib/info平台检测go-nvml/pkg/nvmlNVML Go绑定go-gpuallocator/gpuallocatorGPU拓扑对齐分配nvidia-container-toolkit/pkg/nvcdiCDI规格生成container-device-interface/pkg/cdiCDI解析kubelet/pkg/apis/deviceplugin/v1beta1K8s Device Plugin APIurfave/cli/v2CLI框架fsnotify/fsnotify文件系统事件监控sigs.k8s.io/node-feature-discoveryNFD NodeFeature APIC. 架构图索引编号图名文件1整体架构图diagrams/01_overall_architecture.png2主启动流程diagrams/02_main_flow.png3模块调用关系diagrams/03_call_relationship.png4Plugin模块diagrams/04_plugin_module.png5Resource Manager模块diagrams/05_rm_module.png6Resource设备抽象模块diagrams/06_resource_module.png7CDI模块diagrams/07_cdi_module.png8Label Manager模块diagrams/08_lm_module.png9入口模块diagrams/09_entry_module.png10MPS模块diagrams/10_mps_module.png11Config模块diagrams/11_config_module.png12辅助模块diagrams/12_auxiliary_modules.png13Allocate流程diagrams/13_allocate_flow.png