已合并
新增提案:ofep-0031-鲲鹏机密容器Operator #59
pervasive创建于 1月26日
新增提案:ofep-0031-鲲鹏机密容器Operator #59
已合并
pervasive创建于 1月26日
3 个文件变更+2127-0
@@ -0,0 +1,827 @@
1+---
2+# 提案标题
3+title: 鲲鹏机密容器Operator
4+# 提案编号
5+ofep-number: 31
6+# 提案作者
7+authors:
8+ - "@ruanhanqing"
9+# 提案主导SIG
10+owning-sig: sig-container-platform
11+# 提案协作SIG
12+participating-sigs:
13+# 提案状态(初步草案|准备开始实现|已在SIG中实现并合并|提案被暂缓|提案被否决|作者主动撤回提案|被另一个oFEP取代)
14+status: provisional
15+# 创建日期
16+creation-date: 2026-01-20
17+# 评审人
18+reviewers:
19+ - TBD
20+# 批准人
21+approvers:
22+ - TBD
23+# 相关联的其他oFEP
24+see-also:
25+# 当前oFEP替代了哪些已有提案
26+replaces:
27+# 当前oFEP被哪些提案替代,当status为replaced时需要填写此字段
28+replaced-by:
29+# 此oFEP当前开发阶段
30+stage: alpha
31+# 最近一次推进的版本
32+latest-milestone: "v1.19"
33+# 各阶段目标版本
34+milestone:
35+ alpha: "v1.19"
36+ beta: "v1.20"
37+ stable: "v1.22"
38+# 功能开关及影响组件
39+feature-gates:
40+# 是否支持关闭该功能
41+disable-supported: true
42+# 该功能引入的监控指标
43+metrics:
44+---
45+<!--
46+**注意:**当你的 oFEP 完成时,应删除所有这些注释块。
47+ 
48+要开始使用此模板:
49+- [ ] **选择一个托管 SIG。**
50+ 确保该问题领域是 SIG 感兴趣的。如果没有 SIG 的赞助,oFEP 不应提交。
51+ -[]**在 openfuyao/ofep 中创建问题**
52+ 提交增强功能跟踪问题时,请务必填写该模板中的所有字段。其中一个字段要求提供指向 oFEP 的链接。你可以留空该字段,直到提交此 oFEP 后再返回到增强功能并添加链接。
53+- [ ] **复制此模板目录。**
54+ 将此模板复制到所属 SIG 的目录中,并将其命名为“ofep-NNNN-short-descriptive-title”,其中“NNNN”是分配给上述增强功能的问题编号(没有前导零填充)。
55+- [ ] **尽可能多地填写以上oFEP元数据。**
56+ 至少,你应该填写“标题”、“作者”、“SIG所有者”、“状态”和与日期相关的字段。
57+- [ ] **请尽可能详细地填写此文件。**
58+ 至少,你应该填写“摘要”和“动机”部分。如果你已经和相关的 SIG 进行过前期沟通和想法验证,那么这两部分应该会很容易完成。
59+- [ ] **为此 oFEP 创建 PR。**
60+ 将其指派给正在支持该流程的 SIG(特别兴趣小组)成员。
61+- [ ] **尽早合并并迭代。**
62+ 避免纠结于具体细节,而应致力于明确 oFEP 的目标并快速合并。最好的方法是从概要部分开始,然后在后续的 PR 中逐步完善细节。
63+ 
64+oFEP 合并并不意味着它已完成或获得批准。任何标记为“临时”的 oFEP 都是工作文档,可能会发生变更。你可以按以下方式标记正在积极讨论的部分:
65+ 
66+编辑 oFEPS 时,请尽量使用范围明确、主题单一的 PR,以保持讨论的集中性。如果你不同意文档中已有的内容,请提交新的 PR 并提出修改建议。
67+ 
68+一个 oFEP 对应其整个生命周期内的一项“功能”或“增强”。例如,从 Beta 版升级到 GA 版无需新的 oFEP。如果出现属于 oFEP 的新细节,请编辑 oFEP。一旦某个功能被“实现”,重大变更应该获得新的 oFEP。
69+ 
70+最新(以及该文件的可能来源)的规范位置是[0000-ofep-template.md](/0000-ofep-template.md)。
71+ 
72+**注意:**任何将 oFEP 推进为“implementable”状态的 PR,或在标记为“implementable”后的重大更改,都必须得到每个 oFEP 批准人的批准。如果这些批准人均不合适(例如离开社区、角色变更等),则该列表的更改应由其余批准人和/或所属 SIG 批准。
73+-->
74+ 
75+# oFEP-0031:鲲鹏机密容器Operator
76+ 
77+<!--
78+这是你的 oFEP 的标题。请保持简短、简洁且描述性强。一个好的标题可以帮助传达什么是 oFEP,以及有助于审查与追踪。
79+-->
80+ 
81+<!--
82+目录(TOC)有助于快速跳转到 oFEP 的各个部分,同时突出显示超出标准模板所提供的其他信息。
83+ 
84+确保目录已用<code>&lt;!-- toc --&rt;&lt;!-- /toc --&rt;</code>标签,然后用`hack/update-toc.sh`生成。
85+-->
86+ 
87+<!-- toc -->
88+- [发布签核清单](#release-signoff-checklist)
89+- [摘要](#summary)
90+- [动机](#motivation)
91+ - [目标](#goals)
92+ - [非目标](#non-goals)
93+- [提案](#proposal)
94+ - [用户故事(可选)](#user-stories-optional)
95+ - [故事 1](#story-1)
96+ - [故事 2](#story-2)
97+ - [注释/约束/警告(可选)](#notesconstraintscaveats-optional)
98+ - [风险与缓解措施](#risks-and-mitigations)
99+- [设计细节](#design-details)
100+ - [测试计划](#test-plan)
101+ - [先决条件测试更新](#prerequisite-testing-updates)
102+ - [单元测试](#unit-tests)
103+ - [集成测试](#integration-tests)
104+ - [e2e 测试](#e2e-tests)
105+ - [毕业标准](#graduation-criteria)
106+ - [升级/降级策略](#upgrade--downgrade-strategy)
107+ - [版本倾斜策略](#version-skew-strategy)
108+- [生产准备情况评审问卷](#production-readiness-review-questionnaire)
109+ - [功能启用和回滚](#feature-enablement-and-rollback)
110+ - [推出、升级和回滚规划](#rollout-upgrade-and-rollback-planning)
111+ - [监控要求](#monitoring-requirements)
112+ - [依赖项](#dependencies)
113+ - [可扩展性](#scalability)
114+ - [故障排除](#troubleshooting)
115+- [实施历史](#implementation-history)
116+- [缺点](#drawbacks)
117+- [替代方案](#alternatives)
118+- [所需基础设施(可选)](#infrastructure-needed-optional)
119+<!-- /toc -->
120+ 
121+## 发布签核清单
122+<!--
123+**需要采取的行动:**为了将代码合并到一个版本中,在[openfuyao/ofep]引用此oFEP并在目标版本的[增强冻结]之前瞄准发布里程碑**中必须存在问题。
124+ 
125+对于对核心代码或流程/程序进行更改的增强功能,例如:[openfuyao/openfuyao],我们需要完成以下发布签署清单。
126+ 
127+完成后勾选这些,以便发布团队跟踪。为了发布增强,必须更新这些检查表项。
128+-->
129+ 
130+标记有(R)的项目*在达到里程碑/发布*之前是必需的。
131+- [ ](R)发布里程碑中的增强问题,链接到 [openfuyao/ofep] 中的 oFEP 目录
132+- [ ] (R) oFEP 审批者已批准 oFEP 状态为“可实施”
133+- [ ] (R) 设计细节已适当记录
134+- [ ](R)测试计划已到位,并考虑了 SIG 架构和 SIG 测试的输入(包括测试重构)
135+ - [ ] 针对所有 Beta API 操作(端点)进行 e2e 测试
136+ - [ ] (R) 确保 GA e2e 测试满足一致性测试的要求
137+ - [ ] (R) GA e2e 测试至少需要两周时间才能证明测试结果无 flake(不稳定或偶发失败)
138+- [ ] (R) 毕业标准已设定
139+ - [ ] (R) 所有 GA 端点必须通过[一致性测试]
140+- [ ] (R) 生产准备情况审查完成
141+- [ ] (R) 生产准备情况审查已获批准
142+- [ ] “实施历史”部分已更新里程碑
143+- [ ] 面向用户的文档已在 [openfuyao/docs] 创建,以便发布到 [openfuyao.com]
144+- [ ] 支持文档 - 例如,额外的设计文档、邮件列表讨论/SIG 会议链接、相关 PR/问题、发行说明
145+ 
146+<!--
147+**注意:**此清单是迭代的,每次考虑将此增强功能作为里程碑时都应进行审查和更新。
148+-->
149+ 
150+- [openfuyao.com](https://openfuyao.com/)
151+- [openfuyao/ofep](https://gitcode.com/openfuyao/ofep)
152+- [openfuyao/docs](https://gitcode.com/openfuyao/docs)
153+ 
154+## 概括
155+<!--
156+这部分对于生成高质量、以用户为中心的文档(如发行说明或开发路线图)非常重要。应该在实现开始之前收集这些信息,以避免要求实现者在编写发行说明和实现功能本身之间分散注意力。oFEP 编辑器和SIG文档应该有助于确保“摘要”部分的语气和内容对广泛的受众有用。
157+ 
158+好的摘要可能至少有一段长度。
159+ 
160+在本节和下一节中,请遵循[文档样式指南]的指导方针。特别是,将代码行包装到合理的长度,使审阅者更容易引用特定的部分,并尽量减少更新的差异。
161+-->
162+ 
163+鲲鹏机密容器基于鲲鹏TEE,通过k8s+containerd+Kata+QEMU+KVM+CoCo的整套软件栈进行构建,在开源Kata/CoCo社区的基础上进行了定制和适配,具备远程证明、镜像签名和加密、机密容器设备直通等安全特性。鲲鹏机密容器涉及组件多,部署方案复杂。本提案旨在为 openFuyao 平台打造鲲鹏机密容器环境的Opeartor化快速安装部署解决方案,以降低用户使用门槛。通过一系列技术文档编制、自动化脚本开发、定制化Operator部署及测试验证等工作,推动鲲鹏机密容器在实际场景中的应用与推广,并为openFuyao平台提供安全方面的重要技术支撑。
164+ 
165+## 动机
166+<!--
167+本节用于明确列出该oFEP的动机、目标和非目标。描述变更的重要性以及对用户的好处。
168+-->
169+ 
170+### 社区现状
171+ 
172+- 《[ofep-0008-基于国产TEE的openFuyao平台机密容器安装部署解决方案](https://gitcode.com/openFuyao/ofep/blob/main/ofeps/sig-container-platform/ofep-0008-基于国产TEE的openFuyao平台机密容器安装部署解决方案.md)》构建了针对海光csv机密容器的Operator安装部署解决方案,但不支持鲲鹏机密容器。
173+- Kata/CoCo官方社区只支持Intel、AMD、IBM等硬件平台的机密容器,不支持鲲鹏机密容器。
174+- [openEuler/virtCCA_sdk社区](https://gitcode.com/openeuler/virtCCA_sdk/blob/master/kata-v3.15.0/doc/kata机密容器.md)提供了鲲鹏机密容器的编译、部署、验证指导文档,是鲲鹏官方对Kata/CoCo机密容器的适配,但手工操作步骤较多,没有提供完整的企业级解决方案。
175+ 
176+因此,我们希望在openFuyao平台当前已支持海光csv机密容器的基础上,增加对鲲鹏机密容器环境的快速部署解决方案。
177+ 
178+### 目标
179+<!--
180+列出oFEP的具体目标。它想要达到什么目标?我们怎么知道这已经成功了?
181+-->
182+ 
183+- 提供鲲鹏机密容器相关组件的快速编译构建能力,包括一键式构建脚本和指导文档。
184+- 提供针对鲲鹏机密容器定制和优化的Operator,在openFuyao管理的Kubernetes集群中实现鲲鹏机密容器环境的快速安装部署。
185+- 制定鲲鹏机密容器特性测试方法,提供详细的文档和指引。
186+ 
187+### 非目标
188+<!--
189+什么超出了这个oFEP的范围?列出非目标有助于集中讨论并取得进展。
190+-->
191+ 
192+- 不涉及国外的TEE技术(如 AMD SEV、Intel SGX/TDX)
193+ 
194+- 不涉及海光csv机密容器。
195+ 
196+- 不包含对OpenFuyao现有核心架构或基础功能的改造,不涉及将机密容器组件的构建/部署能力集成到openFuyao平台的版本构建/部署流程中。
197+ 
198+- 不涉及鲲鹏TEE机密容器底层硬件技术的研发,仅基于现有TEE技术进行方案构建。
199+ 
200+- 不涉及鲲鹏机密容器对Kata/CoCo的功能适配和增强,仅基于现有能力进行安装部署解决方案的构建。
201+ 
202+## 提案
203+<!--
204+**这是我们真正进入提案具体内容的部分。**
205+这一部分应包含足够的细节,使评审人员能清晰理解你到底在提出什么建议,
206+但不应涉及 API 设计或具体实现细节。
207+ 
208+请阐明:
209+- **预期目标是什么?**
210+- **我们如何衡量成功?**
211+ 
212+请将更详细的设计和实现细节放在下方的 “设计细节” 部分中。
213+-->
214+ 
215+鲲鹏机密容器的软件架构如下图。
216+ 
217+![0005-kunpeng-coco-component](./images/0005-kunpeng-coco-component.PNG)
218+ 
219+主要组件说明如下:
220+ 
221+- **机密容器运行时相关组件**
222+ - containerd-shim-kata-v2:kata shim,负责启动POD VM及将CRI请求转发给kata-agent,由Kata社区提供
223+ - nydus-snapshotter:负责拦截容器镜像拉取流程,将控制权交给image-rs,由containerd社区提供
224+ - kata-agent:负责kata容器的生命周期管理,由Kata社区提供
225+ - image-rs:负责机密容器镜像拉取,由CoCo社区提供
226+ - ASR:api-server-rest,负责代理容器对CDH的请求,由CoCo社区提供
227+ - CDH:confidential-data-hub,负责处理机密容器秘钥,由CoCo社区提供
228+ - AA:attestation-agent,负责身份证明和密钥获取,由CoCo社区提供
229+ - initrd:机密虚拟机GuestOS的initrd镜像,由Kata社区提供构建脚本
230+ - kernel:机密虚拟机GuestOS的内核镜像,由Kata社区提供构建脚本
231+ - qemu:机密虚拟机的hypervisor,由Kata社区提供构建脚本
232+ 
233+- **trustee相关组件**
234+ - KBS:Key Broker Service,负责基于远程证明的身份认证和授权、秘钥资源存储和访问控制,由CoCo社区提供
235+ - AS:Attestation Service,证明服务,负责验证远程报告,由CoCo社区提供
236+ - RVPS:Reference Value Provider Service,负责提供度量基线值的注册和查询,由CoCo社区提供
237+ 
238+鲲鹏官方对Kata和CoCo做了一些适配和定制,相关补丁patch在openEuler社区维护。
239+ 
240+ 
241+ 
242+本提案以鲲鹏virtCCA所提供的TEE技术为基础,为openFuyao平台打造企业级的鲲鹏机密容器环境安装部署解决方案,旨在降低开发者和终端用户在使用机密容器过程中的技术门槛。主要包括以下目标:
243+ 
244+1. 提供鲲鹏机密容器相关组件的快速编译构建能力,包括一键式构建脚本和指导文档。
245+ 
246+ (1)提供一键式编译构建脚本,从源码编译构建机密容器运行时相关组件。源码来源为Kata [kata-containers](https://github.com/kata-containers/kata-containers)、CoCo [guest-components](https://github.com/confidential-containers/guest-components)、[openEuler/virtCCA_SDK对Kata/CoCo的patch补丁](https://gitcode.com/openeuler/virtCCA_sdk/blob/master/kata-v3.15.0/doc/kata机密容器.md)、[containerd/nydus-snapshotter](https://github.com/containerd/nydus-snapshotter)。编译组件包括containerd-shim-kata-v2、qemu、guest firmware、guest kernel、guest initrd、kata-agent、image-rs、ASR、CDH、AA,打包到kata-static-tar.xz中。以及nydus-snapshotter,输出镜像为reqs-payload.tar。
247+ 
248+ (2)提供一键式编译构建脚本,从源码编译trustee相关组件。源码来源为CoCo [trustee](https://github.com/confidential-containers/trustee)、openEuler/virtCCA_SDK对CoCo的patch补丁。编译组件为AS、KBS、RVPS。
249+ 
250+ (3)提供编译构建指导文档,以便用户能够便捷、准确地完成相关操作。
251+ 
252+2. 提供针对鲲鹏机密容器定制和优化的Operator,在openFuyao管理的Kubernetes集群中实现鲲鹏机密容器环境的快速安装部署。
253+ 
254+ (1)提供cc-Operator及相关部署配置文件。cc-Operator用于部署机密容器运行时相关组件。cc-Operator复用CoCo官方[cc-Operator](https://github.com/confidential-containers/operator)基础上针对鲲鹏容器进行定制和优化。
255+ 
256+ (2)提供trustee-Operator及相关部署配置文件。trustee-Operator用于部署trustee相关组件。trustee-Opeartor复用CoCo官方[trustee-Operator](https://github.com/confidential-containers/trustee-operator)基础上针对鲲鹏容器进行定制和优化。
257+ 
258+ (3)提供一键式部署cc-Opeartor和trustee-Opeartor和导入部署配置文件的自动化脚本。
259+ 
260+ (4)提供cc-Opeartor和trustee-Opeartor安装部署指导文档。
261+ 
262+ (5)提供在鲲鹏硬件服务器上开启和配置机密容器功能的指导文档,明确对硬件的要求,约束,配置最佳实践。
263+ 
264+3. 制定鲲鹏机密容器特性测试方法,提供详细的文档和指引。
265+ 
266+ (1)提供详细的鲲鹏机密容器特性测试文档,指导用户部署鲲鹏机密容器、验证容器镜像签名/加密、远程证明等能力。
267+ 
268+基于此,本提案请求在`confidential-containers-deployment`代码仓下新增代码,存放鲲鹏机密容器部署相关的文档、脚本和代码等资料。
269+ 
270+### 用户故事(可选)
271+<!--
272+详细说明如果该 oFEP 被实施,用户将能够做哪些事情。请尽可能提供细节,以便人们理解系统将“如何”运作。此部分的目标是:让用户对提案有真实的感受,而不是陷入技术细节的泥淖中。
273+-->
274+ 
275+#### 故事 1
276+ 
277+根据文档和自动化脚本,一键式完成鲲鹏机密容器运行时相关组件和trustee相关组件的编译构建。
278+ 
279+#### 故事 2
280+ 
281+根据文档和Opeartor,快速完成鲲鹏机密容器环境的安装部署。
282+ 
283+#### 故事3
284+ 
285+根据指导文档,准确顺利的完成鲲鹏机密容器的基本功能验证。
286+ 
287+### 注释/限制/注意事项(可选)
288+<!--
289+该提案有哪些注意事项或潜在限制?
290+有没有上文未能充分表达的重要细节?
291+请在此处根据需要尽可能详细地展开说明。
292+这部分也非常适合用于讲解一些核心概念及它们之间的关联关系。
293+-->
294+ 
295+**提案涉及技术名词说明**
296+ 
297+1. **REE(Rich Execution Environment) - 富执行环境**
298+ 
299+ 鲲鹏机密计算基于鲲鹏处理器的TrustZone技术,通过分时复用,在同一套硬件系统上划分了两个独立的环境Normal World和Secure World,Normal World为常规环境,即REE。Secure World为安全环境,即TEE。
300+ 
301+2. **TEE(Trusted Execution Environment)- 可信执行环境**
302+ TEE是可信执行环境的简称,指在CPU与内存中单独划分出的一块安全区域,该区域与普通操作系统完全隔离。它通过硬件级防护机制,确保区域内敏感数据与关键代码在执行过程中不被外界窃取或篡改。即使普通操作系统受到攻击,TEE内的信息仍能保持安全。
303+ 
304+3. **CoCo(Confidential Containers)- 机密容器**
305+ CoCo是Confidential Containers的简称,是CNCF旗下的开源项目。它基于硬件TEE技术,结合云原生技术体系,旨在为运行在不受用户控制的云计算基础设施上的敏感数据和应用提供安全可信的计算环境。本提案也是以CoCo提供的框架与方案为基础,依托国产鲲鹏TEE技术,在符合Kubernetes标准的平台上创建和运行机密容器。
306+ 
307+4. **nydus-snapshotter**
308+ 普通容器的镜像在主机上拉取和存储。对于机密容器而言,镜像数据若存储在主机上(即TEE环境之外),可能被恶意篡改,从而无法保证TEE内部运行程序的完整性和安全性。
309+ 为解决这一问题,需借助containerd的[Remote Snapshotter](https://github.com/containerd/containerd/blob/main/docs/remote-snapshotter.md)功能,跳过主机端的镜像拉取步骤。CoCo社区未选择单独开发自己的Remote Snapshotter,而是复用了已有的[nydus-snapshotter](https://github.com/containerd/nydus-snapshotter)实现,以降低开发与维护成本。
310+ 在实际方案中,镜像拉取并非由nydus完成:nydus-snapshotter仅负责返回镜像元数据,最终会在TEE(即机密虚拟机)内部,由image-rs组件完成容器镜像的拉取操作。
311+ 
312+5. **trustee**
313+ trustee是CoCo项目下的核心代码仓库,主要利用TEE的可认证(Attestability)特性,提供了 [Remote ATtestation procedureS (RATS) Architecture](https://www.rfc-editor.org/rfc/rfc9334.html) 的具体实现。它为运行机密容器的TEE提供便捷的远程认证与秘钥管理服务,是CoCo实现镜像签名、镜像加密等增强特性的基础。该组件包含三个相互关联的服务模块:
314+ 
315+ - **KBS**(Key Broker Service):提供远程证明与机密信息交付服务。在RATS架构中,KBS承担"Relying Party"角色,接收来自Attester的证据后,提交给Verifier进行认证,并根据认证结果和预设策略评估是否向Attester返回其请求的机密资源。
316+ 
317+ - **AS**(Attestation Service):负责验证TEE证据,对应RATS架构中的"Verifier"。在验证过程中,需从RVPS获取参考值,再依据预设策略评估证据所提供的声明是否符合客户预期。
318+ 
319+ - **RVPS**(Reference Value Provider Service):核心功能是管理参考值,为AS验证TEE证据提供必要支持。
320+ 
321+6. **guest-components**
322+ guest-components 是CoCo项目下的另一代码仓库,包含可在TEE内部运行的各类组件,主要组件功能如下:
323+ 
324+ - **attestation-agent**(简称AA):对应RATS架构中的"Attester",负责收集TEE证据,并与外部的KBS服务通信。
325+ 
326+ - **confidential-data-hub**(简称CDH):提供基于gRPC或ttRPC协议的资源获取服务接口。KBS是其资源提供者之一,需通过attestation-agent请求获取。
327+ 
328+ - **api-server-rest**:以RESTful API的形式对CDH与AA的服务进行封装,方便其他模块及容器应用调用相关功能。
329+ 
330+ - **image-rs**:在TEE内部从远程镜像仓库拉取容器镜像的核心组件。
331+ 
332+### 风险与缓解措施
333+<!--
334+这个提案存在哪些风险?我们将如何加以缓解?请从广泛的角度思考,例如包括安全性问题,以及它可能对更大范围的 openfuyao 生态系统产生的影响。 安全性将由谁进行评审,以及如何评审?用户体验(UX)将由谁进行评审,以及如何评审?建议考虑邀请 SIG 外部或子项目之外的相关人员参与评估。
335+-->
336+ 
337+## 设计细节
338+<!--
339+本节应包含足够的信息,以便读者能够清楚理解你所提出的变更具体是什么。这可能包括 API 规格说明(虽然并非必须)或代码片段。如果对该提案将如何实施存在任何疑问,应在此处进行详细讨论。
340+-->
341+ 
342+以下架构图展示了如何通过`Confidential Containers Operator(简称cc-Operator)``Trustee Operator`在Kubernetes集群中快速部署机密容器运行时环境,以及二者之间的关联关系。
343+![architecture_with_operators](./images/architecture_with_operators.png)
344+ 
345+`cc-Operator`直接复用CoCo官方的[cc-Operator](https://github.com/confidential-containers/operator),部署`cc-Operator`后,会在Kubernetes集群的`Control Plane`中创建`CcRuntime`的自定义资源定义(CRD),同时部署用于监听其状态变化的`cc-operator-controller-manager`POD服务。
346+ 
347+`CcRuntime CRD`定义了部署机密容器运行时的一系列参数配置,包括payloadImage(指定kata-depoly镜像包)、preInstall.image(指定reqs-payload镜像包,主要是nydus-snapshotter组件)、runtimeClasses等。本需求提供针对鲲鹏机密容器定制和适配的`CcRuntime CR`
348+ 
349+当在集群内创建或更新`CcRuntime`实例时,`cc-operator-controller-manager`会触发一系列`DaemonSet`的创建流程。其中,
350+ 
351+- `cc-operator-pre-install-daemon`负责在节点上安装部署`nydus-snapshotter``containerd`,其核心作用是将默认在节点主机拉取容器镜像的流程,调整为在机密虚拟机内部完成拉取操作。
352+ 
353+- `cc-operator-daemon-install`的功能则是在节点上部署启动机密虚拟机所需的各类组件,包括qemu、kernel、initrd、containerd-shim-kata-v2等,并在集群中创建和配置对应的`RuntimeClass`
354+ 
355+ 
356+ 
357+`Trustee Operator`可以在Kubernetes集群中快速部署KBS服务。需要注意的是,部署KBS服务的集群与运行机密容器的集群无需为同一集群。关键在于,KBS必须部署在用户完全可信且可控的环境中,同时需确保`attestation-agent`能够从机密虚拟机内部访问KBS提供的服务。
358+ 
359+KBS借助可信执行环境(TEE)的可认证性(Attestability),为机密容器提供远程认证鉴权与秘密管理服务,进而实现容器镜像签名及加密的增强特性,保障运行于机密虚拟机内的代码具备完整性且不可篡改。
360+ 
361+`Trustee Operator`直接复用CoCo官方的[Trustee Operator](https://github.com/confidential-containers/trustee-operator),部署`Trustee Operator`后,会在Kubernetes集群的`Control Plane`中创建`KbsConfig`的自定义资源定义(CRD),同时部署用于监听其状态变化的`trustee-operator-controller-manager`POD服务。
362+ 
363+`KbsConfig CRD`定义了trustee服务的一系列参数配置,包括kbs/AS服务监听的IP/端口等。本需求提供针对鲲鹏机密容器定制和适配的`KbsConfig CR`
364+ 
365+当在集群内创建或更新`KbsConfig CR`时,`trustee-operator-controller-manager`会触发启动`trustee-deployment` POD,该POD负责完成trustee相关服务的部署。
366+ 
367+ 
368+ 
369+实现说明:
370+ 
371+1. Kata和CoCo版本跟随最新版本的virtCCA_sdk已经适配的版本,virtCCA_sdk版本为0.1.37,Kata版本为3.15.0,CoCo为0.12.0。cc-Opeartor版本为0.13.0,trustee-Opeartor版本为0.5.0。
372+2. virtCCA_sdk对Kata和CoCo适配的patch编译构建时直接从virtCCA_sdk社区在线下载,不归档到openFuyao社区。
373+3. 鲲鹏机密容器环境部署相关的文档和自动化脚本代码规划路径:https://gitcode.com/openFuyao/confidential-containers-deployment/tree/master/deploy/kunpeng
374+4. 编译构建脚本代码规划路径:https://gitcode.com/openFuyao/confidential-containers-deployment/tree/master/build/kunpeng
375+5. 鲲鹏机密容器验证相关文档代码规划路径:https://gitcode.com/openFuyao/confidential-containers-deployment/tree/master/doc/kunpeng
376+ 
377+### 测试计划
378+ 
379+<!--
380+**注意:**在该提案尚未被纳入某个正式版本前,此部分不是必需的。
381+其目标是确保我们不会接收缺乏充分测试的增强功能。
382+所有代码都应具备充分的测试(最终也应满足测试覆盖率要求)。在撰写测试计划时,请遵循 openFuyao 测试指南。
383+-->
384+ 
385+[ ] 我/我们理解,相关组件的所有者可能会要求更新已有的测试,以便在提交实现该增强功能所需的更改之前,使代码达到足够稳固的质量标准。
386+ 
387+##### 先决条件测试更新
388+<!--
389+根据评审者的反馈,描述在实施此项增强功能之前需要补充哪些额外的测试,以确保该增强特性也具备稳固的基础。
390+-->
391+ 
392+##### 单元测试
393+<!--
394+原则上,所有新增的代码都应具有完整的单元测试覆盖率,因此列出确切的测试项并不会带来额外价值。
395+但如果无法实现完整的单元测试覆盖,请说明原因,并解释为何在这种情况下这是可以接受的。
396+-->
397+ 
398+<!--
399+此外,对于 Alpha 阶段,请尽量列出为了实现该增强功能将涉及的核心包(core package),并提供这些包当前的单元测试覆盖率,格式如下:
400+ 
401+- <软件包>: <日期> - <当前测试覆盖率>
402+这可以帮助我们在扩展生产代码、实施该增强功能之前,识别并推进某些测试覆盖率的改进工作。
403+-->
404+ 
405+- `<软件包>`: `<日期>` - `<测试覆盖率>`
406+ 
407+##### 集成测试
408+<!--
409+集成测试允许控制用于启动被测二进制文件的配置参数。
410+这与不允许配置参数的 e2e 测试不同。
411+这样做可以测试非默认选项以及多个不同的、可能冲突的命令行选项。
412+ 
413+如果集成测试不是必要的或有用的,请解释原因。
414+-->
415+ 
416+<!--
417+当准备将功能纳入某个正式版本时,需要填写此问题。
418+ 
419+- 对于 Alpha 阶段,请描述将添加哪些测试,以确保该增强功能具备良好的质量保障。
420+- 对于 Beta 和 GA 阶段,需要记录测试已经编写、被定期执行,且结果稳定。
421+ 
422+你可以通过以下方式提供相关证明:
423+- 指向 gitcode 源代码的永久链接
424+- 指向定期测试作业的链接,并按测试名称过滤
425+- 在 openfuyao 缺陷追踪工具中进行搜索。
426+-->
427+ 
428+- 测试名称
429+ 
430+##### e2e 测试
431+<!--
432+当该功能计划纳入某个正式版本时,应填写此问题。
433+- 对于 Alpha 阶段,请描述将添加哪些测试,以确保该增强功能具备良好的质量保障。
434+- 对于 Beta 和 GA 阶段,需要说明测试已经编写、被定期执行,且结果稳定。
435+ 
436+可通过以下方式提供证明材料:
437+- 指向 gitcode 源代码的永久链接
438+- 指向定期测试作业的链接,并按测试名称过滤
439+- 在 openfuyao 缺陷追踪工具中进行搜索。
440+ 
441+作为进入 GA(正式可用)阶段的标准,我们期望过去一个月内不存在任何非基础设施相关的 flaky 测试(不稳定测试)。
442+如果你认为无需添加端到端测试(e2e),请解释其原因及合理性。
443+-->
444+ 
445+- 测试名称
446+ 
447+### 毕业标准
448+<!--
449+ 
450+> **注意:** *在功能尚未计划纳入某个正式版本时,本节无需填写。*
451+> 请在此处定义该功能的毕业(Graduation)里程碑。
452+> 毕业条件可以基于 API 成熟度、[Feature Gate] 的推进阶段,或其他方式来定义。此处应保持高层次,重点说明评估是否可以毕业时将参考哪些信号(信心指标)。
453+> 在制定毕业标准时,请参考以下内容:
454+> - [成熟度等级(`alpha`、`beta`、`stable`)]
455+> - [Feature Gate 生命周期][feature gate]
456+> - [弃用政策][deprecation-policy]
457+> 请明确说明“毕业”的定义。
458+> 通常我们倾向于无论功能通过何种方式访问,均采用相同的阶段划分(alpha、beta、GA)。
459+ 
460+#### 🔹 Alpha 阶段
461+- 功能已通过 Feature Gate 实现(默认关闭)
462+- 初步的端到端(e2e)测试已完成并启用
463+#### 🔸 Beta 阶段
464+- 收集开发者反馈及用户调研结果
465+- 完成核心功能 A、B、C
466+- 额外的测试已加入 Testgrid,并在 oFEP 中有链接说明
467+- 实现更严格的测试形式,例如降级测试和可扩展性测试
468+- 所有功能均已实现
469+- 所有安全相关机制均已完备
470+- 所有监控要求均已实现
471+- 所有测试要求均已满足
472+- 所有预发布阶段的问题与缺陷均已修复
473+ 
474+> **注意:** Beta 阶段的评估标准必须包含所有功能、安全性、监控与测试的要求,并解决所有已知问题或差距。
475+ 
476+#### 🟢 GA 阶段
477+- 有 N 个真实生产环境中的使用示例
478+- 有 N 次实际安装部署记录
479+- 已留出反馈窗口期,收集充分用户反馈
480+- 所有在 Beta 阶段反馈的问题与缺陷都已解决
481+ 
482+> **注意:** GA 阶段的毕业标准不得再包含功能、安全性、监控或测试方面的要求,这些应在 Beta 阶段全部完成。
483+> **注意:** 通常,我们在 Beta 和 GA 之间至少间隔两个版本周期,以便留出时间获取用户反馈和发现潜在问题,避免在连续发布中遗漏反馈环节。
484+> **对于非可选(默认启用)功能在进入 GA 阶段时,毕业标准必须包含 [一致性测试(Conformance tests)]。**
485+ 
486+#### 🧯 弃用(Deprecation)
487+- 宣布弃用现有功能标志(flag)并说明支持策略
488+- 自引入替代功能以来,已过去两个版本(以解决版本偏差问题)
489+- 处理来自 gitcode Issues 等反馈渠道中的用法变更或行为差异问题
490+- 正式弃用原有标志 (flag)
491+-->
492+### 升级/降级策略
493+<!--
494+> 指导提案人在功能设计时兼顾向前兼容性、配置迁移、Feature Gate 管理等问题。
495+-->
496+<!--
497+如果适用,该组件在升级和降级时将如何处理?请确保在测试计划中包含这部分内容。
498+ 
499+在制定该增强功能的升级/降级策略时,请考虑以下问题:
500+- 为了保持现有行为不变,集群在升级时是否需要进行调用方式、配置或 API 使用上的任何更改?
501+- 为了使用该增强功能,集群在升级时是否需要对调用方式、配置或 API 使用做出调整?
502+-->
503+ 
504+### 版本倾斜策略
505+<!--
506+确保你的提案在 openfuyao 集群中升级时能够兼容不同版本组件之间的运行差异。
507+-->
508+<!--
509+如果适用,该组件在面对与其他组件的版本不一致(version skew)时将如何处理?有哪些兼容性保证?请确保在测试计划中包括这一部分。
510+ 
511+在为此增强功能制定版本偏差应对策略时,请考虑以下问题:
512+- 该功能是否涉及控制面(Control Plane)与节点(Node)之间的协同行为?
513+- 当使用该功能时,版本落后三个版本(n-3)的 kubelet 或 kube-proxy 会如何表现?
514+- 当使用该功能时,版本落后一个版本(n-1)的 kube-controller-manager 或 kube-scheduler 会有何行为?
515+- 节点上的其他组件是否会发生变更? 例如,CSI(容器存储接口)、CRI(容器运行时接口)或 CNI(容器网络接口)是否需要在 kubelet 之前被更新?
516+-->
517+ 
518+## 生产可用性审查
519+<!--
520+**生产可用性审查(Production Readiness Review,PRR)** 的目的是确保即将合并到 openfuyao 中的功能:
521+- 可观测(observable)、可扩展(scalable)、可支持(supportable);
522+- 能在生产环境中安全运行;
523+- 在出现故障时能够被禁用或回滚。
524+ 
525+**要使 oFEP 进入 `implementable` 状态并被纳入发布版本,必须完成并通过生产可用性审查问卷(PRR Questionnaire)。**
526+ 
527+在某些情况下,元数据中也应包含这些问题的答案:
528+- 这样可以便于自动化工具验证是否进行了审查;
529+- 同时有助于减少评审负担并降低审查延迟。
530+-->
531+ 
532+### 功能启用和回滚
533+<!--
534+当针对 alpha 版本发布时,必须完成此部分。
535+-->
536+ 
537+###### 如何在实时集群中启用/禁用此功能?
538+<!--
539+选择其中一个并删除其余的。
540+-->
541+ 
542+- [ ] **功能开关(Feature gate)**(请同时在元数据中填写相应字段)
543+ - 功能开关名称:
544+ - 依赖该功能开关的组件:
545+- [ ] **其他机制**
546+ - 描述机制实现方式:
547+ - 启用/禁用该功能是否会导致控制平面需要停机?
548+ - 启用/禁用该功能是否会导致节点需要停机或重新部署(reprovision)?
549+ 
550+###### 启用该功能会改变任何默认行为吗?
551+<!--
552+任何默认行为的变更都可能让用户感到意外,或破坏现有的自动化流程,因此在这方面必须格外小心。
553+-->
554+ 
555+###### 该功能一旦启用,是否可以禁用(即我们可以回滚启用)?
556+<!--
557+**请描述该功能对现有工作负载可能造成的影响**(例如,如果这是一个运行时特性,它是否可能破坏现有应用程序的行为?)。
558+ 
559+通常,通过将功能开关(Feature Gate)设置为 `false` 并重启相应组件,即可禁用该功能。除这个操作之外,不应再需要其他变更来完成禁用。
560+ 
561+**注意:**在元数据中,也请将 `disable-supported` 字段设置为 `true``false`
562+-->
563+ 
564+###### 如果该功能之前已回滚,现在我们重新启用它会发生什么情况?
565+ 
566+###### 是否有任何针对功能启用/禁用的测试?
567+<!--
568+当前的端到端测试框架(e2e framework)**尚不支持启用或禁用 Feature Gate**
569+然而,对于处理数据的每个组件,必须编写包含**启用和未启用该功能场景的单元测试**
570+ 
571+如果该功能修改了 API 类型,**至少应该考虑添加转换测试(conversion tests)**
572+ 
573+此外,如果该功能引入了新的 API 字段,**还必须编写测试 Feature Gate 开关行为的单元测试**——也就是验证以下情形:
574+- “当我先启用 Feature Gate 并写入了包含新字段的对象后,随后将其禁用,会发生什么?”
575+-->
576+ 
577+### 推出、升级和回滚规划
578+<!--
579+当该功能计划从 Beta 阶段发布至正式版本时,必须填写本节内容。
580+-->
581+ 
582+###### 部署或回滚为何会失败?这会影响正在运行的工作负载吗?
583+<!--
584+**尽可能保持警觉和审慎**——例如,假设在发布过程中某些组件会中途重启,会发生什么?
585+ 
586+请务必考虑以下场景:
587+- **高可用(HA)集群**:在该场景下,功能开关(Feature Flag)可能仅在部分 API Server 上启用,而其他仍为禁用状态;
588+- **大型集群**:在这种情况下,功能的启用/禁用可能会分批分节点地推进,需考虑该过程中的一致性与兼容性问题。
589+-->
590+ 
591+###### 哪些具体指标应该通知回滚?
592+<!--
593+当该功能还处于早期阶段时,用户应关注哪些信号,以便及早发现可能存在的严重问题?
594+-->
595+ 
596+###### 升级和回滚测试了吗?升级->降级->升级的路径测试了吗?
597+<!--
598+请描述已完成的手动测试及其结果。
599+从长远来看,我们可能会要求实施自动化的升级/回滚测试,但目前我们仍缺少相关的机制和工具,因此暂时无法实现。
600+-->
601+ 
602+###### 推出时是否伴随任何功能、API、API 类型的字段、标志等的弃用和/或删除?
603+<!--
604+即使应用弃用政策,仍可能会让一些用户感到惊讶。
605+-->
606+ 
607+### 监控要求
608+<!--
609+当计划将功能从 Beta 阶段纳入某个正式版本(release)时,必须完成此部分内容。
610+对于 GA(正式可用)阶段,该部分也是必须填写的:审批人应能够基于实际生产环境中的经验,确认之前各项回答的准确性。
611+-->
612+ 
613+###### 操作员如何确定该功能是否正在被工作负载使用?
614+<!--
615+理想情况下,应使用指标(metric)来实现。
616+通过对 Kubernetes API 的操作(例如检查是否存在设置了字段 X 的对象)应作为最后手段。
617+请避免将日志或事件用于此目的。
618+-->
619+ 
620+###### 使用此功能的人如何知道它适用于他们的实例?
621+<!--
622+例如,如果这是一个与 Pod 相关的功能,则应能够针对每个 Pod 确定该功能是否正常工作。
623+请从以下选项中选择一项并删除其余内容。
624+请在下方详细描述所有对最终用户可见的内容,确保他们能够验证该功能是否已正确启用并正常运行。
625+> 请注意:最终用户通常无法查看组件日志或访问系统指标(metrics)。
626+-->
627+ 
628+- [ ] 事件
629+ - 事件原因:
630+- [ ] API .状态
631+ - 条件名称:
632+ - 其他领域:
633+- [ ] 其他(作为最后手段)
634+ - 细节:
635+ 
636+###### 增强的合理 SLO(服务级别目标)是什么?
637+<!--
638+这是你定义该功能“正常服务质量”(Quality of Service,QoS)表现的机会。
639+我们无法提供全面的指导,但从高层角度来看(还需要更精确定义),这些表现可能包括:
640+- 每天返回 5XX 错误的 API 调用比例 ≤ 1%
641+- CronJob 的任务实际创建时间与预期创建时间之差的绝对值在一天内的 99 百分位 ≤ 10%
642+- 每天 99.9% 的 `/health` 请求返回 HTTP 200 状态码
643+ 
644+这些目标将有助于你在下一个问题中确定需要衡量的服务指标(SLIs)。
645+-->
646+ 
647+###### 运维人员可以使用哪些服务级别指标(SLIs)来判断服务的健康状况?
648+<!--
649+请选择以下选项中的一个,并删除其余内容。
650+-->
651+ 
652+- [ ] 指标
653+ - 指标名称:
654+ - [可选] 聚合方法:
655+ - 暴露指标的组件:
656+- [ ] 其他(作为最后手段)
657+ - 细节:
658+ 
659+###### 是否存在任何尚未覆盖的指标(metrics),可以用来进一步提升该功能的可观测性?
660+<!--
661+请描述这些指标本身,以及未添加它们的原因(例如:成本高、实现复杂等)。
662+-->
663+ 
664+### 依赖项
665+<!--
666+当计划将该功能从 Beta 阶段纳入某个正式版本(release)时,必须完成本节内容。
667+-->
668+ 
669+###### 此功能是否依赖于集群中运行的任何特定服务?
670+<!--
671+请同时考虑集群级别的服务(例如 metrics-server)以及节点级别的代理(例如某个特定版本的 CRI)。
672+重点关注该功能所依赖的 **外部或可选服务**
673+例如,如果该功能依赖云服务商的 API、或外部的软件定义存储(SDS)或网络控制面板等服务,则应明确列出。
674+ 
675+对于每一项依赖项,请填写以下内容:
676+- 当前用户工作负载的运行情况
677+- 新建工作负载的创建情况
678+- 集群级别的服务(例如 DNS)
679+ 
680+填写格式如下:
681+```
682+- [依赖项名称]
683+ - 使用说明:
684+ - 若该服务发生中断,对该功能的影响:
685+ - 若该服务性能下降或错误率升高,对该功能的影响:
686+```
687+-->
688+ 
689+### 可扩展性
690+<!--
691+对于 Alpha 阶段,鼓励填写本节内容:评审人员应考虑这些问题,并尝试给出回答。
692+对于 Beta 阶段,本节为必填项:评审人员必须回答这些问题。
693+对于 GA(正式发布)阶段,本节同样为必填项:审批人员应能根据实际生产经验,确认之前给出的所有回答。
694+-->
695+ 
696+###### 启用/使用此功能会导致任何新的 API 调用吗?
697+<!--
698+**请描述相关 API 调用,包括以下信息:**
699+- **API 调用类型**(例如:`PATCH pods`
700+- **预估调用频率(吞吐量)**
701+- **调用发起组件**(例如:`Kubelet``Feature-X-controller`
702+ 
703+重点关注以下场景:
704+- **组件开始列出(list)或监听(watch)以前未处理的资源**
705+- **某些 Kubernetes 资源发生变化后,触发新的 API 请求行为**
706+ 例如:更新对象 X 后又触发了对对象 Y 的修改或创建
707+- **用于状态对齐(state reconciliation)的定期 API 请求**
708+ 例如:周期性获取资源状态、心跳上报、领导者选举等
709+ -->
710+ 
711+###### 启用/使用此功能是否会导致引入新的 API 类型?
712+<!--
713+请描述它们(指代 API 对象或资源),并提供以下信息:
714+- **API 类型**(API type)
715+- **每个集群支持的最大对象数量**
716+- **每个命名空间支持的最大对象数量**(仅适用于具备命名空间作用域的对象)
717+-->
718+ 
719+###### 启用/使用此功能是否会导致对云提供商的任何新的 API 调用?
720+<!--
721+请进行如下描述:
722+- **涉及哪些 API:**
723+- **预估调用增加量:**
724+-->
725+ 
726+###### 启用/使用此功能是否会导致现有 API 对象的大小或数量增加?
727+<!--
728+**请描述新增或受影响的资源对象,提供以下信息:**
729+- **API 类型(API type(s)):**
730+- **预估对象体积增加量:**(例如:新增注解字段,大小为 32 字节)
731+- **预估新增对象数量:**(例如:为每个现有 Pod 创建一个新的对象 X)
732+-->
733+ 
734+###### 启用/使用此功能是否会导致现有 SLI/SLO 所涵盖操作的耗时增加?
735+<!--
736+请思考是否会新增额外操作或在现有流程中引入新的中间步骤(例如:为了启动一个容器,现在需要先执行步骤 X 等)。
737+请在下方详细描述这些新增内容。
738+-->
739+ 
740+###### 启用/使用此功能是否会导致任何组件的资源使用率(CPU、RAM、磁盘、IO 等)不可忽略的增加?
741+<!--
742+需要注意的事项包括:
743+- 增加的内存状态(in-memory state);
744+- 新引入的耗时计算操作;
745+- 频繁的磁盘访问(包括日志量增加);
746+- 大量发送或接收的网络数据流量等。
747+ 
748+请从小型和大型集群的不同规模角度,**全面评估这些资源消耗**,并结合 Kubernetes 的[支持上限(supported limits)](https://git.k8s.io/community/sig-scalability/configs-and-limits/thresholds.md)进行考量。
749+-->
750+ 
751+###### 启用/使用此功能是否会导致某些节点资源(PID、套接字、inode 等)耗尽?
752+<!--
753+**请不要只关注理想情况,更重要的是评估异常或极端情况**,例如:
754+- 探针响应时间从毫秒级变成分钟级;
755+- 异常或失败的 Pod 持续占用资源等。
756+ 
757+**如果该功能可能会导致某些资源被耗尽**,请说明:
758+- 如何通过 Kubernetes 已有的资源限制机制进行缓解(例如每节点最大 Pod 数);
759+- 或该 oFEP 是否引入了新的限制来控制这些风险。
760+ 
761+此外,还请说明:
762+- **是否已经进行了性能相关测试(或计划进行),用于更好地理解性能特征,并验证所声明的资源使用上限?**
763+-->
764+ 
765+### 故障排除
766+<!--
767+**当该功能计划从 Beta 阶段发布至正式版本(release)时,本节必须填写。**
768+ 
769+对于 **GA(正式发布)阶段**,本节同样为必填项:审批人员应能够根据实际生产环境中的经验,确认之前的各项回答。
770+ 
771+当前的 **“排障(Troubleshooting)” 部分**,在功能发布流程中相当于临时承担了 **“运维手册(Playbook)”** 的角色。
772+未来可能会将其拆分为一个专门的 `Playbook` 文档(可能还会包含一些监控信息)。但目前仍将其保留在此处。
773+-->
774+ 
775+###### 如果 API 服务器和/或 etcd 不可用,此功能如何反应?
776+ 
777+###### 其他已知故障模式有哪些?
778+<!--
779+**对于每种故障模式,请使用以下模板逐项填写信息:**
780+- **[故障模式简要描述]**
781+ - **检测方式(Detection):**
782+ 如何通过指标(metrics)检测该问题?换句话说:
783+ 操作人员**如何在不登录 master 或 worker 节点的情况下排障**?
784+ - **缓解手段(Mitigations):**
785+ 尤其对于已在运行的用户工作负载,可采取哪些措施止血/减缓影响?
786+ - **诊断信息(Diagnostics):**
787+ 有哪些有用的日志消息?其对应的**日志级别**(logging level)是多少?
788+ ✅ *注:日志诊断信息在功能进入 Beta 阶段前可不填写。*
789+ - **测试情况(Testing):**
790+ 针对该故障是否有测试用例?若无,请说明原因。
791+ -->
792+ 
793+###### 如果未满足 SLO,应采取哪些步骤来确定问题?
794+ 
795+## 实施历史
796+<!--
797+**在本节中应记录一个 oFEP 生命周期中的主要里程碑。**
798+ 
799+可能包括但不限于以下内容:
800+- `摘要``动机` 部分被合并,表示 SIG 已接受该提案
801+- `提案` 部分被合并,表示对设计方案达成一致
802+- 实现工作的启动日期
803+- 首个包含该 oFEP 初始版本的 openfuyao 发布版本
804+- 该 oFEP 成功毕业为正式可用(GA)的 openfuyao 版本
805+- oFEP 被废弃或被其他提案取代的时间
806+-->
807+ 
808+## 缺点
809+<!--
810+为什么不实施这个 oFEP?从反面角度分析该提案可能带来的负面影响、权衡成本、潜在风险或争议点。
811+-->
812+ 
813+## 替代方案
814+<!--
815+**你还考虑过哪些其他方案?为什么将它们排除?**
816+这些备选方案不需要像最终提案那样详尽,但应提供足够的信息来阐述其基本思路,并说明为什么它们不可接受。
817+-->
818+ 
819+## 所需基础设施(可选)
820+<!--
821+**如果你需要从项目或 SIG 获得资源支持,请在本节中列出。** 例如:
822+- 请求创建新的子项目(subproject)
823+- 新建 gitcode 仓库(repos)
824+- 配置 gitcode 相关权限或细节(如 team 成员或 CI 权限等)
825+ 
826+提前在这里列出这些需求,有助于 SIG 尽早启动相关流程,加快资源配置效率。
827+-->
@@ -0,0 +1,1300 @@
1+---
2+title: DRA拓扑亲和调度
3+ofep-number: 0062
4+authors:
5+ - "@ruanhanqing"
6+owning-sig: sig-orchestration-engine
7+participating-sigs:
8+ 
9+status: implementable
10+creation-date: 2025-07-20
11+reviewers:
12+ 
13+approvers:
14+ 
15+see-also:
16+ 
17+replaces:
18+ 
19+replaced-by:
20+ 
21+stage: alpha
22+latest-milestone: "v26.09"
23+milestone:
24+ alpha: "v26.09"
25+ beta: "v26.12"
26+ stable: "v26.12"
27+feature-gates:
28+disable-supported:
29+metrics:
30+---
31+<!--
32+**注意:**当你的 oFEP 完成时,应删除所有这些注释块。
33+ 
34+要开始使用此模板:
35+- [ ] **选择一个托管 SIG。**
36+ 确保该问题领域是 SIG 感兴趣的。如果没有 SIG 的赞助,oFEP 不应提交。
37+- [ ] **在 openfuyao/ofep 中创建问题**
38+ 提交增强功能跟踪问题时,请务必填写该模板中的所有字段。其中一个字段要求提供指向 oFEP 的链接。你可以留空该字段,直到提交此 oFEP 后再返回到增强功能并添加链接。
39+- [ ] **复制此模板目录。**
40+ 将此模板复制到所属 SIG 的目录中,并将其命名为"ofep-NNNN-short-descriptive-title",其中"NNNN"是分配给上述增强功能的问题编号(没有前导零填充)。
41+- [ ] **尽可能多地填写以上oFEP元数据。**
42+ 至少,你应该填写"标题"、"作者"、"SIG所有者"、"状态"和与日期相关的字段。
43+- [ ] **请尽可能详细地填写此文件。**
44+ 至少,你应该填写"摘要"和"动机"部分。如果你已经和相关的 SIG 进行过前期沟通和想法验证,那么这两部分应该会很容易完成。
45+- [ ] **为此 oFEP 创建 PR。**
46+ 将其指派给正在支持该流程的 SIG(特别兴趣小组)成员。
47+- [ ] **尽早合并并迭代。**
48+ 避免纠结于具体细节,而应致力于明确 oFEP 的目标并快速合并。最好的方法是从概要部分开始,然后在后续的 PR 中逐步完善细节。
49+ 
50+oFEP 合并并不意味着它已完成或获得批准。任何标记为"临时"的 oFEP 都是工作文档,可能会发生变更。你可以按以下方式标记正在积极讨论的部分:
51+ 
52+编辑 oFEPS 时,请尽量使用范围明确、主题单一的 PR,以保持讨论的集中性。如果你不同意文档中已有的内容,请提交新的 PR 并提出修改建议。
53+ 
54+一个 oFEP 对应其整个生命周期内的一项"功能"或"增强"。例如,从 Beta 版升级到 GA 版无需新的 oFEP。如果出现属于 oFEP 的新细节,请编辑 oFEP。一旦某个功能被"实现",重大变更应该获得新的 oFEP。
55+ 
56+最新(以及该文件的可能来源)的规范位置是[0000-ofep-template.md](/0000-ofep-template.md)。
57+ 
58+**注意:**任何将 oFEP 推进为"implementable"状态的 PR,或在标记为"implementable"后的重大更改,都必须得到每个 oFEP 批准人的批准。如果这些批准人均不合适(例如离开社区、角色变更等),则该列表的更改应由其余批准人和/或所属 SIG 批准。
59+-->
60+# oFEP-0062:DRA拓扑亲和调度
61+ 
62+<!--
63+这是你的 oFEP 的标题。请保持简短、简洁且描述性强。一个好的标题可以帮助传达什么是 oFEP,以及有助于审查与追踪。
64+-->
65+ 
66+<!--
67+目录(TOC)有助于快速跳转到 oFEP 的各个部分,同时突出显示超出标准模板所提供的其他信息。
68+ 
69+确保目录已用<code>&lt;!-- toc --&rt;&lt;!-- /toc --&gt;</code>标签,然后用`hack/update-toc.sh`生成。
70+-->
71+ 
72+<!-- toc -->
73+- [发布签核清单](#release-signoff-checklist)
74+- [摘要](#summary)
75+- [动机](#motivation)
76+ - [目标](#goals)
77+ - [非目标](#non-goals)
78+- [提案](#proposal)
79+ - [用户故事(可选)](#user-stories-optional)
80+ - [故事 1](#story-1)
81+ - [故事 2](#story-2)
82+ - [故事 3](#story-3)
83+ - [注释/约束/警告(可选)](#notesconstraintscaveats-optional)
84+ - [风险与缓解措施](#risks-and-mitigations)
85+- [设计细节](#design-details)
86+ - [拓扑关系查询](#拓扑关系查询)
87+ - [DRA驱动上报拓扑关系](#dra驱动上报拓扑关系)
88+ - [通过ResourceClaim实现亲和调度](#通过resourceclaim实现亲和调度)
89+ - [预置ResourceClaimTemplate](#预置resourceclaimtemplate)
90+ - [测试计划](#test-plan)
91+ - [先决条件测试更新](#prerequisite-testing-updates)
92+ - [单元测试](#unit-tests)
93+ - [集成测试](#integration-tests)
94+ - [e2e 测试](#e2e-tests)
95+ - [毕业标准](#graduation-criteria)
96+ - [升级/降级策略](#upgrade--downgrade-strategy)
97+ - [版本倾斜策略](#version-skew-strategy)
98+- [生产准备情况评审问卷](#production-readiness-review-questionnaire)
99+ - [功能启用和回滚](#feature-enablement-and-rollback)
100+ - [推出、升级和回滚规划](#rollout-upgrade-and-rollback-planning)
101+ - [监控要求](#monitoring-requirements)
102+ - [依赖项](#dependencies)
103+ - [可扩展性](#scalability)
104+ - [故障排除](#troubleshooting)
105+- [实施历史](#implementation-history)
106+- [缺点](#drawbacks)
107+- [替代方案](#alternatives)
108+- [所需基础设施(可选)](#infrastructure-needed-optional)
109+<!-- /toc -->
110+ 
111+## 发布签核清单
112+<!--
113+**需要采取的行动:**为了将代码合并到一个版本中,在[openfuyao/ofep]引用此oFEP并在目标版本的[增强冻结]之前瞄准发布里程碑**中必须存在问题。
114+ 
115+对于对核心代码或流程/程序进行更改的增强功能,例如:[openfuyao/openfuyao],我们需要完成以下发布签署清单。
116+ 
117+完成后勾选这些,以便发布团队跟踪。为了发布增强,必须更新这些检查表项。
118+-->
119+ 
120+标记有(R)的项目*在达到里程碑/发布*之前是必需的。
121+- [ ](R)发布里程碑中的增强问题,链接到 [openfuyao/ofep] 中的 oFEP 目录
122+- [ ] (R) oFEP 审批者已批准 oFEP 状态为"可实施"
123+- [ ] (R) 设计细节已适当记录
124+- [ ](R)测试计划已到位,并考虑了 SIG 架构和 SIG 测试的输入(包括测试重构)
125+ - [ ] 针对所有 Beta API 操作(端点)进行 e2e 测试
126+ - [ ] (R) 确保 GA e2e 测试满足一致性测试的要求
127+ - [ ] (R) GA e2e 测试至少需要两周时间才能证明测试结果无 flake(不稳定或偶发失败)
128+- [ ] (R) 毕业标准已设定
129+ - [ ] (R) 所有 GA 端点必须通过[一致性测试]
130+- [ ] (R) 生产准备情况审查完成
131+- [ ] (R) 生产准备情况审查已获批准
132+- [ ] "实施历史"部分已更新里程碑
133+- [ ] 面向用户的文档已在 [openfuyao/docs] 创建,以便发布到 [openfuyao.com]
134+- [ ] 支持文档 - 例如,额外的设计文档、邮件列表讨论/SIG 会议链接、相关 PR/问题、发行说明
135+ 
136+<!--
137+**注意:**此清单是迭代的,每次考虑将此增强功能作为里程碑时都应进行审查和更新。
138+-->
139+ 
140+- [openfuyao.com](https://openfuyao.com/)
141+- [openfuyao/ofep](https://gitcode.com/openfuyao/ofep)
142+- [openfuyao/docs](https://gitcode.com/openfuyao/docs)
143+ 
144+## 概括
145+<!--
146+这部分对于生成高质量、以用户为中心的文档(如发行说明或开发路线图)非常重要。应该在实现开始之前收集这些信息,以避免要求实现者在编写发行说明和实现功能本身之间分散注意力。oFEP 编辑器和SIG文档应该有助于确保"摘要"部分的语气和内容对广泛的受众有用。
147+ 
148+好的摘要可能至少有一段长度。
149+ 
150+在本节和下一节中,请遵循[文档样式指南]的指导方针。特别是,将代码行包装到合理的长度,使审阅者更容易引用特定的部分,并尽量减少更新的差异。
151+-->
152+ 
153+在昇腾AI处理器集群环境中,不同NPU卡之间的拓扑连接方式以及NPU与CPU的NUMA亲和性对AI训练/推理任务的性能有显著影响。本提案旨在基于Kubernetes动态资源分配(DRA)机制,实现NPU设备的拓扑感知亲和调度,通过在ResourceSlice中上报拓扑关系属性,并利用ResourceClaim的属性约束能力,优化多卡AI训练/推理任务的设备分配策略,提升训练/推理性能。
154+ 
155+## 动机
156+<!--
157+本节用于明确列出该oFEP的动机、目标和非目标。描述变更的重要性以及对用户的好处。
158+-->
159+ 
160+### 目标
161+<!--
162+列出oFEP的具体目标。它想要达到什么目标?我们怎么知道这已经成功了?
163+-->
164+ 
165+- DRA驱动能够上报NPU设备的拓扑关系属性(包括NUMA节点、HCCS环、PCIe Root等)
166+- 支持通过ResourceClaim约束实现多种拓扑亲和调度策略(同HCCS环、同NUMA节点、同PCIe Root等)
167+- 支持310p、910b、910c的拓扑关系解析和上报
168+ 
169+### 非目标
170+<!--
171+什么超出了这个oFEP的范围?列出非目标有助于集中讨论并取得进展。
172+-->
173+ 
174+- 不涉及跨节点的拓扑亲和调度(仅关注节点内拓扑)
175+- 不涉及DRA调度器节点打分能力的实现(优先占满原则)
176+- 不涉及异构设备间(如NPU与RDMA网卡)的亲和调度优化
177+ 
178+## 提案
179+<!--
180+**这是我们真正进入提案具体内容的部分。**
181+这一部分应包含足够的细节,使评审人员能清晰理解你到底在提出什么建议,
182+但不应涉及 API 设计或具体实现细节。
183+ 
184+请阐明:
185+- **预期目标是什么?**
186+- **我们如何衡量成功?**
187+ 
188+请将更详细的设计和实现细节放在下方的 "设计细节" 部分中。
189+-->
190+ 
191+### 用户故事(可选)
192+<!--
193+详细说明如果该 oFEP 被实施,用户将能够做哪些事情。请尽可能提供细节,以便人们理解系统将"如何"运作。此部分的目标是:让用户对提案有真实的感受,而不是陷入技术细节的泥淖中。
194+-->
195+ 
196+#### 故事 1
197+ 
198+AI训练团队需要在Atlas 200T A2 Box16服务器上运行一个8卡训练任务,希望8张NPU卡位于同一个HCCS环内以获得最佳通信性能。通过引用预置的ResourceClaimTemplate,团队可以直接申领8张卡,系统自动确保这8张卡来自同一个HCCS环,无需手动指定具体的NPU卡编号。
199+ 
200+#### 故事 2
201+ 
202+AI工程师需要运行一个跨环的12卡训练任务,希望将12张卡平均分配到两个HCCS环,并且环间对应的NPU卡通过PIX连接以获得较好的跨环通信性能。通过使用具有多个约束的ResourceClaim,工程师可以声明12张卡的拓扑约束,系统自动满足对称分配要求。
203+ 
204+#### 故事 3
205+ 
206+性能优化工程师需要验证NUMA亲和性对训练性能的影响。通过使用支持优先级排序的ResourceClaim,工程师可以声明优先选择同HCCS环的NPU卡,如果无法满足则退而求其次选择同NUMA节点的卡,系统按照优先级自动选择最优拓扑组合。
207+ 
208+### 注释/限制/警告(可选)
209+<!--
210+该提案有哪些注意事项或潜在限制?
211+有没有上文未能充分表达的重要细节?
212+请在此处根据需要尽可能详细地展开说明。
213+这部分也非常适合用于讲解一些核心概念及它们之间的关联关系。
214+-->
215+ 
216+**限制:**
217+ 
218+- 不支持运行时动态调整已分配设备的拓扑约束
219+ 
220+### 风险与缓解措施
221+<!--
222+这个提案存在哪些风险?我们将如何加以缓解?请从广泛的角度思考,例如包括安全性问题,以及它可能对更大范围的 openfuyao 生态系统产生的影响。 安全性将由谁进行评审,以及如何评审?用户体验(UX)将由谁进行评审,以及如何评审?建议考虑邀请 SIG 外部或子项目之外的相关人员参与评估。
223+-->
224+ 
225+**风险1:拓扑信息上报不准确导致调度失败或性能下降**
226+ 
227+缓解措施:
228+- DRA驱动启动时对拓扑信息进行校验,确保上报数据的准确性
229+- 提供拓扑信息查询和验证工具,方便用户核对
230+ 
231+**风险2:约束过于严格导致资源碎片化**
232+ 
233+缓解措施:
234+- 通过DRA框架的优先级排序机制,允许业务在严格约束无法满足时降级到较宽松约束
235+ 
236+## 设计细节
237+<!--
238+本节应包含足够的信息,以便读者能够清楚理解你所提出的变更具体是什么。这可能包括 API 规格说明(虽然并非必须)或代码片段。如果对该提案将如何实施存在任何疑问,应在此处进行详细讨论。
239+-->
240+ 
241+### 拓扑关系查询
242+ 
243+通过以下命令可以查询昇腾NPU设备CPU和NPU的亲和性关系、多NPU之间的拓扑结构:
244+ 
245+```bash
246+npu-smi info -t topo
247+```
248+ 
249+拓扑关系说明:**按照性能从快到慢排序**,NPU卡之间的通信方式有以下几种。
250+ 
251+- X:表示卡自身与自身通信
252+- HCCS:表示两张NPU卡之间通过HCCS连接,速度最快。
253+- PIX:在同一个NUMA节点下通过**单个PCIe switch**连接两个NPU之间的拓扑互联关系,速度极快
254+- PXB:在同一个NUMA节点下通过**多个PCIe switches**连接两个NPU之间的拓扑互联关系,速度较快
255+- PHB(PCIe Host Bridge):在同一个NUMA节点下的NPU之间的拓扑互联关系,表示两张卡连接在同一个CPU的**同一个PCIe主机桥下**,数据传输不需要跨越NUMA节点,直接在PCIe局部总线层完成交互,通信速度较慢。
256+- SYS:表示两张卡位于不同的**不同的NUMA节点下**。通信速度最慢。
257+ 
258+参考资料:[Atlas A2 中心推理和训练硬件 26.0.RCx npu-smi 命令参考 02 - 华为](https://support.huawei.com/enterprise/zh/doc/EDOC1100568421/20aa1a9d?idPath=23710424|251366513|254884019|261408772|261457531)
259+ 
260+**示例1:一个有8张310P3 NPU卡(一卡两芯)的服务器,拓扑关系如下**
261+ 
262+```
263+ NPU0 NPU1 NPU2 NPU3 NPU4 NPU5 NPU6 NPU7 CPU Affinity
264+NPU0 X SYS SYS SYS PHB SYS SYS SYS 144-167
265+NPU1 SYS X SYS SYS SYS PHB SYS SYS 96-119
266+NPU2 SYS SYS X SYS SYS SYS PHB SYS 48-71
267+NPU3 SYS SYS SYS X SYS SYS SYS PHB 0-23
268+NPU4 PHB SYS SYS SYS X SYS SYS SYS 144-167
269+NPU5 SYS PHB SYS SYS SYS X SYS SYS 96-119
270+NPU6 SYS SYS PHB SYS SYS SYS X SYS 48-71
271+NPU7 SYS SYS SYS PHB SYS SYS SYS X 0-23
272+ 
273+Legend:
274+ 
275+ X = Self
276+ SYS = Path traversing PCIe and NUMA nodes. Nodes are connected through SMP, such as QPI, UPI.
277+ PHB = Path traversing PCIe and the PCIe host bridge of a CPU.
278+ HCCS = Connection traversing HCCS.
279+ NA = Unknown relationship.
280+```
281+ 
282+以上拓扑关系解读为:
283+ 
284+8张NPU卡两两配对:
285+ 
286+- NPU0和NPU4互为PHB:NPU0和NPU4插在同一个PCIe桥下。
287+- NPU1和NPU5互为PHB。
288+- NPU2和NPU6互为PHB。
289+- NPU3和NPU7互为PHB。
290+ 
291+CPU亲和性关系:与NPU具有亲和性关系的CPU。
292+ 
293+- NPU0和NPU4共享CPU亲和核心144-167。当NPU0和NPU4与CPU进行数据交互时,最快、路径最短的CPU逻辑核心编号是144-167。当某个AI进程绑定了NPU0或NPU4,那么把该进程的CPU核心限制在144-167范围内性能最好。
294+- NPU1和NPU5共享CPU亲和核心96-119
295+- NPU2和NPU6共享CPU亲和核心48-71
296+- NPU3和NPU7共享CPU亲和核心0-23
297+ 
298+**示例2:一个有8张910B4卡的服务器(Atlas 800I A2 HCCS款),NPU拓扑关系输出如下**
299+ 
300+```
301+[root@n2 ~]# npu-smi info -t topo
302+       NPU0 NPU1 NPU2 NPU3 NPU4 NPU5 NPU6 NPU7 CPU Affinity
303+NPU0 X HCCS HCCS HCCS HCCS HCCS HCCS HCCS 144-167
304+NPU1 HCCS X HCCS HCCS HCCS HCCS HCCS HCCS 144-167
305+NPU2 HCCS HCCS X HCCS HCCS HCCS HCCS HCCS 96-119
306+NPU3 HCCS HCCS HCCS X HCCS HCCS HCCS HCCS 96-119
307+NPU4 HCCS HCCS HCCS HCCS X HCCS HCCS HCCS 0-23
308+NPU5 HCCS HCCS HCCS HCCS HCCS X HCCS HCCS 0-23
309+NPU6 HCCS HCCS HCCS HCCS HCCS HCCS X HCCS 48-71
310+NPU7 HCCS HCCS HCCS HCCS HCCS HCCS HCCS X 48-71
311+ 
312+Legend:
313+ 
314+ X = Self
315+ SYS = Path traversing PCIe and NUMA nodes. Nodes are connected through SMP, such as QPI, UPI.
316+ PHB = Path traversing PCIe and the PCIe host bridge of a CPU.
317+ PIX = Path traversing a single PCIe switch
318+ PXB = Path traversing multipul PCIe switches
319+ HCCS = Connection traversing HCCS.
320+ NA = Unknown relationship.
321+```
322+ 
323+NPU-to-NPU拓扑关系解读:
324+ 
325+8张NPU卡通过HCCS组成一个8P Full Mesh完全互联架构,任意NPU卡之间都是直达的。
326+ 
327+说明:一些老款Atlas 800训练服务器是4P Full Mesh架构,4张NPU卡组成HCCS环,环间通过PCIe通信。
328+ 
329+CPU-to-NPU亲和关系解读:
330+ 
331+4个CPU,每个物理CPU直连2张NPU卡,0和1,2和3,4和5,6和7分别共享一个NUMA节点。
332+ 
333+ 
334+ 
335+**示例3:一个Atlas 200T A2 Box16异构子框服务器的拓扑关系如下**
336+ 
337+```
338+ NPU0 NPU1 NPU2 NPU3 NPU4 NPU5 NPU6 NPU7 NPU8 NPU9 NPU10 NPU11 NPU12 NPU13 NPU14 NPU15 CPU Affinity
339+NPU0 X HCCS HCCS HCCS HCCS HCCS HCCS HCCS PIX PHB PHB PHB SYS SYS SYS SYS 0-51,104-155
340+NPU1 HCCS X HCCS HCCS HCCS HCCS HCCS HCCS PHB PIX PHB PHB SYS SYS SYS SYS 0-51,104-155
341+NPU2 HCCS HCCS X HCCS HCCS HCCS HCCS HCCS PHB PHB PIX PHB SYS SYS SYS SYS 0-51,104-155
342+NPU3 HCCS HCCS HCCS X HCCS HCCS HCCS HCCS PHB PHB PHB PIX SYS SYS SYS SYS 0-51,104-155
343+NPU4 HCCS HCCS HCCS HCCS X HCCS HCCS HCCS SYS SYS SYS SYS PIX PHB PHB PHB 52-103,156-207
344+NPU5 HCCS HCCS HCCS HCCS HCCS X HCCS HCCS SYS SYS SYS SYS PHB PIX PHB PHB 52-103,156-207
345+NPU6 HCCS HCCS HCCS HCCS HCCS HCCS X HCCS SYS SYS SYS SYS PHB PHB PIX PHB 52-103,156-207
346+NPU7 HCCS HCCS HCCS HCCS HCCS HCCS HCCS X SYS SYS SYS SYS PHB PHB PHB PIX 52-103,156-207
347+NPU8 PIX PHB PHB PHB SYS SYS SYS SYS X HCCS HCCS HCCS HCCS HCCS HCCS HCCS 0-51,104-155
348+NPU9 PHB PIX PHB PHB SYS SYS SYS SYS HCCS X HCCS HCCS HCCS HCCS HCCS HCCS 0-51,104-155
349+NPU10 PHB PHB PIX PHB SYS SYS SYS SYS HCCS HCCS X HCCS HCCS HCCS HCCS HCCS 0-51,104-155
350+NPU11 PHB PHB PHB PIX SYS SYS SYS SYS HCCS HCCS HCCS X HCCS HCCS HCCS HCCS 0-51,104-155
351+NPU12 SYS SYS SYS SYS PIX PHB PHB PHB HCCS HCCS HCCS HCCS X HCCS HCCS HCCS 52-103,156-207
352+NPU13 SYS SYS SYS SYS PHB PIX PHB PHB HCCS HCCS HCCS HCCS HCCS X HCCS HCCS 52-103,156-207
353+NPU14 SYS SYS SYS SYS PHB PHB PIX PHB HCCS HCCS HCCS HCCS HCCS HCCS X HCCS 52-103,156-207
354+NPU15 SYS SYS SYS SYS PHB PHB PHB PIX HCCS HCCS HCCS HCCS HCCS HCCS HCCS X 52-103,156-207
355+```
356+ 
357+NPU-to-NPU拓扑关系解读:
358+ 
359+16张卡组成两个HCCS环,环间通过PCIe Switch互联。
360+ 
361+- NPU0~NPU7组成第一个HCCS环。NPU8~NPU15组成第二个HCCS环。
362+- NPU0和NPU8互为PIX,表示这两张卡插在同一个PCIe Switch下。NPU1和NPU9,。。。,NPU7和NPU15两两配对,都是通过PIX连接。
363+- NPU0和NPU9/10/11通过PHB互联,表示处于同一个NUMA节点下,但是走物理CPU的PCIe桥,性能比PIX慢。
364+- NPU0和NPU12/13/14/15通过SYS互联,表示处于不同的NUMA节点下,性能最差。
365+ 
366+CPU亲和性分析:
367+ 
368+这台服务器有2个超大的NUMA节点。
369+ 
370+NUMA 0(核心0-51,104-155):亲和NPU 0/1/2/3/8/9/10/11
371+ 
372+NUMA 1(核心52-103,156-207):亲和NPU 4/5/6/7/12/13/14/15
373+ 
374+针对这种拓扑关系,亲和调度应该分优先级:
375+ 
376+第一优先级:HCCS环内分配。如果申请小于等于8张卡,应该优先在同一个HCCS环内分配。如果小于等于4张卡,再考虑NUMA亲和,应该优先分配同一个NUMA节点的卡,例如NPU 0/1/2/3。
377+ 
378+第二优先级:跨HCCS环的对称分配。如果申请大于8张卡,应该优先保证环间通信走PIX通道,例如NPU0和NPU8。
379+ 
380+ 
381+ 
382+**示例4:Atlas 800T A3 超节点的拓扑关系示例如下**
383+ 
384+```
385+ Phy-ID0 Phy-ID1 Phy-ID2 Phy-ID3 Phy-ID4 Phy-ID5 Phy-ID6 Phy-ID7
386+Phy-ID0 X SIO HCCS_SW HCCS_SW HCCS_SW HCCS_SW HCCS_SW HCCS_SW
387+Phy-ID1 SIO X HCCS_SW HCCS_SW HCCS_SW HCCS_SW HCCS_SW HCCS_SW
388+Phy-ID2 HCCS_SW HCCS_SW X SIO HCCS_SW HCCS_SW HCCS_SW HCCS_SW
389+Phy-ID3 HCCS_SW HCCS_SW SIO X HCCS_SW HCCS_SW HCCS_SW HCCS_SW
390+Phy-ID4 HCCS_SW HCCS_SW HCCS_SW HCCS_SW X SIO HCCS_SW HCCS_SW
391+Phy-ID5 HCCS_SW HCCS_SW HCCS_SW HCCS_SW SIO X HCCS_SW HCCS_SW
392+Phy-ID6 HCCS_SW HCCS_SW HCCS_SW HCCS_SW HCCS_SW HCCS_SW X SIO
393+Phy-ID7 HCCS_SW HCCS_SW HCCS_SW HCCS_SW HCCS_SW HCCS_SW SIO X
394+Legend:
395+ X = Self
396+ SYS = Path traversing PCIe and NUMA nodes. Nodes are connected through SMP, such as QPI, UPI.
397+ PHB = Path traversing PCIe and the PCIe host bridge of a CPU.
398+ PIX = Path traversing a single PCIe switch
399+ PXB = Path traversing multipul PCIe switches
400+ HCCS = Connection traversing HCCS.
401+ SIO = Path traversing the SIO bus
402+ HCCS_SW = Connection traversing HCCS through a switch
403+ NA = Unknown relationship.
404+```
405+ 
406+拓扑关系解读:
407+ 
408+- 两个昇腾AI处理器之间通过SIO互联形成一个HiAM模组,例如NPU0和NPU1形成一个HiAM模组,NPU2和NPU3形成一个HiAM模组。
409+- HiAM模组之间通过HCCS互联,HCCS_SW表示通过HCCS经交换机连接的两个NPU之间的拓扑互联关系。
410+- 同一个NPU与所有CPU的亲和性相同,不体现NUMA亲和性关系。
411+ 
412+ 
413+### DRA驱动上报拓扑关系
414+ 
415+DRA驱动需将拓扑关系作为ResourceSlice的属性上报。针对NUMA节点、HCCS环、PIX、PXB、PHB、SYS不同的连接方式,定义对应的属性,呈现完整拓扑结构。
416+ 
417+- resource.kubernetes.io/pciBusID:Kubernetes社区定义的[DRA标准属性](https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/4381-dra-structured-parameters),表示设备的PCI总线地址,用于唯一设备分配。pciBusID可通过`npu-smi info`命令获取(Bus-Id)。
418+- resource.kubernetes.io/pcieRoot:Kubernetes社区定义的[DRA标准属性](https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/4381-dra-structured-parameters),表示设备的PCIe根复合体。一个NUMA节点下可以有多个PCIe Root。PIX连接即表示两个NPU卡处于相同的PCIe Root。通过约束具有相同的PCIe Root可以实现NPU和RDMA NIC之间的异构设备亲和调度,参考[issue213](https://github.com/kubernetes-sigs/dra-driver-nvidia-gpu/issues/213)。pcieRoot可通过`readlink -f /sys/bus/pci/devices/${pciBusID}`获取设备的物理绝对路径,再通过awk抓取含有`pciXXXX:XX`的根节点。
419+- numaNode:表示NPU卡所属的numa节点。如果没有,则不上报该属性。Kubernetes社区的[6072-dra-standard-numanode](https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/6072-dra-standard-numanode)提案计划将numaNode作为DRA标准属性,当前pr还处于open状态,因此,暂时还是使用厂商自定义的属性,待Kubernetes社区支持标准numaNode属性后,再进行迁移。获取方式:`cat /sys/bus/pci/devices/${pciBusID}/numa_node`
420+- topoHccsRingID:表示NPU卡所属的HCCS环。如果没有,则不上报该属性。获取方式:通过解析`npu-smi info -t topo`命令输出。
421+- topoSioID:表示NPU卡所属的SIO bus ID。如果没有,则不上报该属性。获取方式:通过解析`npu-smi info -t topo`命令输出。
422+- topoPixID:表示NPU卡所属的pcie-switch-pair-id。通过PIX连接的设备的pcieRoot相同,因此可以使用resource.kubernetes.io/pcieRoot字段替代。当前可不上报该属性。
423+- topoPxbID:表示NPU卡所属的pxb ID。典型昇腾服务器当前没有看到有PXB连接方式。因此,该字段当前也可以不上报。
424+- topoPhbID:表示NPU卡所属的phb ID。通过PHB连接的设备处于同一个NUMA节点,因此可以使用numaNode字段替代。当前可不上报该属性。
425+- sys:sys是最慢的连接方式,没有必要设置对应的属性。
426+ 
427+**说明**
428+ 
429+1. HCCS环拓扑关系需通过解析环境真实topo关系获得,不能根据服务器型号硬编码,同时要考虑不同服务器的拓扑差异。
430+2. 优先调用DCMI接口获取NPU相关信息,次选调用npu-smi命令获取。
431+ 
432+ 
433+示例:以上面的16卡服务器为例,各卡取值如下:
434+ 
435+| 属性 | NPU0 | NPU1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
436+| -------------- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |
437+| numaNode | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 |
438+| topoHccsRingID | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
439+| topoPixID | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
440+| topoPxbID | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - |
441+| topoPhbID | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 |
442+ 
443+ 
444+ 
445+ResourceSlice资源参考:
446+ 
447+```yaml
448+apiVersion: resource.k8s.io/v1
449+kind: ResourceSlice
450+metadata:
451+ creationTimestamp: "2026-02-27T01:55:37Z"
452+ generateName: master-npu.huawei.com
453+ generation: 1
454+ name: master-npu.huawei.com-9gv8l
455+ ownerReferences:
456+ - apiVersion: v1
457+ controller: true
458+ kind: Node
459+ name: master
460+ uid: 6ef76e72-da36-44e3-b9c3-93f44684a859
461+ resourceVersion: "2225369"
462+ uid: 0c1b399e-4fa8-4279-93f8-b92a1faeff6f
463+spec:
464+ devices:
465+ - attributes:
466+ chipName:
467+ string: 910B4
468+ physicalId: # NPU 0
469+ int: 0
470+ resource.kubernetes.io/pciBusID:
471+ string: '0000:81:00:0'
472+ resource.kubernetes.io/pcieRoot:
473+ string: 'pci0000:80'
474+ numaNode: # NPU卡所属numa节点
475+ int: 0
476+ topoHccsRingID: # NPU卡所属的HCCS环
477+ int: 0
478+ capacity:
479+ memCapacity:
480+ value: 32Gi
481+ name: npu-0
482+ - attributes:
483+ chipName:
484+ string: 910B4
485+ physicalId: # NPU 8
486+ int: 8
487+ resource.kubernetes.io/pciBusID:
488+ string: '0000:91:00:0'
489+ resource.kubernetes.io/pcieRoot:
490+ string: 'pci0000:80'
491+ numaNode: # NPU卡所属numa节点
492+ int: 0
493+ topoHccsRingID: # NPU卡所属的HCCS环
494+ int: 1
495+ capacity:
496+ memCapacity:
497+ value: 32Gi
498+ name: npu-8
499+ - attributes:
500+ chipName:
501+ string: 910B4
502+ physicalId: # NPU 11
503+ int: 11
504+ resource.kubernetes.io/pciBusID:
505+ string: '0000:95:00:0'
506+ resource.kubernetes.io/pcieRoot:
507+ string: 'pci0000:94'
508+ numaNode: # NPU卡所属numa节点
509+ int: 0
510+ topoHccsRingID: # NPU卡所属的HCCS环
511+ int: 1
512+ capacity:
513+ memCapacity:
514+ value: 32Gi
515+ name: npu-11
516+ - attributes:
517+ chipName:
518+ string: 910B4
519+ physicalId: # NPU 14
520+ int: 14
521+ resource.kubernetes.io/pciBusID:
522+ string: '0000:99:00:0'
523+ resource.kubernetes.io/pcieRoot:
524+ string: 'pci0000:98'
525+ numaNode: # NPU卡所属numa节点
526+ int: 1
527+ topoHccsRingID: # NPU卡所属的HCCS环
528+ int: 1
529+ capacity:
530+ memCapacity:
531+ value: 32Gi
532+ name: npu-14
533+... ... # 其它NPU不一一罗列
534+ driver: npu.huawei.com
535+ nodeName: master
536+ pool:
537+ generation: 1
538+ name: master
539+ resourceSliceCount: 1
540+```
541+ 
542+### 通过ResourceClaim实现亲和调度
543+ 
544+利用DRA的constraints约束能力,可以实现多卡亲和调度。
545+ 
546+例如,POD声明8张卡,要求8张卡处于同一个HCCS环内。配置参考如下:
547+ 
548+```yaml
549+apiVersion: resource.k8s.io/v1
550+kind: ResourceClaim
551+metadata:
552+ name: npu-topo-affinity-claim
553+ namespace: ascend-dra
554+spec:
555+ devices:
556+ requests:
557+ - name: npu
558+ exactly:
559+ deviceClassName: npu.huawei.com
560+ allocationMode: ExactCount
561+ count: 8
562+ selectors:
563+ - cel:
564+ expression: |-
565+ device.attributes["npu.huawei.com"].chipName == '910B4'
566+ constraints: # 约束8张卡都具有topoHccsRingID属性,并且属性值相同
567+ - requests: ["npu"]
568+ matchAttribute: "npu.huawei.com/topoHccsRingID"
569+
570+```
571+ 
572+POD声明4张卡,要求4张卡处于同一个HCCS环内,并且处于同一个NUMA节点。配置参考如下:
573+ 
574+```yaml
575+apiVersion: resource.k8s.io/v1
576+kind: ResourceClaim
577+metadata:
578+ name: npu-topo-affinity-claim
579+ namespace: ascend-dra
580+spec:
581+ devices:
582+ requests:
583+ - name: npu
584+ exactly:
585+ deviceClassName: npu.huawei.com
586+ allocationMode: ExactCount
587+ count: 4
588+ selectors:
589+ - cel:
590+ expression: |-
591+ device.attributes["npu.huawei.com"].chipName == '910B4'
592+ constraints:
593+ - requests: ["npu"]
594+ matchAttribute: "npu.huawei.com/topoHccsRingID"
595+ - requests: ["npu"]
596+ matchAttribute: "npu.huawei.com/numaNode"
597+
598+```
599+ 
600+利用DRA的优先级排序能力([KEP-4816](https://github.com/kubernetes/enhancements/tree/master/keps/sig-scheduling/4816-dra-prioritized-list)),可以实现POD声明2张卡,优先要求2张卡处于同一个HCCS环内,如果满足不了,则退而求其次,要求2张卡通过单个PCIe switch连接。
601+ 
602+```yaml
603+apiVersion: resource.k8s.io/v1
604+kind: ResourceClaim
605+metadata:
606+ name: npu-topo-affinity-claim
607+ namespace: ascend-dra
608+spec:
609+ devices:
610+ requests:
611+ - name: npu
612+ firstAvailable:
613+ - name: npu-same-hccs-ring
614+ deviceClassName: npu.huawei.com
615+ allocationMode: ExactCount
616+ count: 2
617+ selectors:
618+ - cel:
619+ expression: |-
620+ device.attributes["npu.huawei.com"].chipName == '910B4'
621+ - name: npu-same-pcieroot
622+ deviceClassName: npu.huawei.com
623+ allocationMode: ExactCount
624+ count: 2
625+ selectors:
626+ - cel:
627+ expression: |-
628+ device.attributes["npu.huawei.com"].chipName == '910B4'
629+ constraints:
630+ - requests: ["npu/npu-same-hccs-ring"]
631+ matchAttribute: "npu.huawei.com/topoHccsRingID"
632+ - requests: ["npu/npu-same-pcieroot"]
633+ matchAttribute: "resource.kubernetes.io/pcieRoot"
634+
635+```
636+ 
637+POD申领12张卡,要求每个HCCS环内分配6张,并且环间两两配对。
638+ 
639+```yaml
640+apiVersion: resource.k8s.io/v1
641+kind: ResourceClaim
642+metadata:
643+ name: npu-topo-affinity-claim
644+ namespace: ascend-dra
645+spec:
646+ devices:
647+ requests:
648+ - name: npu1
649+ exactly:
650+ deviceClassName: npu.huawei.com
651+ allocationMode: ExactCount
652+ count: 1
653+ selectors:
654+ - cel:
655+ expression: |-
656+ device.attributes["npu.huawei.com"].chipName == '910B4'
657+ - name: npu2
658+ exactly:
659+ deviceClassName: npu.huawei.com
660+ allocationMode: ExactCount
661+ count: 1
662+ selectors:
663+ - cel:
664+ expression: |-
665+ device.attributes["npu.huawei.com"].chipName == '910B4'
666+ # npu3 ~ npu11 不一一罗列
667+ - name: npu12
668+ exactly:
669+ deviceClassName: npu.huawei.com
670+ allocationMode: ExactCount
671+ count: 1
672+ selectors:
673+ - cel:
674+ expression: |-
675+ device.attributes["npu.huawei.com"].chipName == '910B4'
676+ constraints:
677+ - requests: ["npu1,npu2,npu3,npu4,npu5,npu6"]
678+ matchAttribute: "npu.huawei.com/topoHccsRingID"
679+ - requests: ["npu7,npu8,npu9,npu10,npu11,npu12"]
680+ matchAttribute: "npu.huawei.com/topoHccsRingID"
681+ - requests: ["npu1,npu7"]
682+ matchAttribute: "resource.kubernetes.io/pcieRoot"
683+ - requests: ["npu2,npu8"]
684+ matchAttribute: "resource.kubernetes.io/pcieRoot"
685+ ... # npu3,npu4,npu5,npu6,npu9,npu10,npu11,npu12类似一一配对
686+```
687+ 
688+业务可以针对各种服务器硬件预置典型场景的ResourceClaimTemplate,业务POD直接引用即可。
689+ 
690+说明:DRA driver组件不负责预置典型场景的ResourceClaimTemplate,仅提供examples,部署DRA driver也不会部署这些ResourceClaimTemplate。
691+ 
692+### 参考资料
693+#### 昇腾MindCluster节点内亲和调度参考
694+ 
695+昇腾MindCluster基于设备插件和volcano调度器扩展实现了[节点内的NPU亲和调度和跨节点的亲和调度](https://www.hiascend.com/document/detail/zh/mindcluster/2600/clustersched/dlug/docs/zh/scheduling/usage/basic_scheduling/01_affinity_scheduling/03_ascend_ai_processor_based_affinity.md)。
696+ 
697+针对每种硬件服务器,因为拓扑结构不同,所以提供了不同的拓扑亲和调度策略和算法。
698+ 
699+以“Atlas 200T A2 Box16 异构子框和Atlas 200I A2 Box16 异构子框”为例。
700+ 
701+| 优先级 | 策略名称 | 策略描述 |
702+| ------ | ---------------- | ------------------------------------------------------------ |
703+| 1 | HCCS互联分配原则 | 如果申请昇腾AI处理器的个数为1~8,则需要调度到同一个HCCS互联。如果申请昇腾AI处理器的个数为10、12、14,需要将所需的昇腾AI处理器平均分配到两个环,相对的物理地址也一致。 |
704+| 2 | 优先占满原则 | 优先分配已经分配过昇腾AI处理器的节点,减少碎片。以1、2、4、8为例,具体如下:<br/>如果申请1个昇腾AI处理器,优先申请HCCS互联可用昇腾AI处理器数量为1的节点,其次是可用数量为2个,3个,一直到8个。相同数量优先选择节点昇腾AI处理器总数量少的节点。<br/>如果申请2个昇腾AI处理器,优先申请HCCS互联可用昇腾AI处理器数量为2的节点,其次是可用数量为3个,4个,一直到8个。相同数量优先选择节点昇腾AI处理器总数量少的节点。<br/>如果申请4个昇腾AI处理器,优先申请HCCS互联可用昇腾AI处理器数量为4的节点,其次是可用数量为5个,6个,一直到8个。相同数量优先选择节点昇腾AI处理器总数量少的节点。<br/>如果申请8个昇腾AI处理器,只申请HCCS互联可用昇腾AI处理器数量为8的节点。相同数量优先选择节点昇腾AI处理器总数量少的节点。<br/>下发分布式任务时,任务存在未按照优先占满调度原则占满某个节点。说明如下:<br/>现象说明:如在两台Atlas 200T A2 Box16 异构子框或Atlas 200I A2 Box16 异构子框集群中,同时下发5卡、4卡、3卡任务,存在4卡和3卡任务调度到同一个节点,5卡任务调度到另一个节点的问题。<br/>原因分析:因为Volcano调度完一个任务后,Ascend Device Plugin上报调度后的昇腾AI处理器的拓扑结构到mindx-dl-deviceinfo-${node_name}存在时延,导致Volcano校验该节点昇腾AI处理器数量失败,将任务调度到其他节点上。 |
705+ 
706+资源申请约束:
707+ 
708+根据业务模型,对Atlas 200T A2 Box16 异构子框和Atlas 200I A2 Box16 异构子框训练任务资源申请作如下要求:
709+ 
710+- 训练任务申请的昇腾AI处理器数量不能大于节点昇腾AI处理器总数。
711+- 训练任务申请的昇腾AI处理器数量为1~8、10、12、14和16。
712+- 当训练任务申请的昇腾AI处理器数量不大于8个时,需要选取同一个HCCS互联内的昇腾AI处理器。
713+- 当训练任务申请的昇腾AI处理器数量为10、12、14时,需要将所需的昇腾AI处理器平均分配到两个环,相对的物理地址也一致。
714+- 当训练任务申请的昇腾AI处理器数量为16个时,需要将节点的昇腾AI处理器全部分配给该任务。
715+- 遵循Volcano开源部分的其他约束。
716+ 
717+**总结:**
718+ 
719+1. 拓扑亲和调度,优先调度到同一个HCCS环,其次调度到使用PCIe互联的NPU。
720+2. 申请的昇腾AI处理器数量只能为1~8、10、12、14和16。小于8个时,必须在同一个HCCS环内分配。超过8个时,将所需的昇腾AI处理器平均分配到两个环,相对的物理地址也一致。例如声明10个,则分配0,1,2,3,4,8,9,10,11,12。
721+3. 支持优先占满原则,依赖节点打分。DRA当前尚不支持节点打分能力(参考[issue4970](https://github.com/kubernetes/enhancements/issues/4970))
722+4. 拓扑关系根据NPU的logicID硬编码,非动态获取。
723+ 
724+其它硬件服务器不一一说明,请参考MindCluster文档。
725+ 
726+ 
727+#### DRA亲和调度业界参考
728+ 
729+[AWS Neuron Dynamic Resource Allocation (DRA) Beta](https://awsdocs-neuron.readthedocs-hosted.com/en/v2.27.0/containers/neuron-dra.html) AWS Neuron DRA亲和调度
730+ 
731+[Simplify AI infrastructure for AWS Trainium and Elastic Fabric Adapter with Kubernetes Dynamic Resource Allocation](https://aws.amazon.com/cn/blogs/containers/simplify-ai-infrastructure-for-aws-trainium-and-elastic-fabric-adapter-with-kubernetes-dynamic-resource-allocation/) 异构设备亲和调度
732+ 
733+[Optimizing RDMA performance for AI workloads on AKS with DRANET](https://blog.aks.azure.com/2026/04/01/dranet-rdma-optimization-for-ai-on-aks) GPU和RDMA亲和调度
734+ 
735+### 测试计划
736+<!--
737+**注意:**在该提案尚未被纳入某个正式版本前,此部分不是必需的。
738+其目标是确保我们不会接收缺乏充分测试的增强功能。
739+所有代码都应具备充分的测试(最终也应满足测试覆盖率要求)。在撰写测试计划时,请遵循 openFuyao 测试指南。
740+-->
741+ 
742+[ ] 我/我们理解,相关组件的所有者可能会要求更新已有的测试,以便在提交实现该增强功能所需的更改之前,使代码达到足够稳固的质量标准。
743+ 
744+##### 先决条件测试更新
745+<!--
746+根据评审者的反馈,描述在实施此项增强功能之前需要补充哪些额外的测试,以确保该增强特性也具备稳固的基础。
747+-->
748+ 
749+##### 单元测试
750+<!--
751+原则上,所有新增的代码都应具有完整的单元测试覆盖率,因此列出确切的测试项并不会带来额外价值。
752+但如果无法实现完整的单元测试覆盖,请说明原因,并解释为何在这种情况下这是可以接受的。
753+-->
754+ 
755+-
756+ 
757+单元测试覆盖:
758+- 拓扑信息采集和解析逻辑
759+- ResourceSlice属性上报逻辑
760+ 
761+##### 集成测试
762+<!--
763+集成测试允许控制用于启动被测二进制文件的配置参数。
764+这与不允许配置参数的 e2e 测试不同。
765+这样做可以测试非默认选项以及多个不同的、可能冲突的命令行选项。
766+ 
767+如果集成测试不是必要的或有用的,请解释原因。
768+-->
769+ 
770+- 测试名称:`dra-topology-integration`
771+ 
772+集成测试场景:
773+- DRA驱动正确上报拓扑属性到ResourceSlice
774+- ResourceClaim约束能够正确限制设备分配
775+- 不同拓扑约束组合的设备分配结果符合预期
776+ 
777+##### e2e 测试
778+<!--
779+当该功能计划纳入某个正式版本时,应填写此问题。
780+- 对于 Alpha 阶段,请描述将添加哪些测试,以确保该增强功能具备良好的质量保障。
781+- 对于 Beta 和 GA 阶段,需要说明测试已经编写、被定期执行,且结果稳定。
782+ 
783+可通过以下方式提供证明材料:
784+- 指向 gitcode 源代码的永久链接
785+- 指向定期测试作业的链接,并按测试名称过滤
786+- 在 openfuyao 缺陷追踪工具中进行搜索。
787+ 
788+作为进入 GA(正式可用)阶段的标准,我们期望过去一个月内不存在任何非基础设施相关的 flaky 测试(不稳定测试)。
789+如果你认为无需添加端到端测试(e2e),请解释其原因及合理性。
790+-->
791+ 
792+| 用例名称 | 前置条件 | 用例步骤 | 后置操作 | 预期结果 |
793+|---------|---------|---------|---------|---------|
794+| 单HCCS环8卡调度 | 集群有Atlas 200T A2 Box16节点 | 1.创建8卡ResourceClaim(同HCCS环约束)<br>2.创建Pod引用该ResourceClaim<br>3.检查分配的NPU设备 | 删除Pod和ResourceClaim | 分配的8张NPU位于同一个HCCS环 |
795+| NUMA亲和4卡调度 | 集群有Atlas 200T A2 Box16节点 | 1.创建4卡ResourceClaim(同HCCS环+同NUMA约束)<br>2.创建Pod引用该ResourceClaim<br>3.检查分配的NPU设备 | 删除Pod和ResourceClaim | 分配的4张NPU位于同一个HCCS环且同一个NUMA节点 |
796+| 跨环对称12卡调度 | 集群有Atlas 200T A2 Box16节点 | 1.创建12卡ResourceClaim(双环对称约束)<br>2.创建Pod引用该ResourceClaim<br>3.检查分配的NPU设备 | 删除Pod和ResourceClaim | 分配的12张NPU平均分配到两个HCCS环 |
797+| 优先级调度降级测试 | 集群有Atlas 200T A2 Box16节点,HCCS环已占用 | 1.创建优先级ResourceClaim<br>2.创建Pod引用该ResourceClaim<br>3.检查分配的NPU设备 | 删除Pod和ResourceClaim | 无法满足高优先级约束时,降级到低优先级约束成功分配 |
798+ 
799+- 测试名称:`dra-topology-affinity-e2e`
800+ 
801+### 毕业标准
802+<!--
803+> **注意:** *在功能尚未计划纳入某个正式版本时,本节无需填写。*
804+> 请在此处定义该功能的毕业(Graduation)里程碑。
805+> 毕业条件可以基于 API 成熟度、[Feature Gate] 的推进阶段,或其他方式来定义。此处应保持高层次,重点说明评估是否可以毕业时将参考哪些信号(信心指标)。
806+> 在制定毕业标准时,请参考以下内容:
807+> - [成熟度等级(`alpha`、`beta`、`stable`)]
808+> - [Feature Gate 生命周期][feature gate]
809+> - [弃用政策][deprecation-policy]
810+> 请明确说明"毕业"的定义。
811+> 通常我们倾向于无论功能通过何种方式访问,均采用相同的阶段划分(alpha、beta、GA)。
812+ 
813+#### 🔹 Alpha 阶段
814+- 功能已通过 Feature Gate 实现(默认关闭)
815+- 初步的端到端(e2e)测试已完成并启用
816+#### 🔸 Beta 阶段
817+- 收集开发者反馈及用户调研结果
818+- 完成核心功能 A、B、C
819+- 额外的测试已加入 Testgrid,并在 oFEP 中有链接说明
820+- 实现更严格的测试形式,例如降级测试和可扩展性测试
821+- 所有功能均已实现
822+- 所有安全相关机制均已完备
823+- 所有监控要求均已实现
824+- 所有测试要求均已满足
825+- 所有预发布阶段的问题与缺陷均已修复
826+ 
827+> **注意:** Beta 阶段的评估标准必须包含所有功能、安全性、监控与测试的要求,并解决所有已知问题或差距。
828+ 
829+#### 🟢 GA 阶段
830+- 有 N 个真实生产环境中的使用示例
831+- 有 N 次实际安装部署记录
832+- 已留出反馈窗口期,收集充分用户反馈
833+- 所有在 Beta 阶段反馈的问题与缺陷都已解决
834+ 
835+> **注意:** GA 阶段的毕业标准不得再包含功能、安全性、监控或测试方面的要求,这些应在 Beta 阶段全部完成。
836+> **注意:** 通常,我们在 Beta 和 GA 之间至少间隔两个版本周期,以便留出时间获取用户反馈和发现潜在问题,避免在连续发布中遗漏反馈环节。
837+> **对于非可选(默认启用)功能在进入 GA 阶段时,毕业标准必须包含 [一致性测试(Conformance tests)]。**
838+ 
839+#### 🧯 弃用(Deprecation)
840+- 宣布弃用现有功能标志(flag)并说明支持策略
841+- 自引入替代功能以来,已过去两个版本(以解决版本偏差问题)
842+- 处理来自 gitcode Issues 等反馈渠道中的用法变更或行为差异问题
843+- 正式弃用原有标志 (flag)
844+-->
845+ 
846+#### Alpha阶段
847+- DRA驱动支持上报拓扑关系属性(pciBusID, pcieRoot, numaNode, topoHccsRingID)
848+- 支持通过ResourceClaim约束实现同HCCS环调度
849+- 初步e2e测试覆盖基础调度场景
850+ 
851+#### Beta阶段
852+- 完整测试覆盖各种拓扑约束组合
853+- 收集用户反馈和性能数据
854+ 
855+#### GA阶段
856+- 至少1个生产环境使用案例
857+- 监控和诊断工具完备
858+- 文档和最佳实践完善
859+ 
860+### 升级/降级策略
861+<!--
862+> 指导提案人在功能设计时兼顾向前兼容性、配置迁移、Feature Gate 管理等问题。
863+-->
864+<!--
865+如果适用,该组件在升级和降级时将如何处理?请确保在测试计划中包含这部分内容。
866+ 
867+在制定该增强功能的升级/降级策略时,请考虑以下问题:
868+- 为了保持现有行为不变,集群在升级时是否需要进行调用方式、配置或 API 使用上的任何更改?
869+- 为了使用该增强功能,集群在升级时是否需要对调用方式、配置或 API 使用做出调整?
870+-->
871+ 
872+**升级策略:**
873+- 新增的拓扑属性字段对现有ResourceClaim无影响
874+- 已有的ResourceClaim在不使用拓扑约束时行为不变
875+- 建议升级后逐步为业务Pod添加拓扑约束以优化性能
876+ 
877+**降级策略:**
878+- 使用拓扑约束的ResourceClaim在调度时会失败
879+- 建议在降级前移除所有拓扑约束
880+ 
881+### 版本倾斜策略
882+<!--
883+确保你的提案在 openfuyao 集群中升级时能够兼容不同版本组件之间的运行差异。
884+-->
885+<!--
886+如果适用,该组件在面对与其他组件的版本不一致(version skew)时将如何处理?有哪些兼容性保证?请确保在测试计划中包括这一部分。
887+ 
888+在为此增强功能制定版本偏差应对策略时,请考虑以下问题:
889+- 该功能是否涉及控制面(Control Plane)与节点(Node)之间的协同行为?
890+- 当使用该功能时,版本落后三个版本(n-3)的 kubelet 或 kube-proxy 会如何表现?
891+- 当使用该功能时,版本落后一个版本(n-1)的 kube-controller-manager 或 kube-scheduler 会有何行为?
892+- 节点上的其他组件是否会发生变更? 例如,CSI(容器存储接口)、CRI(容器运行时接口)或 CNI(容器网络接口)是否需要在 kubelet 之前被更新?
893+-->
894+ 
895+**版本偏差处理:**
896+- DRA驱动需要与kube-scheduler版本匹配才能使用拓扑约束
897+- 当kube-scheduler版本落后时,不支持拓扑约束的ResourceClaim会调度失败
898+- 建议先升级kube-scheduler,再升级DRA驱动
899+ 
900+## 生产可用性审查
901+<!--
902+**生产可用性审查(Production Readiness Review,PRR)** 的目的是确保即将合并到 openfuyao 中的功能:
903+- 可观测(observable)、可扩展(scalable)、可支持(supportable);
904+- 能在生产环境中安全运行;
905+- 在出现故障时能够被禁用或回滚。
906+ 
907+**要使 oFEP 进入 `implementable` 状态并被纳入发布版本,必须完成并通过生产可用性审查问卷(PRR Questionnaire)。**
908+ 
909+在某些情况下,元数据中也应包含这些问题的答案:
910+- 这样可以便于自动化工具验证是否进行了审查;
911+- 同时有助于减少评审负担并降低审查延迟。
912+-->
913+ 
914+### 功能启用和回滚
915+<!--
916+当针对 alpha 版本发布时,必须完成此部分。
917+-->
918+ 
919+###### 如何在实时集群中启用/禁用此功能?
920+<!--
921+选择其中一个并删除其余的。
922+-->
923+ 
924+- [x] **功能开关(Feature gate)**(请同时在元数据中填写相应字段)
925+ - 功能开关名称:
926+ - 依赖该功能开关的组件:
927+ 
928+###### 启用该功能会改变任何默认行为吗?
929+<!--
930+任何默认行为的变更都可能让用户感到意外,或破坏现有的自动化流程,因此在这方面必须格外小心。
931+-->
932+ 
933+启用该功能不会改变默认行为。只有当ResourceClaim明确声明拓扑约束时才会触发拓扑感知调度。
934+ 
935+###### 该功能一旦启用,是否可以禁用(即我们可以回滚启用)?
936+<!--
937+**请描述该功能对现有工作负载可能造成的影响**(例如,如果这是一个运行时特性,它是否可能破坏现有应用程序的行为?)。
938+ 
939+通常,通过将功能开关(Feature Gate)设置为 `false` 并重启相应组件,即可禁用该功能。除这个操作之外,不应再需要其他变更来完成禁用。
940+ 
941+**注意:**在元数据中,也请将 `disable-supported` 字段设置为 `true``false`
942+-->
943+ 
944+###### 如果该功能之前已回滚,现在我们重新启用它会发生什么情况?
945+ 
946+重新启用后,DRA驱动重新上报拓扑属性,调度器可以处理拓扑约束。
947+ 
948+###### 是否有任何针对功能启用/禁用的测试?
949+<!--
950+当前的端到端测试框架(e2e framework)**尚不支持启用或禁用 Feature Gate**
951+然而,对于处理数据的每个组件,必须编写包含**启用和未启用该功能场景的单元测试**
952+ 
953+如果该功能修改了 API 类型,**至少应该考虑添加转换测试(conversion tests)**
954+ 
955+此外,如果该功能引入了新的 API 字段,**还必须编写测试 Feature Gate 开关行为的单元测试**——也就是验证以下情形:
956+- "当我先启用 Feature Gate 并写入了包含新字段的对象后,随后将其禁用,会发生什么?"
957+-->
958+ 
959+### 推出、升级和回滚规划
960+<!--
961+当该功能计划从 Beta 阶段发布至正式版本时,必须填写本节内容。
962+-->
963+ 
964+###### 部署或回滚为何会失败?这会影响正在运行的工作负载吗?
965+<!--
966+**尽可能保持警觉和审慎**——例如,假设在发布过程中某些组件会中途重启,会发生什么?
967+ 
968+请务必考虑以下场景:
969+- **高可用(HA)集群**:在该场景下,功能开关(Feature Flag)可能仅在部分 API Server 上启用,而其他仍为禁用状态;
970+- **大型集群**:在这种情况下,功能的启用/禁用可能会分批分节点地推进,需考虑该过程中的一致性与兼容性问题。
971+-->
972+ 
973+部署失败场景:
974+- DRA驱动启动失败:ResourceSlice不会更新,调度器使用缓存的旧数据,工作负载不受影响
975+- kube-scheduler配置错误:调度器无法启动,需要修复配置后重启
976+ 
977+回滚失败场景:
978+- 回滚时存在使用拓扑约束的工作负载:新Pod调度失败,需要先移除约束
979+ 
980+###### 哪些具体指标应该通知回滚?
981+<!--
982+当该功能还处于早期阶段时,用户应关注哪些信号,以便及早发现可能存在的严重问题?
983+-->
984+ 
985+回滚指标:
986+- DRA驱动启动失败率
987+- ResourceSlice更新失败率
988+- 使用拓扑约束的ResourceClaim调度失败率
989+- 设备分配耗时显著增加
990+ 
991+###### 升级和回滚测试了吗?升级->降级->升级的路径测试了吗?
992+<!--
993+请描述已完成的手动测试及其结果。
994+从长远来看,我们可能会要求实施自动化的升级/回滚测试,但目前我们仍缺少相关的机制和工具,因此暂时无法实现。
995+-->
996+ 
997+手动测试计划:
998+- 升级测试:禁用->启用->验证拓扑调度功能
999+- 回滚测试:启用->禁用->验证已运行工作负载正常
1000+- 路径测试:禁用->启用->禁用->启用
1001+ 
1002+###### 推出时是否伴随任何功能、API、API 类型的字段、标志等的弃用和/或删除?
1003+<!--
1004+即使应用弃用政策,仍可能会让一些用户感到惊讶。
1005+-->
1006+ 
1007+无弃用或删除。
1008+ 
1009+### 监控要求
1010+<!--
1011+当计划将功能从 Beta 阶段纳入某个正式版本(release)时,必须完成此部分内容。
1012+对于 GA(正式可用)阶段,该部分也是必须填写的:审批人应能够基于实际生产环境中的经验,确认之前各项回答的准确性。
1013+-->
1014+ 
1015+###### 操作员如何确定该功能是否正在被工作负载使用?
1016+<!--
1017+理想情况下,应使用指标(metric)来实现。
1018+通过对 Kubernetes API 的操作(例如检查是否存在设置了字段 X 的对象)应作为最后手段。
1019+请避免将日志或事件用于此目的。
1020+-->
1021+ 
1022+监控指标:
1023+- 使用拓扑约束的ResourceClaim数量
1024+- 各种拓扑约束类型的分布(同HCCS环、同NUMA等)
1025+- 拓扑约束调度成功率和失败率
1026+ 
1027+###### 使用此功能的人如何知道它适用于他们的实例?
1028+<!--
1029+例如,如果这是一个与 Pod 相关的功能,则应能够针对每个 Pod 确定该功能是否正常工作。
1030+请从以下选项中选择一项并删除其余内容。
1031+请详细描述所有对最终用户可见的内容,确保他们能够验证该功能是否已正确启用并正常运行。
1032+> 请注意:最终用户通常无法查看组件日志或访问系统指标(metrics)。
1033+-->
1034+ 
1035+- [x] 其他(作为最后手段)
1036+ - 细节:用户可以通过Pod的resource claim状态查看分配的设备拓扑信息,或通过`kubectl get resourceslice -o yaml`查看节点上报的拓扑属性
1037+ 
1038+###### 增强的合理 SLO(服务级别目标)是什么?
1039+<!--
1040+这是你定义该功能"正常服务质量"(Quality of Service,QoS)表现的机会。
1041+我们无法提供全面的指导,但从高层角度来看(还需要更精确定义),这些表现可能包括:
1042+- 每天返回 5XX 错误的 API 调用比例 ≤ 1%
1043+- CronJob 的任务实际创建时间与预期创建时间之差的绝对值在一天内的 99 百分位 ≤ 10%
1044+- 每天 99.9% 的 `/health` 请求返回 HTTP 200 状态码
1045+ 
1046+这些目标将有助于你在下一个问题中确定需要衡量的服务指标(SLIs)。
1047+-->
1048+ 
1049+拓扑约束调度延迟不超过普通调度的2倍。
1050+ 
1051+拓扑约束调度成功率不低于95%(受资源碎片影响)。
1052+ 
1053+###### 运维人员可以使用哪些服务级别指标(SLIs)来判断服务的健康状况?
1054+<!--
1055+请选择以下选项中的一个,并删除其余内容。
1056+-->
1057+ 
1058+- [x] 指标
1059+ - 指标名称:
1060+ - [可选] 聚合方法:平均值、计数
1061+ - 暴露指标的组件:
1062+ 
1063+###### 是否存在任何尚未覆盖的指标(metrics),可以用来进一步提升该功能的可观测性?
1064+<!--
1065+请描述这些指标本身,以及未添加它们的原因(例如:成本高、实现复杂等)。
1066+-->
1067+ 
1068+### 依赖项
1069+<!--
1070+当计划将该功能从 Beta 阶段纳入某个正式版本(release)时,必须完成本节内容。
1071+-->
1072+ 
1073+###### 此功能是否依赖于集群中运行的任何特定服务?
1074+<!--
1075+请同时考虑集群级别的服务(例如 metrics-server)以及节点级别的代理(例如某个特定版本的 CRI)。
1076+重点关注该功能所依赖的 **外部或可选服务**
1077+例如,如果该功能依赖云服务商的 API、或外部的软件定义存储(SDS)或网络控制面板等服务,则应明确列出。
1078+ 
1079+对于每一项依赖项,请填写以下内容:
1080+- 当前用户工作负载的运行情况
1081+- 新建工作负载的创建情况
1082+- 集群级别的服务(例如 DNS)
1083+ 
1084+填写格式如下:
1085+```
1086+- [依赖项名称]
1087+ - 使用说明:
1088+ - 若该服务发生中断,对该功能的影响:
1089+ - 若该服务性能下降或错误率升高,对该功能的影响:
1090+```
1091+-->
1092+ 
1093+- [kube-scheduler]
1094+ - 使用说明:调度器需要支持DRA和拓扑约束处理
1095+ - 若该服务发生中断,对该功能的影响:新Pod无法调度,已运行Pod不受影响
1096+ - 若该服务性能下降或错误率升高,对该功能的影响:调度延迟增加
1097+ 
1098+- [DRA驱动(npu.huawei.com)]
1099+ - 使用说明:驱动需要上报拓扑属性
1100+ - 若该服务发生中断,对该功能的影响:ResourceSlice不更新,调度器使用缓存数据
1101+ - 若该服务性能下降或错误率升高,对该功能的影响:拓扑信息可能不准确
1102+ 
1103+### 可扩展性
1104+<!--
1105+对于 Alpha 阶段,鼓励填写本节内容:评审人员应考虑这些问题,并尝试给出回答。
1106+对于 Beta 阶段,本节为必填项:评审人员必须回答这些问题。
1107+对于 GA(正式发布)阶段,本节同样为必填项:审批人员应能根据实际生产经验,确认之前给出的所有回答。
1108+-->
1109+ 
1110+###### 启用/使用此功能会导致任何新的 API 调用吗?
1111+<!--
1112+**请描述相关 API 调用,包括以下信息:**
1113+- **API 调用类型**(例如:`PATCH pods`
1114+- **预估调用频率(吞吐量)**
1115+- **调用发起组件**(例如:`Kubelet``Feature-X-controller`
1116+ 
1117+重点关注以下场景:
1118+- **组件开始列出(list)或监听(watch)以前未处理的资源**
1119+- **某些 Kubernetes 资源发生变化后,触发新的 API 请求行为**
1120+ 例如:更新对象 X 后又触发了对对象 Y 的修改或创建
1121+- **用于状态对齐(state reconciliation)的定期 API 请求**
1122+ 例如:周期性获取资源状态、心跳上报、领导者选举等
1123+-->
1124+ 
1125+无新增API调用。拓扑信息作为ResourceSlice的属性字段上报,不增加额外的API请求。
1126+ 
1127+###### 启用/使用此功能是否会导致引入新的 API 类型?
1128+<!--
1129+请描述它们(指代 API 对象或资源),并提供以下信息:
1130+- **API 类型(API type)**
1131+- **每个集群支持的最大对象数量**
1132+- **每个命名空间支持的最大对象数量**(仅适用于具备命名空间作用域的对象)
1133+-->
1134+ 
1135+无新增API类型。使用现有的ResourceSlice和ResourceClaim API。
1136+ 
1137+###### 启用/使用此功能是否会导致对云提供商的任何新的 API 调用?
1138+<!--
1139+请进行如下描述:
1140+- **涉及哪些 API:**
1141+- **预估调用增加量:**
1142+-->
1143+ 
1144+不涉及云提供商API调用。
1145+ 
1146+###### 启用/使用此功能是否会导致现有 API 对象的大小或数量增加?
1147+<!--
1148+**请描述新增或受影响的资源对象,提供以下信息:**
1149+- **API 类型(API type(s)):**
1150+- **预估对象体积增加量:**(例如:新增注解字段,大小为 32 字节)
1151+- **预估新增对象数量:**(例如:为每个现有 Pod 创建一个新的对象 X)
1152+-->
1153+ 
1154+- API类型:ResourceSlice
1155+- 预估对象体积增加量:每个设备增加约100字节的拓扑属性字段
1156+- 预估新增对象数量:无新增对象
1157+ 
1158+###### 启用/使用此功能是否会导致现有 SLI/SLO 所涵盖操作的耗时增加?
1159+<!--
1160+请思考是否会新增额外操作或在现有流程中引入新的中间步骤(例如:为了启动一个容器,现在需要先执行步骤 X 等)。
1161+请在下方详细描述这些新增内容。
1162+-->
1163+ 
1164+Pod调度耗时可能因拓扑约束验证而略有增加,预计影响小于10%。
1165+ 
1166+###### 启用/使用此功能是否会导致任何组件的资源使用率(CPU、RAM、磁盘、IO 等)不可忽略的增加?
1167+<!--
1168+需要注意的事项包括:
1169+- 增加的内存状态(in-memory state);
1170+- 新引入的耗时计算操作;
1171+- 频繁的磁盘访问(包括日志量增加);
1172+- 大量发送或接收的网络数据流量等。
1173+ 
1174+请从小型和大型集群的不同规模角度,**全面评估这些资源消耗**,并结合 Kubernetes 的[支持上限(supported limits)](https://git.k8s.io/community/sig-scalability/configs-and-limits/thresholds.md)进行考量。
1175+-->
1176+ 
1177+- 内存:kube-scheduler需要缓存拓扑信息,每个设备约增加100字节,影响很小
1178+- CPU:拓扑约束验证的计算开销很小,不影响整体性能
1179+- 磁盘/IO:无额外磁盘访问
1180+ 
1181+###### 启用/使用此功能是否会导致某些节点资源(PID、套接字、inode 等)耗尽?
1182+<!--
1183+**请不要只关注理想情况,更重要的是评估异常或极端情况**,例如:
1184+- 探针响应时间从毫秒级变成分钟级;
1185+- 异常或失败的 Pod 持续占用资源等。
1186+ 
1187+**如果该功能可能会导致某些资源被耗尽**,请说明:
1188+- 如何通过 Kubernetes 已有的资源限制机制进行缓解(例如每节点最大 Pod 数);
1189+- 或该 oFEP 是否引入了新的限制来控制这些风险。
1190+ 
1191+此外,还请说明:
1192+- **是否已经进行了性能相关测试(或计划进行),用于更好地理解性能特征,并验证所声明的资源使用上限?**
1193+-->
1194+ 
1195+不会导致节点资源耗尽。拓扑信息存储在etcd和调度器内存中,不占用节点资源。
1196+ 
1197+### 故障排除
1198+<!--
1199+**当该功能计划从 Beta 阶段发布至正式版本(release)时,本节必须填写。**
1200+ 
1201+对于 **GA(正式发布)阶段**,本节同样为必填项:审批人员应能够根据实际生产环境中的经验,确认之前的各项回答。
1202+ 
1203+当前的 **"排障(Troubleshooting)" 部分**,在功能发布流程中相当于临时承担了 **"运维手册(Playbook)"** 的角色。
1204+未来可能会将其拆分为一个专门的 `Playbook` 文档(可能还会包含一些监控信息)。但目前仍将其保留在此处。
1205+-->
1206+ 
1207+###### 如果 API 服务器和/或 etcd 不可用,此功能如何反应?
1208+ 
1209+如果API服务器/etcd不可用:
1210+- DRA驱动无法更新ResourceSlice,使用缓存数据
1211+- 调度器无法处理新的调度请求,已运行的工作负载不受影响
1212+ 
1213+###### 其他已知故障模式有哪些?
1214+<!--
1215+**对于每种故障模式,请使用以下模板逐项填写信息:**
1216+- **[故障模式简要描述]**
1217+ - **检测方式(Detection):**
1218+ 如何通过指标(metrics)检测该问题?换句话说:
1219+ 操作人员**如何在不登录 master 或 worker 节点的情况下排障**?
1220+ - **缓解手段(Mitigations):**
1221+ 尤其对于已在运行的用户工作负载,可采取哪些措施止血/减缓影响?
1222+ - **诊断信息(Diagnostics):**
1223+ 有哪些有用的日志消息?其对应的**日志级别**(logging level)是多少?
1224+ ✅ *注:日志诊断信息在功能进入 Beta 阶段前可不填写。*
1225+ - **测试情况(Testing):**
1226+ 针对该故障是否有测试用例?若无,请说明原因。
1227+-->
1228+ 
1229+###### 如果未满足 SLO,应采取哪些步骤来确定问题?
1230+ 
1231+## 实施历史
1232+<!--
1233+**在本节中应记录一个 oFEP 生命周期中的主要里程碑。**
1234+ 
1235+可能包括但不限于以下内容:
1236+- `摘要``动机` 部分被合并,表示 SIG 已接受该提案
1237+- `提案` 部分被合并,表示对设计方案达成一致
1238+- 实现工作的启动日期
1239+- 首个包含该 oFEP 初始版本的 openfuyao 发布版本
1240+- 该 oFEP 成功毕业为正式可用(GA)的 openfuyao 版本
1241+- oFEP 被废弃或被其他提案取代的时间
1242+-->
1243+ 
1244+- 2025-07-20:oFEP创建,摘要和动机部分完成
1245+ 
1246+## 缺点
1247+<!--
1248+为什么不实施这个 oFEP?从反面角度分析该提案可能带来的负面影响、权衡成本、潜在风险或争议点。
1249+-->
1250+ 
1251+1. **资源碎片化风险**:严格的拓扑约束可能导致资源碎片化,降低整体资源利用率。
1252+ 
1253+2. **运维复杂度增加**:需要用户了解硬件拓扑结构和约束配置,增加了使用门槛。
1254+ 
1255+3. **硬件依赖性强**:不同服务器型号的拓扑结构不同,需要预置不同的模板,维护成本高。
1256+ 
1257+4. **调度延迟增加**:拓扑约束验证会增加调度延迟,虽然影响较小但仍存在。
1258+ 
1259+## 替代方案
1260+<!--
1261+**你还考虑过哪些其他方案?为什么将它们排除?**
1262+这些备选方案不需要像最终提案那样详尽,但应提供足够的信息来阐述其基本思路,并说明为什么它们不可接受。
1263+-->
1264+ 
1265+**替代方案1:使用节点标签和节点亲和性**
1266+ 
1267+在节点上打标签标记拓扑信息,使用节点亲和性调度。
1268+ 
1269+缺点:
1270+- 无法实现细粒度的设备级拓扑约束
1271+- 节点标签信息有限,难以表达复杂的拓扑关系
1272+- 与DRA机制不兼容
1273+ 
1274+**替代方案2:使用调度器扩展**
1275+ 
1276+实现自定义调度器扩展,在调度时查询拓扑信息并决策。
1277+ 
1278+缺点:
1279+- 需要额外的调度器扩展开发和维护
1280+- 无法利用DRA的原生约束机制
1281+- 与Kubernetes生态集成度低
1282+ 
1283+**替代方案3:使用设备管理工具(如MindCluster)**
1284+ 
1285+使用专业的设备管理工具实现拓扑调度。
1286+ 
1287+缺点:
1288+- 引入额外依赖,增加系统复杂度
1289+- 与Kubernetes原生调度不集成
1290+- 不符合云原生理念
1291+ 
1292+## 所需基础设施(可选)
1293+<!--
1294+**如果你需要从项目或 SIG 获得资源支持,请在本节中列出。** 例如:
1295+- 请求创建新的子项目(subproject)
1296+- 新建 gitcode 仓库(repos)
1297+- 配置 gitcode 相关权限或细节(如 team 成员或 CI 权限等)
1298+ 
1299+提前在这里列出这些需求,有助于 SIG 尽早启动相关流程,加快资源配置效率。
1300+-->