Ascend Docker Runtime v26.0.1 系统级架构分析

基于源码的深度架构剖析
分析日期:2026-07-26
代码规模:13个Go源文件 + C/Shell辅助组件,约8,436行核心Go代码
项目路径:component/ascend-docker-runtime


目录


第一章:项目整体架构

1.1 项目概述

Ascend Docker Runtime 是华为昇腾(Ascend) NPU 的容器化运行时插件,基于 OCI 标准实现,为 AI 训练/推理作业提供 NPU 容器化支持。它不修改 Docker 引擎,而是以插件方式在 runc 启动容器过程中注入 NPU 设备。

功能说明
NPU 设备挂载根据 ASCEND_VISIBLE_DEVICES 将对应 NPU 设备挂载到容器 namespace
设备 cgroup 配置在 Host 上配置 device cgroup,确保容器只使用指定 NPU
CANN 运行时库挂载将 Host 上的 CANN Runtime Library 挂载到容器
vNPU 虚拟化支持虚拟设备(vdavinci)切分与创建
Prestart Hook在容器 created→running 过渡期执行设备注入
安装/卸载自动修改 Docker/containerd 配置文件

1.2 整体设计思路

多后端抽象

DcDriverV1

Ascend 910/310 旧版

DcDriverV2

Ascend 910B/A5 新版

Hook 机制

Prestart Hook

容器 namespace 已创建

但作业未启动

挂载设备 + 配置 cgroup

挂载 CANN 库

核心设计

OCI 标准兼容

不修改 Docker 引擎

作为 Docker Runtime 插件

在 runc 前拦截 config.json

修改 OCI Spec 注入 NPU 设备

执行 runc 完成容器创建

1.3 整体运行流程

否

是

否

是

Docker/Containerd 收到容器创建请求

调用 ascend-docker-runtime

runtime/main.go 启动

命令是 create?

直接 exec runc 透传

读取 config.json OCI Spec

解析 ASCEND_VISIBLE_DEVICES

需要 NPU 设备?

直接 exec runc

获取 NPU Worker
V1或V2驱动

注入 Prestart Hook 到 Spec

创建虚拟设备 vNPU
如果 VIRTUAL 模式

挂载 davinci 设备到 Spec

挂载管理设备到 Spec

添加 device cgroup 规则

写入修改后的 config.json

exec runc 创建容器

runc 触发 Prestart Hook

hook/main.go 执行

解析挂载配置列表

调用 ascend-docker-cli 挂载文件/目录

容器启动,NPU 可用

1.4 系统整体架构图

底层

安全工具

install

ascend-docker-cli (C语言)

ascend-docker-hook

ascend-docker-runtime

容器运行时

create

修改Spec+注入Hook

Prestart Hook

exec

挂载设备

修改

Docker/Containerd

runc

runtime/main.go
运行时入口

runtime/process
Spec修改+设备注入

runtime/dcmi
NPU设备管理

hook/main.go
Hook入口

hook/process
挂载配置解析

cli/src/main.c
实际挂载执行

install/main.go
安装/卸载

install/process
配置修改

mindxcheckutils
路径/文件校验

libdcmi.so
设备管理接口

NPU 硬件
davinci0-N

1.5 技术栈概览

依赖用途
github.com/opencontainers/runtime-specOCI 运行时规范
github.com/containerd/containerdcontainerd 配置解析
github.com/pelletier/go-tomlTOML 配置文件解析
ascend-common华为昇腾公共库(api/工具)
libdcmi.so (CGO)NPU 设备管理 C 库
hwlog华为日志库

第二章:子模块划分

2.1 运行时入口 (runtime/)

核心作用:作为 Docker Runtime 插件入口,拦截容器创建请求,修改 OCI Spec 注入 NPU 设备,然后透传给 runc。

args

+string bundleDirPath

+string cmd

process

+DoProcess() : error

-getArgs()(*args, error)

-modifySpecFile(path) : error

-execRunc() : error

-addDevice(w, spec, devices) : error

-addHook(w, spec, devices) : error

-addManagerDevice(w, spec) : error

-checkVisibleDevice(spec)([]int, error)

-addAscendDockerEnv(spec)

main

+main()

否

是

是

否

DoProcess

cmd == create?

execRunc 透传

获取 bundle 路径

读取 config.json

checkVisibleDevice
解析 ASCEND_VISIBLE_DEVICES

设备列表为空?

addAscendDockerEnv
直接 exec runc

GetMatchingNpuWorker
选择V1/V2驱动

addHook
注入 Prestart + Poststop Hook

addDevice
挂载 davinci 设备

addManagerDevice
挂载管理设备

addUBDevice
挂载UB设备

写入 config.json

execRunc

关键文件核心函数/方法作用
runtime/main.gomain()入口,初始化日志,调用 DoProcess
runtime/process/process.goDoProcess()主流程:拦截create命令,修改Spec,exec runc
runtime/process/process.gomodifySpecFile()读取→修改→写回 config.json
runtime/process/process.gocheckVisibleDevice()解析 ASCEND_VISIBLE_DEVICES 环境变量
runtime/process/process.goaddDevice()挂载 davinci/vdavinci 设备到 Spec
runtime/process/process.goaddManagerDevice()根据芯片类型挂载管理设备
runtime/process/process.goaddHook()注入 Prestart Hook 和 Poststop Hook
runtime/process/process.goGetDeviceTypeByChipName()根据芯片名获取设备类型
runtime/process/process.goparseDevices()解析设备ID列表(支持范围"0-3"和单个"0,1,2")
runtime/process/process.goexecRunc()查找并执行 runc/docker-runc

2.2 DCMI 设备管理模块 (runtime/dcmi/)

核心作用:封装 NPU 设备管理接口,通过 CGO 调用 libdcmi.so,提供设备查询、虚拟设备创建/销毁能力。

«interface»

WorkerInterface

+Initialize() : error

+ShutDown()

+CreateVDevice(uniqueID int32, coreNum string)(VDeviceInfo, error)

+DestroyVDevice(uniqueID int32, vDevID int32) : error

+GetProductType()(string, error)

+GetChipName()(string, error)

«interface»

DcDriverV1Interface

+DcInitialize() : error

+DcShutDown()

+DcGetCardList()(int32, []int32, error)

+DcGetDeviceNumInCard(cardID)(int32, error)

+DcGetDeviceLogicID(card, device)(int32, error)

+DcGetProductType(card, device)(string, error)

+DcCreateVDevice(card, device, coreNum)(int32, error)

+DcDestroyVDevice(card, device, vDevID) : error

+DcGetChipInfo(card, device)(*ChipInfo, error)

«interface»

DcDriverV2Interface

+DcInitialize() : error

+DcShutDown()

+DcGetDeviceList()(int32, []int32, error)

+DcCreateVDevice(deviceID, coreNum)(int32, error)

+DcDestroyVDevice(deviceID, vDevID) : error

+DcGetChipInfo(deviceID)(*ChipInfo, error)

NpuV1Worker

+driver DcDriverV1Interface

+cardID int32

+deviceID int32

NpuV2Worker

+driver DcDriverV2Interface

+deviceID int32

DcV1Manager

-nvmllib nvml.Interface

DcV2Manager

-nvmllib nvml.Interface

VDeviceInfo

+int32 VdeviceID

+int32 CardID

+int32 DeviceID

ChipInfo

+string ChipName

+string ChipType

V1 旧版

V2 新版

GetMatchingNpuWorker

检测驱动版本

NpuV1Worker
+DcV1Manager

NpuV2Worker
+DcV2Manager

Initialize: DcInitialize

Initialize: DcInitialize

FindDevice
遍历Card+Device

DcGetDeviceList
直接获取设备列表

GetChipName
DcGetChipInfo

GetProductType
DcGetProductType

CreateVDevice
切分虚拟设备

返回 VDeviceInfo

关键文件核心类型/函数作用
dcmi.goWorkerInterface 接口NPU Worker 统一接口
dcmi.goNpuV1WorkerV1驱动实现(Ascend 910/310)
dcmi.goNpuV2WorkerV2驱动实现(Ascend 910B/A5)
dcmi.goGetMatchingNpuWorker()工厂函数,选择V1/V2
dcmi.goChipInfo芯片信息结构体
dcmi_api.goVDeviceInfo虚拟设备信息
dcmi_api.goCreateVDevice()创建虚拟设备顶层API
dcmi_api.goextractVpuParam()从OCI Spec提取vNPU参数
dcManager.goDcV1ManagerV1 CGO调用封装
dcManager.goDcV2ManagerV2 CGO调用封装
dcManager.goDcGetCardList()获取NPU卡列表
dcManager.goDcGetChipInfo()获取芯片信息
dcManager.goDcCreateVDevice()CGO创建虚拟设备
dcManager.goDcDestroyVDevice()CGO销毁虚拟设备

2.3 Hook 模块 (hook/)

核心作用:OCI Prestart Hook 实现,在容器 namespace 已创建但作业未启动时,解析挂载配置并调用 CLI 执行实际挂载。

是

否

hook/main.go 启动

InitLogModule 日志初始化

StringChecker 安全校验

DoPrestartHook

getContainerConfig
从stdin读取OCI State

getValueByKey
检查 ASCEND_VISIBLE_DEVICES

visibleDevices 为空?

直接返回 不处理

parseMounts
解析 ASCEND_RUNTIME_MOUNTS

readConfigsOfDir
读取 /etc/ascend-docker-runtime.d/

addUBMount
添加HCCL+Topo

parseRuntimeOptions
解析 NODRV/VIRTUAL

parseSoftLinkMode
解析软链接模式

查找 ascend-docker-cli

组装 CLI 参数

syscall.Exec
执行 CLI 挂载

关键文件核心函数/方法作用
hook/main.gomain()Hook入口,安全校验+调用DoPrestartHook
hook/process/process.goDoPrestartHook()主逻辑:解析配置→调用CLI挂载
hook/process/process.gogetContainerConfig()从stdin读取OCI State,解析config.json
hook/process/process.goparseMounts()解析 ASCEND_RUNTIME_MOUNTS 环境变量
hook/process/process.goreadConfigsOfDir()读取配置目录下的 .list 文件
hook/process/process.goparseRuntimeOptions()解析 NODRV/VIRTUAL 选项
hook/process/process.goaddUBMount()添加UB挂载(hccl_rootinfo + topo)

2.4 安装模块 (install/)

核心作用:安装/卸载 ascend-docker-runtime,自动修改 Docker daemon.json 或 containerd config.toml。

docker/isula

containerd

add

rm

cgroup v2

cgroup v1

add

rm

install/main.go

参数校验

场景判断

DockerProcess

ContainerdProcess

action

读取 daemon.json

读取 daemon.json

addDockerDaemon
添加 ascend runtime

rmDockerDaemon
删除 ascend runtime

设置 default-runtime

写入 daemon.json

cgroup 版本

changeCgroupV2BinaryNameConfig
修改 BinaryName

action

changeCgroupV1RuntimeConfig
修改 runtime 路径

恢复默认 runc

changeCgroupV1RuntimeTypeConfig
修改 runtime_type

写入 config.toml

关键文件核心函数/方法作用
install/main.gomain()安装入口,参数校验,分发到Docker/Containerd处理
install/process/common.goCheckParamLength()参数数量校验
install/process/constant.go常量定义命令长度、位置索引、场景名等
install/process/docker_process.goDockerProcess()修改Docker daemon.json
install/process/docker_process.goaddDockerDaemon()添加ascend runtime配置
install/process/docker_process.gormDockerDaemon()移除ascend runtime配置
install/process/docker_process.goloadOriginJson()读取原始daemon.json
install/process/containerd_process.goContainerdProcess()修改containerd config.toml
install/process/containerd_process.goeditContainerdConfig()编辑containerd配置
install/process/containerd_process.gochangeCgroupV2BinaryNameConfig()cgroup v2配置
install/process/containerd_process.gochangeCgroupV1Config()cgroup v1配置

2.5 安全检查模块 (mindxcheckutils/)

核心作用:提供路径安全校验、文件信息检查、字符串白名单过滤等安全工具函数。

mindxcheckutils

+CheckPath(path, allowLink) : error

+CheckFileInfo(file, size) : error

+RealFileChecker(path, checkParent, allowLink, size)(string, error)

+RealDirChecker(path, checkParent, allowLink)(string, error)

+FileChecker(path, allowDir, checkParent, allowLink, deep)(bool, error)

+StringChecker(text, minLen, maxLen, whiteList) : bool

+GetLogPrefix()(string, error)

+ChangeRuntimeLogMode(prefix) : error

关键文件核心函数作用
mindxcheckutils.goRealFileChecker()文件路径安全校验(防软链接攻击)
mindxcheckutils.goRealDirChecker()目录路径安全校验
mindxcheckutils.goFileChecker()递归文件检查(深度限制)
mindxcheckutils.goStringChecker()字符串白名单过滤(防注入)
mindxcheckutils.goCheckFileInfo()文件大小检查
mindxcheckutils.goChangeRuntimeLogMode()日志文件权限修改

2.6 CLI 工具 (cli/) — C语言实现

核心作用:实际执行文件/目录挂载到容器 namespace 的 C 语言工具,被 Hook 调用。

cli/src (C语言)

main.c
入口

u_mount.c
挂载逻辑

options.c
参数解析

ns.c
namespace操作

cgrp.c
cgroup配置

utils.c
工具函数

logger.c
日志

2.7 Destroy 工具 (destroy/) — C语言实现

核心作用:Poststop Hook 执行器,容器停止时销毁虚拟设备。

destroy/src/main.c

读取参数
cardID, deviceID, vDevID

调用 dcmi 销毁vDevice

清理资源


第三章:模块调用关系

3.1 模块依赖关系图

外部

工具层

设备层

处理层

入口层

exec

exec

注入Poststop

runtime/main.go

hook/main.go

install/main.go

runtime/process

hook/process

install/process

runtime/dcmi

libdcmi.so
CGO

mindxcheckutils

hwlog
日志库

ascend-common/api
常量定义

runc

ascend-docker-cli
C语言

ascend-docker-destroy
C语言

3.2 容器创建主流程时序图

ascend-docker-cli hook/main.go runc dcmi runtime/process runtime/main.go Docker ascend-docker-cli hook/main.go runc dcmi runtime/process runtime/main.go Docker alt [VIRTUAL模式] alt [需要 NPU] create --bundle /path DoProcess() getArgs() 解析参数 读取 config.json checkVisibleDevice() 解析设备列表 GetMatchingNpuWorker() 选择V1/V2驱动 GetChipName() 获取芯片类型 addHook() 注入Prestart+Poststop CreateVDevice() 创建虚拟设备 updateEnvAndPostHook() addDevice() 挂载davinci设备 addManagerDevice() 挂载管理设备 addUBDevice() 挂载UB设备 写回 config.json exec runc create 触发 Prestart Hook DoPrestartHook() 解析挂载配置 .list文件 exec ascend-docker-cli --mount-file ... --mount-dir ... 挂载设备文件+目录到容器namespace 配置device cgroup 容器创建完成,NPU可用

3.3 安装流程时序图

文件系统 ContainerdProcess DockerProcess install/main.go 用户/脚本 文件系统 ContainerdProcess DockerProcess install/main.go 用户/脚本 alt [add] [rm] alt [cgroup v2] [cgroup v1] alt [Docker场景] [Containerd场景] add/rm <args> 参数校验 CheckParamLength DockerProcess(command) 读取 daemon.json addDockerDaemon() 设置 default-runtime=ascend rmDockerDaemon() 删除 default-runtime 写入 daemon.json ContainerdProcess(command) 读取 config.toml editContainerdConfig() changeCgroupV2BinaryNameConfig() changeCgroupV1RuntimeConfig() changeCgroupV1RuntimeTypeConfig() 写入 config.toml

3.4 vNPU 虚拟设备创建流程

否

是

V1

V2

检测到 VIRTUAL 选项

extractVpuParam
从Spec提取切分参数

参数有效?

返回错误

Worker.CreateVDevice

Worker版本

DcV1Manager.DcCreateVDevice
CGO: 指定card+device

DcV2Manager.DcCreateVDevice
CGO: 指定deviceID

返回 vDevID

updateEnvAndPostHook

更新ASCEND_RUNTIME_OPTIONS
追加VIRTUAL标记

注入Poststop Hook
销毁vDevice

更新deviceIdList
改为vDeviceID

3.5 数据流描述

设备发现数据流:
ASCEND_VISIBLE_DEVICES环境变量 → getValueByDeviceKey() → parseDevices()/parseAscendDevices() → 设备ID列表 → GetMatchingNpuWorker() → NPU Worker → GetChipName() → 芯片类型

设备注入数据流:
设备ID列表 → addDevice() → /dev/davinci{N} → oci.DeviceFromPath() → Spec.Linux.Devices → Spec.Linux.Resources.Devices(cgroup) → 写入config.json → runc读取并创建设备

Hook挂载数据流:
runc触发Prestart → hook/main.go → stdin读取OCI State → 解析config.json → 读取 /etc/ascend-docker-runtime.d/base.list → 组装CLI参数 → syscall.Exec(ascend-docker-cli) → CLI挂载文件/目录到容器namespace


第四章:架构设计总结

4.1 设计模式总结

安全防御

mindxcheckutils

路径校验防软链接攻击

文件大小限制

字符串白名单过滤

递归深度限制

Hook模式

Prestart Hook

容器namespace已创建

挂载设备+配置cgroup

Poststop Hook

容器停止

销毁vDevice

拦截器模式

ascend-docker-runtime

拦截create命令

修改OCI Spec

透传给runc

工厂模式

V1

V2

GetMatchingNpuWorker

驱动版本检测

创建NpuV1Worker

创建NpuV2Worker

策略模式

运行时选择

WorkerInterface

NpuV1Worker
旧版驱动策略

NpuV2Worker
新版驱动策略

GetMatchingNpuWorker

4.2 关键设计决策

决策原因实现
不修改Docker引擎保持与Docker原生兼容,升级无感知OCI Runtime插件方式
Prestart Hook挂载namespace已创建但作业未启动,安全窗口OCI Spec注入Hook
V1/V2双驱动新旧NPU硬件驱动接口不同WorkerInterface策略模式
C语言CLI挂载操作需要直接系统调用,C更高效hook通过exec调用C CLI
安全检查模块防止路径穿越、软链接攻击、注入攻击mindxcheckutils统一校验
config.json修改OCI标准方式,runc自动读取读取→修改→写回
Poststop HookvNPU虚拟设备需要销毁,避免资源泄漏destroy C程序

4.3 扩展性分析

扩展点机制示例
新增NPU芯片类型扩展 GetDeviceTypeByChipName()Ascend 910 → 910B → A5
新增驱动版本实现 WorkerInterfaceV1 → V2
新增挂载配置添加 .list 文件到配置目录base.list + 自定义.list
新增运行时选项扩展 validRuntimeOptionsNODRV, VIRTUAL
新增容器运行时扩展 install/processDocker, Containerd, iSula
新增管理设备扩展 managerDevicesMap芯片特定设备列表

4.4 架构特点总结

  1. OCI标准兼容:完全基于OCI标准实现,不侵入Docker/containerd引擎
  2. 分层设计:入口层(main) → 处理层(process) → 设备层(dcmi) → 底层(CGO/C库)
  3. 安全优先:所有外部输入都经过 mindxcheckutils 安全校验
  4. 多版本兼容:V1/V2双驱动策略,支持新旧NPU硬件
  5. 声明式配置:通过 .list 文件声明挂载列表,非硬编码
  6. Go+C混合实现:Go处理业务逻辑,C处理底层挂载操作
Logo

鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。

更多推荐