Ascend Device Plugin 超深度源码分析 — Part 3

设备管理基类 + 910设备管理器 + 热重置容错引擎


分析文件清单

序号 文件 行数 核心职责
1 pkg/device/ascendcommon.go ~1823 AscendTools 基类:所有NPU设备管理的公共能力层
2 pkg/device/ascend910.go ~2223 HwAscend910Manager:910系列设备的设备发现、健康监测、热重置容错
3 pkg/device/ascendtolerance.go ~996 HotResetTools:热重置管理器实现,CM同步、任务级容错策略
4 pkg/device/ascendcommon_v2.go ~56 A5超节点扩展属性 getter/setter

目录


一、模块定位

1.1 业务职责

这四个文件共同构成了 Ascend NPU Device Plugin 的设备管理层核心引擎,负责在 Kubernetes 集群中管理华为昇腾910系列NPU设备的完整生命周期。

模块 业务职责
AscendTools (ascendcommon.go) 所有NPU设备管理的公共基类:设备发现、健康状态判定、故障码处理、设备IP获取、Pod注解校正、设备信息ConfigMap管理、K8s事件写入、虚拟设备管理、手动隔离NPU处理、升级故障原因缓存
HwAscend910Manager (ascend910.go) 910系列设备专用管理器:NPU发现(物理/虚拟/共享)、Volcano调度ListAndWatch、优雅容错(在线热重置/离线热重置/隔离)、Ring级别设备重置、A3卡关联设备重置、带外重置(OutBand Reset)、设备信息CM更新、网络健康检测、DPU故障管理
HotResetTools (ascendtolerance.go) 热重置容错引擎:全局设备故障缓存管理、任务级故障策略决策(L2/L3/L5分级)、Reset CM同步与文件落盘、Pod/CM事件驱动处理、故障设备-Pod映射、任务/设备重置状态管理
ascendcommon_v2.go A5超节点属性扩展:SuperPodType/Size、NodeInternalIP、RackID 的 getter/setter

1.2 系统位置

NPU Hardware

Kubernetes Cluster

K8s API Server

Device Plugin Pod (DaemonSet)

外部依赖层

pkg/device 核心设备管理层

AscendTools
(ascendcommon.go)
公共基类

HwAscend910Manager
(ascend910.go)
910设备管理器

HotResetTools
(ascendtolerance.go)
热重置容错引擎

ascendcommon_v2.go
A5超节点扩展

pkg/common
公共工具

pkg/kubeclient
K8s客户端

ascend-common/devmanager
DCMI设备管理接口

pkg/device/deviceswitch
交换机故障

next/devicefactory/customname
设备名自定义

ConfigMap
(DeviceInfo/ResetInfo)

Node Labels

Pod Annotations

K8s Events

Ascend 910A/B/A3/A5
DCMI接口

1.3 支持的设备类型

Ascend 910 系列

Ascend910A

Ring=8卡重置

Ascend910B

Train: Ring=8

Infer: Ring=1(A800IA2)

Ascend910A3

全节点关联重置
(die0+die1+兄弟卡)

Ascend910A5

Ring=A5RingsNum
+超Pod/Rack感知


二、模块整体结构

2.1 类结构与接口定义

2.1.1 核心类图

持有引用

«interface»

DevManager

+GetNPUs() : NpuAllInfo

+DoWithVolcanoListAndWatch(map, int)

+GraceTolerance(ctx, map)

+SetDmgr(DeviceInterface)

+GetDmgr() : DeviceInterface

+GetChipAICore() : int32

+GetName() : string

+SetKubeClient(ClientK8s)

+GetKubeClient() : ClientK8s

+UpdateHealth(map, []NpuDevice, string)

+GetChange(map, map) : map

+AddPodAnnotation(PodDeviceInfo, string, string, []NpuDevice) : error

+CheckDeviceTypeLabel() : error

+CreateVirtualDevice(int32, string)(string, error)

+DestroyVirtualDevice(string) : error

+SetDeviceUsage(int32) : error

+GetDeviceUsage() : string

+SetSuperPodID(int32)

+GetSuperPodID() : int32

+HandleDropCardFaultEvents(NpuDevice)

+HandleLostChipFaultEvents(NpuDevice, []int32)

+HandleLostNetworkFaultEvents(NpuDevice, []int32)

+WriteFaultToEvent(ctx)

+LoadDeviceInfoCm(ctx)

+SetDpu(string, []DpuCMData, map)

AscendTools

-client: *kubeclient.ClientK8s

-dmgr: devmanager.DeviceInterface

-name: string

-deviceUsage: string

-unHealthyKey: string

-devCount: int32

-healthDevice: sets.String

-boardId: uint32

-superPodID: int32

-serverIndex: int32

-rackID: int32

-superPodType: int8

-superPodSize: int32

-nodeInternalIP: string

-cardInResetMap: map[int32]bool

-cardInResetLock: sync.Mutex

-resetFailedTimesMap: map[int32]int

-resetFailedTimesLock: sync.Mutex

-lastUpdateTimeStamp: time.Time

-lastUpgradeFaultReason: UpgradeFaultReasonMap

-lastManuallySeparateNPU: string

-lastSwitchFaultInfo: SwitchFaultInfo

-lastDpuInfo: DpuInfo

HwAscend910Manager

+AscendTools

-dpu: DpuInfo

-hotResetManager: HotResetManager

«interface»

HotResetManager

+GetResetDevNumOnce()(int, error)

+GetDevIdList(string) : []int32

+GetTaskDevFaultInfoList(string)([]TaskDevInfo, error)

+GetTaskPod(string)(Pod, error)

+GetAllTaskDevFaultInfoList() : map

+GetDevProcessPolicy(string) : string

+GetTaskProcessPolicy(string)(string, int, error)

+GetDevListInReset() : map

+GetGlobalDevFaultInfo(int32)(DevFaultInfo, error)

+UpdateGlobalDevFaultInfoCache([]NpuDevice, []int32) : error

+SetTaskInReset(string) : error

+UnSetTaskInReset(string) : error

+SetDevInReset(int32) : error

+UnSetDevInReset(int32) : error

+SyncResetCM(ctx, ClientK8s)

HotResetTools

-resetDevNumOnce: int

-allTaskDevList: map[string][]int32

-allTaskDevFaultInfo: map[string][]*TaskDevInfo

-globalDevFaultInfo: map[int32]*DevFaultInfo

-taskPod: map[string]v1.Pod

-faultDev2PodMap: map[int32]v1.Pod

-resetTask: map[string]struct

-resetDev: map[int32]struct

-queue: workqueue.RateLimitingInterface

-podIndexer: cache.Indexer

-cmIndexer: cache.Indexer

-jobs: map[string]string

-noResetCmPodKeys: map[string]struct

2.1.2 包级全局变量

ascendtolerance.go 全局变量

processPolicyTable: map[string]int
故障策略→级别映射表

ascend910.go 全局变量

lastTimeNetworkRecoverDevices: sets.String

hotResetManagerInitOnce: sync.Once
热重置管理器单例初始化

isHotResetOn: bool
热重置全局开关

inResetDev: int32
当前正在重置的设备LogicID

isolateDevList: []int32
已隔离设备列表

resetTimeMap: *sync.Map
重置时间记录

resetGoroutine: *sync.Map
重置协程跟踪

offlineInBandFailLogicId: sync.Map
带内重置失败记录

ascendcommon.go 全局变量

isFirstFlushFault: bool
首次故障刷新标记

subscribeToPollingTime: int64
订阅→轮询切换时间阈值

faultMode: map[int32]string
设备故障获取模式缓存

lastCheckNodeLabel: int64
上次节点标签检查时间戳

useIpv4: bool
IPv4/IPv6回退标志

re: regexp
匹配fault_time字段

allFaultInfo: chan DevFaultInfo
故障事件队列

faultEventLimiter: rate.Limiter
K8s事件写入限流器

networkLimiterMap: map[int32]*Limiter
网络查询限流器

networkStatusCache: map[int32]string
网络状态缓存

2.1.3 故障策略级别映射表

processPolicyTable 故障策略分级

Level 0: EmptyError
无故障/正常

Level 1: IgnoreError
忽略故障

Level 2: RestartRequestError
L2-请求重启
(故障自愈)

Level 3: RestartError
L3-设备重启
(等进程退出→重启)

Level 4: FreeResetError
L4-空闲热重置
(仅无任务时重置)

Level 5: ResetError
L5-强制热重置
(有任务也重置)

Level 6: IsolateError
L6-隔离
(升级失败→永久隔离)

2.2 核心方法清单

2.2.1 AscendTools 基类方法
方法 作用 调用者
SetDmgr/GetDmgr 设备管理器接口注入/获取 外部初始化
SetKubeClient/GetKubeClient K8s客户端注入/获取 外部初始化
GetChipAICore 获取AI Core数量 外部
GetName 获取设备名称(如"Ascend910") 多处
convertLogicIDsToDeviceNames LogicID列表→设备名字符串 handleManuallySeparateNPU
handleManuallySeparateNPUFaultInfo 处理手动隔离NPU故障信息 UpdateNodeDeviceInfo
LoadDeviceInfoCm 从DeviceInfo CM加载缓存 外部初始化
asyncReleaseAutoFill 异步释放自动填充故障 LoadDeviceInfoCm
UpdateNodeDeviceInfo 更新节点设备信息到CM 910/310P ListAndWatch
writeDeviceInfoCm 写设备信息到CM缓存 UpdateNodeDeviceInfo
getNodeDeviceInfoCache 构建节点设备信息缓存结构 writeDeviceInfoCm
updateLastInfo 更新上次信息快照 writeDeviceInfoCm
checkAndInitNodeDeviceInfo 初始化设备信息缓存 UpdateNodeDeviceInfo
compareDeviceList 比较设备列表(忽略fault_time) UpdateNodeDeviceInfo
delVirDevInfo 删除虚拟设备信息 UpdateNodeDeviceInfo
assembleNpuDeviceStruct 组装NpuDevice结构体 assemblePhy/Virtual/ShareDevices
assemblePhyDevices 组装物理设备 GetNPUs
assembleVirtualDevices 组装虚拟设备(vNPU) GetNPUs
assembleSpecVirtualDevice 组装特定虚拟设备规格 assembleVirtualDevices
assemble310PMixedPhyDevices 310P混合物理设备组装 310P GetNPUs
removeDuplicate 设备类型去重 GetNPUs
getResetInfoData 从CM解析重置信息 isTaskInReset等
getRealUsedDevices 获取实际使用中的设备 getDevStatesDevSet
filterSoftShareDevices 过滤软共享可用设备 getDevStatesDevSet
getDevStatesDevSet 获取设备状态集合 DoWithVolcanoListAndWatch
getUsedDevices 获取kubelet已分配设备 getDevStatesDevSet
groupDevsByStatus 按健康状态分组设备 getDevStatesDevSet
getFaultTimeAndLevelMap 构建故障时间-级别映射 getDeviceFaultsWithMode
combineFaultTimeMaps 合并故障时间映射 -
getDpuFaults 获取DPU子健康故障 getDeviceFaults
getDeviceFaults 获取设备故障列表(芯片+网络) groupDevsByStatus
getDeviceFaultsWithMode 按故障模式获取故障详情 getDeviceFaults
removeDuplicateErr 故障码去重 getDeviceFaultsWithMode
getDavinCiDev 获取DaVinci设备信息 GetNPUs
getVirtualDevice 获取虚拟设备信息 GetNPUs
GetDeviceIP 获取设备IP(支持v4/v6) 多处
getDcmiDeviceIP DCMI接口获取设备IP GetDeviceIP
getDeviceListIP 批量获取设备IP getConfigAnno
getConfigAnno 构建Pod配置注解 AddPodAnnotation
AddPodAnnotation 校正Pod注解 ListAndWatch循环
UpdateHealth 更新设备健康状态 ListAndWatch循环
GetChange 检测设备状态变化 ListAndWatch循环
setAICoreHealthyIfVNpu vNPU场景同步AI Core健康 UpdateHealth
setHealthyIfDuoCard Duo卡场景同步健康 UpdateHealth
getUnHealthyCard 获取不健康卡列表 setHealthyIfDuoCard
ClassifyDevices 按类型分类设备(包级函数) ListAndWatch
classifyDevByType 按类型分类辅助函数 ClassifyDevices
isHealthy 判定设备是否健康 writeNewFaultCode
isNetworkHealthy 判定网络是否健康 writeNewFaultCode
npuIsUsedNow 检查NPU当前是否有任务 isHealthy
getVGroupID 获取虚拟设备组ID AppendVGroupInfo
AppendVGroupInfo 追加vGroup信息 AddPodAnnotation
CheckDeviceTypeLabel 校验节点设备类型标签 ListAndWatch
CreateVirtualDevice 创建虚拟设备 动态vNPU场景
DestroyVirtualDevice 销毁虚拟设备 动态vNPU场景
GetChipAiCoreCount 获取芯片AI Core总数 初始化
writeNewFaultCode 刷新故障码到设备 UpdateHealth
getCurDeviceFaultCode 获取当前设备故障码 flushFaultCodesWithInit
flushFaultCodesWithInit 刷新故障码并初始化 writeNewFaultCode
moreThanFiveMin 故障是否超过5分钟 LogFaultModeChange
networkMoreThanFiveMin 网络故障是否超5分钟 LogFaultModeChange
LogFaultModeChange 记录故障模式变更 外部调用
getNPUsByShareMode 共享模式NPU列表 assembleShareModeDevices
assembleShareModeDevices 组装共享模式设备 310P GetNPUs
SetDeviceUsage 设置设备用途(训练/推理) 初始化
GetDeviceUsage 获取设备用途 多处
GetServerBoardId 获取服务器板ID SetDeviceUsage
GetIfCardsInResetting/SetCardsInResetting 卡重置状态管理 热重置流程
GetResetFailedTimes/SetResetFailedTimes 重置失败次数管理 热重置流程
WriteFaultToEvent 故障写入K8s Event 后台goroutine
WriteUpgradeReasonRemoveEvent 升级原因释放事件 writeDeviceInfoCm
doWriteFaultToEvent 实际写Event WriteFaultToEvent
SetSuperPodID/GetSuperPodID 超Pod ID管理 A5场景
SetServerIndex/GetServerIndex 服务器索引管理 A5场景
HandleDropCardFaultEvents 处理掉卡故障 故障检测循环
generateCardDropFaultEvents 生成掉卡故障事件 HandleDropCardFaultEvents
checkCardDropFault 检查掉卡故障 generateCardDropFaultEvents
HandleLostChipFaultEvents 处理丢失芯片故障 故障检测循环
generateChipFaultEventsBasedOnFaultCacheChange 基于缓存变化生成芯片故障 HandleLostChipFaultEvents
HandleLostNetworkFaultEvents 处理丢失网络故障 故障检测循环
generateNetworkFaultEventsBasedOnFaultCacheChange 基于缓存变化生成网络故障 HandleLostNetworkFaultEvents
queryNetworkStatusWithoutFaultCode 无故障码时查询网络状态 generateNetworkFaultEvents…
getNetworkStatusCache 带限流的网络状态缓存查询 queryNetworkStatusWithoutFaultCode
2.2.2 HwAscend910Manager 方法
方法 作用
NewHwAscend910Manager 构造函数
getAscend910Name 根据卡类型返回设备名
GetNPUs 发现所有910 NPU设备(物理/虚拟)
GraceTolerance 优雅容错主入口
hotResetHandler 热重置处理器(无任务场景)
getDevFaultInfo 获取设备故障信息
getResetIndex 获取重置Ring索引
hotResetTryOutBand 尝试带外重置
isFaultNeedRestart 判断故障是否需要重启
startUpHotReset 启动热重置流程
setAllDevUnhealthyOnRing 设置Ring上所有设备不健康
setUnhealthyForA3 A3卡设置关联设备不健康
GetAssociatedLogicIDs 获取A3关联LogicID列表
clearDeviceStatus 清除设备重置状态
handleResetProcess 处理重置流程
checkFaultIsExist 检查故障是否仍存在
upgradeHotResetError 升级热重置错误为隔离
refreshDevFaultInfoForResetProcess 刷新重置过程中的故障信息
execHotReset 执行热重置
isChipActive 检查芯片是否活跃(有任务)
canBeReset 检查所有芯片是否可重置
canA3BeReset A3卡可重置检查
getBusyChipListFromPod 从Pod列表获取繁忙芯片
DoWithVolcanoListAndWatch Volcano调度ListAndWatch入口
updateDeviceInfo 更新设备信息到CM
isNeedBlockAllDevice 是否需要阻塞所有设备调度
update910NodeLabel 更新910节点标签
getHealthAndRecoverDev 获取健康和恢复设备
getNewNetworkRecoverDev 获取新网络恢复设备
getPatchLabel 生成节点标签补丁
getRecoverLabelFromNodeSets 从节点标签获取恢复集
toStandardDeviceFmt 转为标准设备格式
updateHotResetCache 更新热重置缓存
updateUpgradeErrorInfo 更新升级错误信息
setTaskDevInfoCache 设置任务设备信息缓存
handleUpdateCaches 批量更新缓存
convertPhysicIdToLogicId 物理ID→逻辑ID转换
isReSchedulingScene 是否为重调度场景
isTaskInReset 任务是否在重置中
filterDevStatus 过滤重置中设备状态
filterDevStatusForA3 A3卡过滤重置状态
processAllTask 处理所有任务容错
policyLevelHandle 策略级别处理
isolateSceneHandle 隔离场景处理
runProcessTask 运行任务处理
restartRequestProcess L2故障处理(请求重启)
handleSucceedRestartRequest L2成功处理
checkDevErrorCode 检查设备错误码清除
restartProcess L3故障处理(设备重启)
upgradeRestartProcess L3升级为重置
upgradeRestartRequestProcess L2升级为重置
updateResetCMStatus 更新重置CM状态
updateResetCMStatusWithoutWait 更新重置CM状态(不等)
resetProcess L5故障处理(强制重置)
waitForAllFaultyDeviceProcessesToZero 等待故障设备进程归零
canContinueGraceProcess 检查是否可继续容错
updateResetCMStatusToIsolate 更新CM为隔离状态
getA3LogicMapByAssociation A3关联LogicID映射
getNeedResetDeviceLogicIdMap 获取需重置设备映射
addAllLogicIdsToFaultMap 添加Ring上所有LogicID
checkNumberOfAllProcessIsZero 检查所有进程是否归零
upgradeResetProcess L5升级为隔离
preProcess 预处理(写CM/设状态)
postProcess 后处理(清理状态)
refreshDevFaultInfo 刷新设备故障信息
getNeedResetDevMapForA3 A3需重置设备映射
getResetIndexForA3 A3重置索引
resetDeviceOnce 执行一次设备重置
canResetDeviceByLogicID 按LogicID检查可重置
canResetDevice 检查设备可重置(忙/次数)
execResetDevice 执行设备重置(带内)
execOutBandReset 执行带外重置
scanDeviceForThirdParty 第三方设备扫描
execRescan 执行重新扫描
fillResetDevs 补充设备信息(PhyID/CardID)
updateResetInfo 更新重置信息文件
resetDeviceOutBand 带外重置单设备
isNetResetCompleted 网络重置完成检查
waitDeviceResetComplete 等待设备重置完成
isRunningDistributed 是否分布式训练
isShouldCheckNet 是否需检查网络
isRingResetComplete Ring重置完成检查
tryResetDevice 尝试重置设备(带内)
tryResetDeviceOffline 尝试离线重置设备
tryWriteIsolationInfo 写隔离信息到CM
isDevShouldBeIsolate 设备是否应隔离
SetDpu 设置DPU信息
2.2.3 HotResetTools 方法
方法 作用
NewHotResetManager 构造函数(根据卡类型/用途/板ID确定Ring大小)
getResetDevNumOnce 获取单次重置设备数
SyncResetCM 同步Reset CM(Pod/CM Informer)
run 工作队列消费循环
processNextWorkItem 处理下一个工作项
handleEvent 事件分发(Pod/CM)
handlePodEvent Pod事件处理
handlePodAddEvent Pod添加事件(创建目录/写CM文件)
writeCmToFileWhilePodAdd Pod添加时写CM到文件
handlePodDeleteEvent Pod删除事件(清理文件/目录)
getPodFromCache 从缓存获取Pod
GetCMFromCache 从缓存获取CM
writeCMToFile 写CM数据到文件
handleConfigMapEvent CM事件处理
handleCMUpdateEvent CM更新事件
handleCMDeleteEvent CM删除事件
writeCmToFileSystem 写CM到文件系统
checkConfigMap CM过滤器(Reset/DataTrace前缀)
GetResetDevNumOnce 获取单次重置设备数
GetTaskDevFaultInfoList 获取任务设备故障信息列表
GetTaskPod 获取任务Pod
GetAllTaskDevFaultInfoList 获取所有任务故障信息
GetDevListInReset 获取重置中设备列表
GetGlobalDevFaultInfo 获取全局设备故障信息
GetDevProcessPolicy 获取设备处理策略
GetTaskProcessPolicy 获取任务处理策略(最高级别)
GetDevIdList 设备字符串→物理ID列表
GetDevListByPolicyLevel 按策略级别筛选设备
GetNeedResetDevMap 获取需重置设备映射
GetTaskResetInfo 获取任务重置信息
GetTaskFaultRankInfo 获取任务故障Rank信息
GetFaultDev2PodMap 获取故障设备→Pod映射
GetTaskNameByPod 从Pod获取任务名
GenerateTaskDevFaultInfoList 生成任务设备故障列表(含Rank)
UpdateFaultDev2PodMap 更新故障设备→Pod映射
UpdateGlobalDevFaultInfoCache 更新全局设备故障缓存
UpdateTaskDevListCache 更新任务设备列表缓存
UpdateTaskDevFaultInfoCache 更新任务故障信息缓存
UpdateTaskPodCache 更新任务Pod缓存
UpdateFreeTask 清理已结束任务的重置状态
isTaskDevListChange 检查任务设备列表是否变化
IsCurNodeTaskInReset 当前节点任务是否在重置
IsExistFaultyDevInTask 任务中是否存在故障设备
SetTaskInReset 设置任务重置状态
SetDevInReset 设置设备重置状态
SetAllDevInReset 设置任务所有设备重置
UnSetDevInReset 取消设备重置状态
UnSetAllDevInReset 取消任务所有设备重置
UnSetTaskInReset 取消任务重置状态
DeepCopyDevInfo 深拷贝设备信息
DeepCopyDevFaultInfoList 深拷贝故障信息列表

2.3 内部调用关系

CM同步 (HotResetTools)

SyncResetCM

cmInformer.Run

run (workqueue)

processNextWorkItem

handleEvent

handlePodEvent

handleConfigMapEvent

handlePodAddEvent

handlePodDeleteEvent

handleCMUpdateEvent

handleCMDeleteEvent

故障检测循环

UpdateHealth

writeNewFaultCode

flushFaultCodesWithInit

getCurDeviceFaultCode

isHealthy

isNetworkHealthy

setHealthyIfDuoCard

setAICoreHealthyIfVNpu

GraceTolerance 容错主循环

GraceTolerance

updateHotResetCache

updateUpgradeErrorInfo

UpdateGlobalDevFaultInfoCache

setTaskDevInfoCache

processAllTask
(在线容错)

GetTaskProcessPolicy

isolateSceneHandle

preProcess

runProcessTask

restartRequestProcess
(L2)

restartProcess
(L3)

resetProcess
(L5)

hotResetHandler
(离线容错)

canBeReset

startUpHotReset

handleResetProcess

execHotReset

tryResetDeviceOffline

isRingResetComplete

filterDevStatus

setAllDevUnhealthyOnRing

ListAndWatch 主循环

DoWithVolcanoListAndWatch

getDevStatesDevSet

groupDevsByStatus

getDeviceFaults

getDeviceFaultsWithMode

filterSoftShareDevices

UpdateNodeDeviceInfo

handleManuallySeparateNPUFaultInfo

writeDeviceInfoCm

2.4 数据流入流出

数据输出

处理层

数据输入

DCMI接口
(devmanager)

K8s API
(Pod/Node/CM)

Fault订阅
(DevFaultInfo)

hccn接口
(网络状态)

AscendTools
故障码刷新/健康判定

HwAscend910Manager
容错策略决策

HotResetTools
缓存管理/CM同步

DeviceInfo CM
(设备健康/故障/隔离)

ResetInfo CM
(重置状态/策略)

Node Labels
(恢复/网络恢复)

Pod Annotations
(设备分配/配置)

K8s Events
(故障事件)

Reset文件
(本地文件系统)

Device Plugin Socket
(ListAndWatch响应)


三、核心业务逻辑深度解析

3.1 ascendcommon.go — AscendTools 基类深度解析

3.1.1 AscendTools 结构体定义
type AscendTools struct {
    client       *kubeclient.ClientK8s    // K8s客户端,用于操作Pod/Node/CM/Event
    dmgr         devmanager.DeviceInterface // DCMI设备管理接口,直通NPU硬件
    name         string                     // 设备名称,如"Ascend910"或"Ascend910A5"→"npu"
    deviceUsage  string                     // 设备用途:"train"或"infer"
    unHealthyKey string                     // CM中不健康设备的key后缀
    devCount     int32                      // 最大设备数(=MaxDevicesNum)
    healthDevice sets.String                // 健康设备集合(未在结构体方法中直接使用)
    boardId      uint32                     // 服务器板ID,用于区分A800IA2等型号
    superPodID   int32                      // A5超Pod ID
    serverIndex  int32                      // A5服务器索引
    rackID       int32                      // A5机架ID
    superPodType int8                       // A5超Pod类型
    superPodSize int32                      // A5超Pod大小
    nodeInternalIP string                   // A5节点内部IP
    // 重置状态管理
    cardInResetMap  map[int32]bool          // LogicID→是否正在重置
    cardInResetLock sync.Mutex              // 重置状态互斥锁
    resetFailedTimesMap map[int32]int       // LogicID→连续重置失败次数
    resetFailedTimesLock sync.Mutex         // 失败次数互斥锁
    // 快照/增量检测
    lastUpdateTimeStamp       time.Time     // 上次更新时间
    lastUpgradeFaultReason    common.UpgradeFaultReasonMap[common.LogicId] // 上次升级故障原因
    lastManuallySeparateNPU   string        // 上次手动隔离NPU
    lastSwitchFaultInfo       common.SwitchFaultInfo // 上次交换机故障
    lastUsedChipsByProcess    sets.String   // 上次进程使用的芯片
    lastUsedChipsContainerMap map[string]sets.String // 上次容器使用芯片映射
    lastDpuInfo               common.DpuInfo // 上次DPU信息
}

设计意图

  • AscendTools 作为所有NPU设备管理器的公共基类,通过组合而非继承的方式被HwAscend910Manager等管理器嵌入
  • dmgr 接口注入实现了硬件层解耦,便于测试mock
  • boardId 缓存设计避免了重复调用DCMI获取板信息
  • cardInResetMap + cardInResetLock 提供了线程安全的重置状态跟踪
  • last* 系列字段实现了增量更新检测,避免无变化的CM写入
3.1.2 DevManager 接口

DevManager 接口定义了设备管理器的完整契约,包含40+方法,覆盖:

  • 设备发现(GetNPUs
  • 调度集成(DoWithVolcanoListAndWatch
  • 容错处理(GraceTolerance
  • 健康管理(UpdateHealth, GetChange
  • Pod注解管理(AddPodAnnotation
  • 虚拟设备管理(CreateVirtualDevice, DestroyVirtualDevice
  • A5超节点属性(SetSuperPodType/Size, SetRackID等)
  • 重置状态管理(SetCardsInResetting, GetResetFailedTimes等)
  • 故障事件处理(HandleDropCardFaultEvents, HandleLostChipFaultEvents等)
  • DPU管理(SetDpu
  • 设备信息加载(LoadDeviceInfoCm
3.1.3 核心流程:UpdateNodeDeviceInfo — 设备信息CM更新

是, 无变化

否, 有变化

有事件

无事件

UpdateNodeDeviceInfo 入口

checkAndInitNodeDeviceInfo
初始化CM缓存(如果为空)

wait.PollImmediate
每Interval秒轮询, Timeout秒超时

GetDeviceInfoCMCache
获取当前CM缓存

MapDeepCopy
深拷贝设备列表

updateDeviceInfoFunc
(由子类实现的具体更新逻辑)

delVirDevInfo
删除虚拟设备信息

handleManuallySeparateNPUFaultInfo
处理手动隔离NPU

RemoveManuallySeparateReasonCache
清理已移除的原因缓存

SwitchSubscribeFailed?
订阅是否失败

GetSwitchFaults
查询交换机故障

GetSwitchFaultInfo
从缓存获取

Ascend910ResetGoroutine!=0?
有重置协程运行?

UpdateSwitchFaultInfoAndFaultLevel
更新交换机故障信息和级别

CopyUpgradeFaultCache
复制升级故障原因缓存

compareDeviceList + DeepEqual
数据是否相同且<5分钟?

跳过更新, 返回true

writeDeviceInfoCm
写入CM

updateLastInfo
更新快照

GetAndCleanRemovedReasonEvent
获取已移除原因事件

WriteUpgradeReasonRemoveEvent
写释放事件

完成

逐行解析关键代码段

// checkAndInitNodeDeviceInfo — 如果CM缓存为空,创建初始结构
func (tool *AscendTools) checkAndInitNodeDeviceInfo() {
    nodeDeviceInfo := tool.GetKubeClient().GetDeviceInfoCMCache()
    if nodeDeviceInfo == nil {
        // 创建初始的设备信息缓存,包含空DeviceList和默认SuperPodID/ServerIndex
        var nodeDeviceData = common.NodeDeviceInfoCache{
            DeviceInfo: common.NodeDeviceInfo{
                DeviceList: make(map[string]string, 1),  // 空设备列表
                UpdateTime: time.Now().Unix(),            // 当前时间戳
            },
            SuperPodID:  common.DefaultSuperPodID,        // 默认超Pod ID
            ServerIndex: common.DefaultServerIndex,       // 默认服务器索引
        }
        // 生成校验码,用于后续CM数据完整性校验
        nodeDeviceData.CheckCode = common.MakeDataHash(nodeDeviceData.DeviceInfo)
        tool.GetKubeClient().SetNodeDeviceInfoCache(&nodeDeviceData)
    }
}
// compareDeviceList — 比较设备列表是否一致(忽略fault_time字段)
func compareDeviceList(deviceList, newDeviceList map[string]string) bool {
    // 双nil检查
    if deviceList == nil && newDeviceList == nil { return true }
    if deviceList == nil || newDeviceList == nil { return false }
    if len(deviceList) != len(newDeviceList) { return false }
    
    for key, value := range deviceList {
        val, exists := newDeviceList[key]
        if !exists { return false }
        // 使用正则 re (`"fault_time":\d+,`) 移除fault_time字段后比较
        // 设计意图:fault_time每次都会变化,但设备状态可能没变
        str1 := re.ReplaceAllString(value, "")
        str2 := re.ReplaceAllString(val, "")
        if str1 != str2 { return false }
    }
    return true
}
3.1.4 核心流程:健康状态判定

NormalNPU/NotHandleFault/SubHealthFault

FreeRestartNPU + 设备在用 + 容错开启

PreSeparateNPU + 设备在用

其他

NormalNPU/NotHandleFault

其他

writeNewFaultCode 入口

GetAndCleanFaultInfo
获取并清空故障信息队列

遍历所有设备

flushFaultCodesWithInit
刷新故障码

故障信息放入allFaultInfo channel
(异步写K8s Event)

getCurDeviceFaultCode
通过DCMI获取当前故障码

SetNewFaultAndCacheOnceRecoverFault
设置新故障并缓存一次性恢复故障

SetNetworkNewFaultAndCacheOnceRecoverFault
设置网络新故障

CountFaultDuration
统计故障持续时间

isHealthy
判定设备健康状态

GetFaultType
故障类型?

Healthy

Healthy
(延迟隔离)

Unhealthy

isNetworkHealthy
判定网络健康

GetNetworkFaultType
网络故障类型?

Healthy

Unhealthy

isFirstFlushFault = false

isHealthy 方法逐行解析

func (tool *AscendTools) isHealthy(device *common.NpuDevice) string {
    // 获取故障类型:根据设备的FaultCodes和LogicID查询故障级别
    faultType := common.GetFaultType(device.FaultCodes, device.LogicID)
    
    // 条件1:正常/不处理/子健康 → 健康
    // 条件2:FreeRestartNPU(空闲重启)且设备当前在用且优雅容错开启 → 健康
    //   设计意图:设备在用时不执行空闲重启,等任务结束再处理
    if faultType == common.NormalNPU || faultType == common.NotHandleFault || 
       faultType == common.SubHealthFault ||
       (faultType == common.FreeRestartNPU &&
        tool.npuIsUsedNow(device.DeviceName) && 
        common.ParamOption.GraceToleranceOn == true) {
        return v1beta1.Healthy
    }
    
    // 条件3:预隔离故障但设备在用 → 健康(延迟隔离)
    //   设计意图:设备有任务运行时不立即隔离,等任务完成后再隔离
    if faultType == common.PreSeparateNPU && tool.npuIsUsedNow(device.DeviceName) {
        hwlog.RunLog.Infof("detect %s but device is used, device name: %s", 
            faultType, device.DeviceName)
        return v1beta1.Healthy
    }
    
    // 其他故障类型 → 不健康
    return v1beta1.Unhealthy
}
3.1.5 核心流程:设备IP获取 (GetDeviceIP)

成功

失败

成功

失败

GetDeviceIP(deviceType, phyID)

IsVirtualDev?
虚拟设备?

返回默认IP
'0.0.0.0'

GetLogicIDFromPhysicID
物理ID→逻辑ID

GetChipInfo
获取芯片信息

chip.Name
包含VirMark?

getDcmiDeviceIP
DCMI获取IP

useIpv4?
IPv4可用?

GetDeviceIPAddress(v4)

返回IPv4地址

useIpv4 = false
切换到IPv6

GetDeviceIPAddress(v6)

以fe80开头?
链路本地地址?

返回错误
链路本地IPv6不可用

返回IPv6地址

useIpv4 = true
回退到IPv4

返回错误

设计意图:IPv4/IPv6双栈自适应机制,先尝试IPv4,失败后切换IPv6,IPv6失败再回退IPv4。useIpv4全局变量实现状态记忆,避免每次都做双栈探测。

3.1.6 核心流程:Pod注解校正 (AddPodAnnotation)
func (tool *AscendTools) AddPodAnnotation(podDev *common.PodDeviceInfo, deviceType, hostIp string,
    allDevices []common.NpuDevice) error {
    // 1. 非预置虚拟设备时,追加vGroup信息到设备名
    if !common.ParamOption.PresetVDevice {
        tool.AppendVGroupInfo(podDev.RealDevice)
    }
    
    // 2. 排序设备列表,确保注解值一致性
    sort.Strings(podDev.KltDevice)
    sort.Strings(podDev.RealDevice)
    allUsedDev := strings.Join(podDev.RealDevice, common.CommaSepDev)
    
    // 3. 构建注解校验列表:huawei.com/Ascend910-2kl 和 AscendReal
    annoChecker := []struct{ annoKey, annoValue string }{
        {api.ResourceNamePrefix + common.Pod2kl, 
         strings.Join(podDev.KltDevice, common.CommaSepDev)},
        {api.PodAnnotationAscendReal, allUsedDev},
    }
    
    // 4. 非虚拟设备:检查并校正注解
    annotation := make(map[string]string)
    if !common.IsVirtualDev(deviceType) {
        for _, checker := range annoChecker {
            // 动态场景不校正 huawei.com/npu-core
            if deviceType == common.AiCoreResourceName && 
                checker.annoKey == fmt.Sprintf("%s%s", api.ResourceNamePrefix, deviceType) {
                continue
            }
            if podDev.Pod.Annotations[checker.annoKey] != checker.annoValue {
                // 发现不一致,记录待校正
                annotation[checker.annoKey] = checker.annoValue
            }
        }
    }
    
    // 5. 910/300IDuo场景:校验配置注解(含ranktable信息)
    if tool.name == api.NPULowerCase || tool.name == api.Ascend910 || common.IsContainAll300IDuo() {
        config, err := tool.getConfigAnno(podDev, deviceType, hostIp, allDevices)
        if err == nil {
            key := api.Pod910DeviceAnno  // "ascend-910-configuration"
            if tool.name == api.NPULowerCase {
                key = api.PodNPUDeviceAnno // "ascend-npu-configuration"
            }
            if podDev.Pod.Annotations[key] != config {
                annotation[key] = config
            }
        }
    }
    
    // 6. 如有变化,通过customname替换后更新Pod注解
    if len(annotation) == 0 { return nil }
    newAnnotation := customname.ReplacePodAnnotation(tool.name, annotation)
    return tool.client.TryUpdatePodAnnotation(&podDev.Pod, newAnnotation)
}
3.1.7 核心流程:故障事件写入K8s Event

ctx.Done()

faultInfo <- allFaultInfo

否(恢复)

成功

失败

WriteFaultToEvent (goroutine)

for循环

select

停止

faultEventLimiter
.Allow()?

丢弃事件
限流溢出

doWriteFaultToEvent

GetCardIDDeviceID
(非A5)

GetNodeNameFromEnv

GetPodNameFromEnv

GetFaultAssertionName
故障断言名称

是网络故障?

GetNetworkFaultTypeByCode

GetFaultTypeByCode

构建v1.Event
Type:Warning

Assertion
== FaultOccur?

Type = Warning

Type = Normal

client.CreateEvent

日志: 成功

日志: 失败, continue

限流设计

// faultEventLimiter: 每1/WriteEventRateLimit秒允许1个事件,突发WriteEventRateLimit个
faultEventLimiter = rate.NewLimiter(
    rate.Every(time.Minute/common.WriteEventRateLimit),  // 每分钟N个事件
    common.WriteEventRateLimit)                           // 突发容量N
3.1.8 核心流程:手动隔离NPU处理

handleManuallySeparateNPUFaultInfo

QueryManuallyFaultNPULogicIDsByHandleStatus
(ManuallySeparateNpuAll)

缓存为空?

返回空, 空列表

GetConfigMap(DeviceInfoName)

GetManuallySeparateNPUFromDeviceInfo
从CM获取物理ID列表

遍历已处理的LogicID

GetPhysicIDFromLogicID

物理ID在
CM中?

DeleteManuallyFaultInfo
从缓存删除

保留

遍历CM中的物理ID

GetLogicIDFromPhysicID

LogicID在
缓存中?

日志: 将从CM移除

保留

SetManuallyFaultNPUHandled
标记所有为已处理

convertLogicIDsToDeviceNames
LogicID→设备名

返回手动隔离NPU字符串, 已移除列表

3.1.9 核心流程:LoadDeviceInfoCm — 启动时加载设备信息CM

错误

成功

LoadDeviceInfoCm(ctx)

GetConfigMap(DeviceInfoName)

日志错误, return

GetManuallySeparateNPUFromDeviceInfo
获取手动隔离物理ID列表

遍历物理ID

GetLogicIDFromPhysicID

SaveManuallyFaultInfo
保存到手动故障缓存

GetUpgradeFaultReasonFromDeviceInfo
获取升级故障原因CM

FixManuallySeparateReason
修正原因(补充缺失的手动隔离原因)

ConvertCmToCache
CM格式→缓存格式
(使用GetLogicIDFromPhysicID转换)

SaveUpgradeFaultCache
保存升级故障缓存

有自动填充
物理ID?

timeout !=
MaxReleaseTimeWindow?

结束

asyncReleaseAutoFill
异步释放自动填充

go func()

time.After(timeout)

RemoveTimeoutReasonCache
逐个释放自动填充原因

3.1.10 核心流程:故障丢失事件补偿机制

HandleLostNetworkFaultEvents

nil检查

条件判断:
首次刷新 || 设备刚重置 || 订阅失败 || 网络不健康且>5分钟

generateNetworkFaultEventsBasedOnFaultCacheChange

跳过

GetDeviceAllErrorCode

过滤出网络故障码

queryNetworkStatusWithoutFaultCode
无故障码时查网络状态

GetChangedDevFaultInfo
对比缓存

DoSaveDevFaultInfo

HandleLostChipFaultEvents

nil检查

条件判断:
首次刷新 || 设备刚重置 || 订阅失败 || 不健康且>5分钟

generateChipFaultEventsBasedOnFaultCacheChange

跳过

GetDeviceAllErrorCode
获取所有故障码

过滤掉网络故障码

GetChangedDevFaultInfo
对比缓存, 生成变化事件

DoSaveDevFaultInfo
保存故障信息

HandleDropCardFaultEvents

是 + 之前未掉卡

否 + 之前已掉卡

检查 SubscribeFailed

跳过

generateCardDropFaultEvents

checkCardDropFault
GetDeviceHealth
错误包含DeviceNotReady?

生成掉卡故障事件
CardDrop=true

生成掉卡恢复事件
CardDrop=false

设计意图:故障订阅接口可能丢失事件(订阅失败、设备重置后短暂中断等),这三个方法作为补偿机制,在以下场景主动补查故障状态:

  1. 首次刷新 (isFirstFlushFault):启动时全量补查
  2. 设备刚重置 (initLogicIDs):重置后重新建立故障基线
  3. 订阅失败 (SubscribeFailed):降级为轮询模式
  4. 故障超时未恢复 (moreThanFiveMin):长时间不健康时主动补查
3.1.11 网络状态缓存与限流
func getNetworkStatusCache(phyId int32) string {
    // 1. 获取或初始化限流器
    //    每个物理设备独立限流,避免单设备查询阻塞其他设备
    networkLimiter, ok := networkLimiterMap[phyId]
    if !ok {
        networkLimiter = rate.NewLimiter(
            rate.Every(common.EveryNetworkQueryDuration*time.Minute/common.NetworkQueryRateLimit),
            common.NetworkQueryRateLimit)
        networkLimiterMap[phyId] = networkLimiter
    }
    
    // 2. 限流检查:如果被限流且有缓存,返回缓存值
    linkStatusCache, ok := networkStatusCache[phyId]
    if !networkLimiter.Allow() && ok {
        return linkStatusCache  // 返回缓存,避免频繁查询硬件
    }
    
    // 3. 实际查询hccn接口
    linkStatus, err := hccn.GetNPULinkStatus(phyId)
    if err != nil {
        // 查询失败时缓存为LinkDown(保守策略)
        networkStatusCache[phyId] = npuCommon.NPUNetworkLinkDownStatus
        return npuCommon.NPUNetworkLinkDownStatus
    }
    networkStatusCache[phyId] = linkStatus
    return linkStatus
}

Logo

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

更多推荐