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

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


分析文件清单

序号文件行数核心职责
1pkg/device/ascendcommon.go~1823AscendTools 基类:所有NPU设备管理的公共能力层
2pkg/device/ascend910.go~2223HwAscend910Manager:910系列设备的设备发现、健康监测、热重置容错
3pkg/device/ascendtolerance.go~996HotResetTools:热重置管理器实现,CM同步、任务级容错策略
4pkg/device/ascendcommon_v2.go~56A5超节点扩展属性 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.goA5超节点属性扩展: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/GetKubeClientK8s客户端注入/获取外部初始化
GetChipAICore获取AI Core数量外部
GetName获取设备名称(如"Ascend910")多处
convertLogicIDsToDeviceNamesLogicID列表→设备名字符串handleManuallySeparateNPU
handleManuallySeparateNPUFaultInfo处理手动隔离NPU故障信息UpdateNodeDeviceInfo
LoadDeviceInfoCm从DeviceInfo CM加载缓存外部初始化
asyncReleaseAutoFill异步释放自动填充故障LoadDeviceInfoCm
UpdateNodeDeviceInfo更新节点设备信息到CM910/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
assemble310PMixedPhyDevices310P混合物理设备组装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)多处
getDcmiDeviceIPDCMI接口获取设备IPGetDeviceIP
getDeviceListIP批量获取设备IPgetConfigAnno
getConfigAnno构建Pod配置注解AddPodAnnotation
AddPodAnnotation校正Pod注解ListAndWatch循环
UpdateHealth更新设备健康状态ListAndWatch循环
GetChange检测设备状态变化ListAndWatch循环
setAICoreHealthyIfVNpuvNPU场景同步AI Core健康UpdateHealth
setHealthyIfDuoCardDuo卡场景同步健康UpdateHealth
getUnHealthyCard获取不健康卡列表setHealthyIfDuoCard
ClassifyDevices按类型分类设备(包级函数)ListAndWatch
classifyDevByType按类型分类辅助函数ClassifyDevices
isHealthy判定设备是否健康writeNewFaultCode
isNetworkHealthy判定网络是否健康writeNewFaultCode
npuIsUsedNow检查NPU当前是否有任务isHealthy
getVGroupID获取虚拟设备组IDAppendVGroupInfo
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获取服务器板IDSetDeviceUsage
GetIfCardsInResetting/SetCardsInResetting卡重置状态管理热重置流程
GetResetFailedTimes/SetResetFailedTimes重置失败次数管理热重置流程
WriteFaultToEvent故障写入K8s Event后台goroutine
WriteUpgradeReasonRemoveEvent升级原因释放事件writeDeviceInfoCm
doWriteFaultToEvent实际写EventWriteFaultToEvent
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上所有设备不健康
setUnhealthyForA3A3卡设置关联设备不健康
GetAssociatedLogicIDs获取A3关联LogicID列表
clearDeviceStatus清除设备重置状态
handleResetProcess处理重置流程
checkFaultIsExist检查故障是否仍存在
upgradeHotResetError升级热重置错误为隔离
refreshDevFaultInfoForResetProcess刷新重置过程中的故障信息
execHotReset执行热重置
isChipActive检查芯片是否活跃(有任务)
canBeReset检查所有芯片是否可重置
canA3BeResetA3卡可重置检查
getBusyChipListFromPod从Pod列表获取繁忙芯片
DoWithVolcanoListAndWatchVolcano调度ListAndWatch入口
updateDeviceInfo更新设备信息到CM
isNeedBlockAllDevice是否需要阻塞所有设备调度
update910NodeLabel更新910节点标签
getHealthAndRecoverDev获取健康和恢复设备
getNewNetworkRecoverDev获取新网络恢复设备
getPatchLabel生成节点标签补丁
getRecoverLabelFromNodeSets从节点标签获取恢复集
toStandardDeviceFmt转为标准设备格式
updateHotResetCache更新热重置缓存
updateUpgradeErrorInfo更新升级错误信息
setTaskDevInfoCache设置任务设备信息缓存
handleUpdateCaches批量更新缓存
convertPhysicIdToLogicId物理ID→逻辑ID转换
isReSchedulingScene是否为重调度场景
isTaskInReset任务是否在重置中
filterDevStatus过滤重置中设备状态
filterDevStatusForA3A3卡过滤重置状态
processAllTask处理所有任务容错
policyLevelHandle策略级别处理
isolateSceneHandle隔离场景处理
runProcessTask运行任务处理
restartRequestProcessL2故障处理(请求重启)
handleSucceedRestartRequestL2成功处理
checkDevErrorCode检查设备错误码清除
restartProcessL3故障处理(设备重启)
upgradeRestartProcessL3升级为重置
upgradeRestartRequestProcessL2升级为重置
updateResetCMStatus更新重置CM状态
updateResetCMStatusWithoutWait更新重置CM状态(不等)
resetProcessL5故障处理(强制重置)
waitForAllFaultyDeviceProcessesToZero等待故障设备进程归零
canContinueGraceProcess检查是否可继续容错
updateResetCMStatusToIsolate更新CM为隔离状态
getA3LogicMapByAssociationA3关联LogicID映射
getNeedResetDeviceLogicIdMap获取需重置设备映射
addAllLogicIdsToFaultMap添加Ring上所有LogicID
checkNumberOfAllProcessIsZero检查所有进程是否归零
upgradeResetProcessL5升级为隔离
preProcess预处理(写CM/设状态)
postProcess后处理(清理状态)
refreshDevFaultInfo刷新设备故障信息
getNeedResetDevMapForA3A3需重置设备映射
getResetIndexForA3A3重置索引
resetDeviceOnce执行一次设备重置
canResetDeviceByLogicID按LogicID检查可重置
canResetDevice检查设备可重置(忙/次数)
execResetDevice执行设备重置(带内)
execOutBandReset执行带外重置
scanDeviceForThirdParty第三方设备扫描
execRescan执行重新扫描
fillResetDevs补充设备信息(PhyID/CardID)
updateResetInfo更新重置信息文件
resetDeviceOutBand带外重置单设备
isNetResetCompleted网络重置完成检查
waitDeviceResetComplete等待设备重置完成
isRunningDistributed是否分布式训练
isShouldCheckNet是否需检查网络
isRingResetCompleteRing重置完成检查
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)
handlePodEventPod事件处理
handlePodAddEventPod添加事件(创建目录/写CM文件)
writeCmToFileWhilePodAddPod添加时写CM到文件
handlePodDeleteEventPod删除事件(清理文件/目录)
getPodFromCache从缓存获取Pod
GetCMFromCache从缓存获取CM
writeCMToFile写CM数据到文件
handleConfigMapEventCM事件处理
handleCMUpdateEventCM更新事件
handleCMDeleteEventCM删除事件
writeCmToFileSystem写CM到文件系统
checkConfigMapCM过滤器(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

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

更多推荐