使用FlexNPU实现NPU资源虚拟化与隔离
FlexNPU是面向华为昇腾(Ascend)硬件生态设计的算力虚拟化与弹性管理系统,可在 Kubernetes 集群中实现物理NPU的细粒度切分、多Pod共享与强隔离调度。 通过Device Plugin机制与Volcano调度器集成,实现NPU资源的声明式管理和按需分配。本文介绍如何使用NPU虚拟化能力实现算力和显存隔离,高效利用NPU设备资源。
若集群中存在正在使用NPU虚拟化资源的容器,请勿直接卸载NPU插件或关闭FlexNPU能力。否则可能导致运行中的Pod无法访问NPU资源,引发服务异常或任务中断。
核心架构

传统AI架构中,应用直接绑定底层驱动并独占物理卡资源,导致资源僵化、调度困难。FlexNPU打破了这一僵局,采用Client-Server分布式架构,实现了“API调用”与“物理执行”的彻底解耦。整体由以下核心组件构成:
- flexnpu-device-plugin与flexnpu-runtime:作为连接Kubernetes控制面与物理底层的桥梁。
- Device Plugin:负责将物理NPU资源进行弹性切片并上报,支撑K8s对细粒度算力的精准调度与分配。
- Runtime:作为底层的OCI拦截引擎,在容器启动时,将虚拟化后的设备节点与通信配置透明、安全地注入业务沙箱,实现业务间的严格隔离。
- flexnpu-daemon:作为部署在宿主机侧的常驻守护进程,负责接收来自上层(如Kubernetes调度体系)的FlexNPU注册请求,动态拉起和管理底层的 aclserver 进程组(实际的物理执行端),是整个单机虚拟化算力调度的核心控制面。
- flexnpu-client:以动态链接库形式部署于业务容器内部,对上层AI应用(如PyTorch、vLLM)实现零侵入。它在前端透明接管应用发起的底层硬件API调用,并通过高速共享内存或轻量级网络协议,将计算请求以极低延迟转发至宿主机的aclserver执行实际物理计算。
FlexNPU特性优势
- 零侵入的API拦截机制
用户侧无需重新编译代码,也无需修改环境变量,即可直接运行原生的AI框架。aclrt会在底层接管aclInit、aclrtMalloc等所有核心指令,将原本在本地执行的函数调用转换为网络或内存请求,极大降低了业务接入成本。
- 高吞吐的双链路RPC通信
针对AI算子下发高频、数据传输量大的特点,FlexNPU在shared模块中实现了双链路通信架构:
- TAP(基于TCP/IP): 用于传输控制流和轻量级状态指令,保证跨隔离环境的连通性和可靠性。
- 共享内存 (Shared Memory): 针对Tensor数据的高频交互,系统动态建立基于/dev/shm的内存映射。客户端直接将数据写入共享内存,服务端直接读取,实现了数据传递的“零拷贝 (Zero-Copy)”,显著降低通信延迟。
- 面向云原生的容器化编排
FlexNPU天生为云原生环境设计。在Docker或containerd等OCI标准容器环境下,物理设备(如/dev/davinciX)由 aclserver 在宿主机的安全沙箱内独占;而业务容器内仅挂载虚拟化的通信配置(如client.conf)和共享内存目录。这种设计不仅实现了完美的资源隔离,还彻底杜绝了容器越权操作物理硬件的风险,非常易于与底层的自定义Runtime结合,实现资源的无缝注入。
前提条件
已创建v1.29及以上版本的CCE Standard/Turbo集群。
约束与限制
| 配置 | 限制说明 |
|---|---|
| NPU芯片型号 | 仅支持Snt9B芯片 |
| 容器镜像的系统 | Ubuntu 22.04 |
| 镜像 | 仅支持Huawei Cloud EulerOS 2.0特定机型的私有镜像,包含支持的NPU驱动25.2.0与CANN 8.2.RC1 |
| 推理引擎 | 仅支持vLLM Ascend v0.9.1,CANN 8.2.RC1 |
| 模型支持 | DeepSeek-R1-Distill-Llama-8B、Qwen3-8B-W4A8、Qwen/QwQ-32B |
| AI Core切分 | 最小5%,步长1%,最大支持100% |
| 显存切分 | 必须是128 MiB的整数倍 |
| NPU虚拟化实例数量 | 单卡节点最多支持切分为3个FlexNPU实例,多卡节点最多支持切分为2倍NPU数量的FlexNPU实例 |
| Pod容器数量限制 | 仅支持在Pod中配置单个容器使用NPU虚拟化,不支持在Pod中配置多个容器时使用NPU虚拟化 |
| 容器运行时 | 仅支持containerd |
| 用户权限要求 | 不支持以非root用户启动NPU虚拟化容器 |
| 特权容器限制 | 当NPU虚拟化负载开启特权容器时,无法保证其隔离性 |
注意事项
- 请勿在集群中存在使用NPU虚拟化的容器时直接卸载NPU插件,否则会导致负载无法使用。
- 请勿强制删除NPU虚拟化容器,否则可能导致资源残留,影响后续资源调度与发放。若不慎强制删除,请务必按以下步骤进行清理。
- 遍历所有启用了NPU虚拟化的节点,在每个节点上执行flexnpu-smi info,对比所有entity-id与当前节点上所有NPU虚拟化负载Pod的UID。
- 若发现存在entity-id但不存在Pod的UID,则说明此NPU虚拟化设备为残留设备,需要通过以下命令进行清理。
flexnpu-smi unregister -u <残留设备对应的flexnpu ID>

- 节点意外重启后,NPU虚拟化Pod可能因NPU虚拟化资源上报延迟,显示为“执行失败”状态。此为正常现象,可忽略该状态。
- 安装CCE AI套件(Ascend NPU)插件后,支持版本升级操作,您可根据实际需求灵活选择。
当CCE AI套件(Ascend NPU)启用NPU虚拟化功能时,进行版本升级需确保节点上无NPU虚拟化负载。若NPU节点存在NPU虚拟化负载,进行插件版本升级操作,则需要对NPU节点进行排水,详情请参见CCE AI套件(Ascend NPU)插件版本升级,如何对NPU节点进行排水。
步骤一:安装CCE AI套件(Ascend NPU)并开启FlexNPU特性
- 登录CCE控制台,单击集群名称进入集群。
- 在左侧导航栏中选择“插件中心”,在右侧找到CCE AI套件(Ascend NPU)插件,单击“安装”。
- 在“安装插件”面板中,插件版本选择2.4.3。
- 单击“YAML安装”,在“spec.values.custom”中添加“enable_flexnpu”参数,并将其值设置为“true”,然后单击“提交”。

- 在“插件中心”页面,查看已安装插件的详情。确认插件的实例状态为运行中。
步骤二:安装并配置Volcano调度器
- 在左侧导航栏中选择“插件中心”,在右侧找到Volcano调度器插件,插件版本选择1.21.17及之后版本,然后单击“安装”。在“插件中心”中查看Volcano调度器的状态,确保调度器状态为运行中。
- 在左侧选择“配置中心”,切换至调度配置页签,设置默认调度器为“Volcano调度器”。
- 单击专家模式后的“开始使用”,在专家模式(Volcano调度)面板中添加以下内容开启FlexNPU能力,然后单击“保存”。

- arguments: scheduleMode: binpack name: flexnpuaffinity表1 参数说明 参数
说明
scheduleMode
调度模式,决定任务如何分配到NPU节点。取值如下:
- binpack:目标是最大限度地填满已有NPU卡,尽量避免将Pod调度至空闲NPU卡。具体实现中,调度器会对所有满足条件的节点进行评分,资源利用率越高,得分越高,调度优先级也越高。Binpack算法能够尽可能填满NPU卡,将应用负载集中于部分NPU卡。
- spread:目标是最大限度地将应用负载分散到不同的NPU卡或节点上,尽量避免将多个Pod调度至同一块NPU卡。在具体实现中,调度器会对所有符合条件的节点进行评分,资源利用率越低的节点得分越低,其调度优先级则越高。通过Spread算法,可以尽可能地利用集群中的空闲资源,使应用负载均匀分布在整个集群中。
name
调度插件的名称。固定为flexnpuaffinity。
- 在配置调度页签,单击“确认配置”,使配置生效。
步骤三:准备NPU虚拟化负载容器镜像
镜像选择说明
核心要求:
离线环境镜像迁移流程
执行迁移流程前需确保:
- 有一台可访问外网的ARM64 Linux服务器(避免多架构转换问题)。
- 已安装Docker客户端并登录目标SWR仓库。
如果您的Kubernetes集群节点无法直接访问公网(无法直接从quay.io拉取镜像),请按照以下步骤在具有外网访问权限的机器上进行镜像拉取、打标签,并推送至您的SWR(容器镜像服务)仓库。
- 拉取ARM64单平台镜像。
由于quay.io可能默认提供多架构清单,为了确保拉取的是ARM64架构,建议使用--platform参数指定架构。
docker pull --platform linux/arm64 quay.io/ascend/vllm-ascend:v0.9.1
- 推送镜像到镜像仓库,具体请参见推送镜像到镜像仓库。
步骤四:创建NPU虚拟化应用
- 在左侧选择“工作负载”,单击“创建工作负载”。
本文以新建工作负载为例。如果修改已有工作负载,单击工作负载的名称,然后切换至容器管理页签。
- 在容器配置的基本信息区域,选择步骤三中的镜像,NPU配额选择NPU虚拟化,您可以将物理NPU卡的算力与显存资源进行切分,并分配给业务容器使用。
- 未开启NPU多卡均分
适用场景:单卡切分场景,将一张物理NPU卡的资源切分后分配给容器。

参数
说明
显存
分配给容器的显存容量,必须是128 MiB的整数倍。
算力
容器可使用的算力上限,以单张物理NPU卡总算力的百分比(%)来表示。
- 开启NPU多卡均分
适用场景:多卡切分场景。将一张或多张物理NPU卡的资源均摊到多张虚拟卡上,容器内将挂载多张虚拟卡。

参数
说明
卡数
指定将总资源(算力和显存)均分到多少张虚拟NPU卡上。例如,设置为2,表示容器内会挂载两张虚拟NPU卡。
总显存
分配给容器的总显存大小,必须是128 MiB的整数倍。
总算力
容器可使用的总算力上限,以单张物理NPU卡总算力的百分比(%)来表示。
例如,您申请配置卡数为2,显存为256 MiB,算力为20%。系统将会为您创建两张虚拟NPU卡,每张卡的资源分配如下:
- 算力:10% (20% / 2)
- 显存:128 MiB (256 MiB / 2)
容器内将挂载这两张虚拟卡,可使用上述分配的资源。
- 未开启NPU多卡均分
- 单击“创建工作负载”,然后查看提交负载的实例状态,直至显示为运行中。
- 先查看Pod的uid,然后在节点上执行以下命令,查看该Pod分配的虚拟NPU信息。

flexnpu-smi info
预期结果:每个Pod的虚拟NPU资源使用量与配置值一致,且相互独立,无干扰。
