编写 VPA 增强提案(AEP):基于 Kubernetes Autoscaler 仓库的完整模板与实践指南
【免费下载链接】autoscalerAutoscaling components for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/au/autoscaler
导读
本文围绕autoscaler仓库中 Vertical Pod Autoscaler(VPA)子项目官方提供的 AEP(Autoscaler Enhancement Proposal,自动扩缩容增强提案)模板展开,系统讲解 AEP 的设计初衷、目录结构、完整章节骨架与每一节的填写要点,并结合仓库内已合并的真实 AEP 实例(如 AEP-7862 CPU Startup Boost、AEP-4016 原地更新、AEP-8818 免驱逐原地更新)说明模板各字段在实际提案中是如何落地的。读完本文,你将掌握 AEP 的标准写作流程、章节组织规范、评审关注点,以及如何参照模板提交一份可被 VPA 维护者有效评审的新功能提案。
AEP 是什么:VPA 子项目轻量级的 KEP
AEP(Autoscaler Enhancement Proposal)是 Kubernetes 官方 KEP(Kubernetes Enhancement Proposal)在 VPA 子项目范围内的一种轻量化变体。模板文档在开头的注释块中明确说明:
AEPs are a lightweight version of Kubernetes KEPs, scoped to the Vertical Pod Autoscaler subproject.
与完整的 KEP 相比,AEP 去掉了很多面向 Kubernetes 全项目所需的流程性内容(如跨 SIG 协调、发布节奏绑定等),聚焦在 VPA 自身的 API 设计、组件行为与测试策略上,让评审者看到一致的结构,从而降低新提案的阅读与评审成本。vertical-pod-autoscaler/enhancements/目录下现存的提案(如 AEP-7862、AEP-4016、AEP-4566 MinReplicas、AEP-8905 原生 Sidecar 支持)均以该模板为骨架撰写,是理解 AEP 规范的最佳样本。
模板位于仓库 vertical-pod-autoscaler/enhancements/NNNN-aep-template/README.md,由 enhancements/README.md 显式引用作为新提案的起点。该目录的 OWNERS 文件显示,审批权限仅授予sig-autoscaling-leads,评审由sig-autoscaling-vpa-reviewers负责,即 AEP 的合并需要 VPA 子项目负责人与评审人把关。
AEP 与一个“特性”的生命周期绑定
模板强调一条重要原则:
One AEP corresponds to one "feature" or "enhancement" for its whole lifecycle. If major changes emerge after implementation, edit the AEP rather than opening a new one.
即一个 AEP 对应一个特性从提案到落地的整个生命周期。实现过程中若出现大的设计变化,应当直接编辑原 AEP而不是另开新文档。真实案例可以佐证这一点:AEP-7862 的 Implementation History 记录了从 2025-03-20 初版到 2026-08-11 的多次重大设计迭代(API 字段改名、解除与 InPlaceOrRecreate 模式的耦合、将同步扫描改为事件驱动工作队列等),全部沉淀在同一个 AEP 文档中,保留了完整的设计演进脉络。
开始前的准备流程(Getting Started)
模板注释给出了使用 AEP 的四个前置步骤,这是在写任何章节之前必须完成的工作:
- 建立跟踪 issue:在
kubernetes/autoscaler仓库打开一个描述问题的跟踪 issue,issue 编号将直接成为 AEP 目录名的前缀。 - 复制模板目录:将
NNNN-aep-template目录复制为NNNN-short-descriptive-title,其中NNNN即 issue 编号,short-descriptive-title是简短描述性标题。 - 先填 Summary 与 Motivation:这两节足以启动设计讨论,不需要等设计完全定型。
- 提交 PR 并迭代:以“每个主题尽量小的 PR”为目标持续迭代;合并 AEP 不代表提案已被批准或完成。
对照实际仓库可以发现,现存的 AEP 目录正是按该命名规范组织的:4016-in-place-updates-support、4566-min-replicas、7862-cpu-startup-boost、8818-in-place-only、8905-native-sidecar-support等,目录名前缀均为对应的 issue 编号。
模板整体骨架:一节对应一个评审关注点
AEP 模板的正文是一个固定骨架,共 8 个一级章节:
- Summary
- Motivation(含 Goals、Non-Goals)
- Proposal
- Design Details(含 API Changes、Test Plan、Feature Enablement and Rollback、Graduation Criteria、Version Skew、Kubernetes Version Compatibility)
- Implementation History
- Alternatives
这个骨架并非随意编排,而是遵循 KEP 的经典逻辑链:为什么做(Motivation)→ 做什么(Proposal)→ 怎么做(Design Details)→ 怎么验证(Test Plan)→ 如何演进(Graduation/Version)→ 历史与备选(History/Alternatives)。下面按模板顺序逐节拆解填写要点,并给出真实 AEP 的写法对照。
Summary:一段话让不熟悉 VPA 的人看懂
模板要求用一两段话讲清楚“这个 AEP 是关于什么的、为什么重要”,并保证一个不熟悉 VPA 内部实现的人也能读懂提案的全貌。它通常要交代:问题背景、提案的核心思路、带来的用户可见变化。
以 AEP-7862 的 Summary 为例:它先描述“Java 等传统工作负载容器启动慢”这一普遍痛点,指出“启动期多给 CPU 但启动后不复原会造成浪费”的矛盾,然后一句话给出方案——利用 Kubernetes 的 in-place pod resize 能力,在 Pod 启动期间提升 CPU request/limit,并在 Pod 变为Ready或经过指定时长后把 CPU 缩回。这就是 Summary 的典型写法:问题 → 思路 → 机制,三段式讲清全貌。
Motivation:证明问题真实存在
Motivation 的职责是解释“为什么值得做这个改动”,模板要求链接 issue、用户报告或过往讨论来证明问题真实存在,并强调:
Reviewers will weigh the cost of the change against the motivation described here, so be concrete.
评审者会用动机的分量去权衡改动的成本,因此必须具体、可验证,而不是泛泛而谈。
Goals:可测试的目标
Goals 用项目符号列出本 AEP 想达成的目标,模板特别要求每个目标都应当可测试:
Keep each goal testable — something a reviewer could point at later to decide whether the AEP succeeded.
AEP-7862 的 Goals 就是可验证表述的范例——“允许 VPA 在 Pod(重新)创建期间提升容器的 CPU request 与 limit”“允许 VPA 在 PodReady且StartupBoost.CPU.DurationSeconds到期后按 VPA 建议(或 Pod spec 中配置的 CPU 值)原地缩回 CPU”。每个目标都对应一个可在测试中观察的行为。
Non-Goals:明确边界,防止范围蔓延
模板对 Non-Goals 的评价甚至高于 Goals:
Listing non-goals is often more valuable than listing goals — it keeps the discussion focused and prevents scope creep during review.
列出“明确不做的事”往往比列目标更有价值,它让讨论保持聚焦,防止评审期间范围蔓延。典型写法见 AEP-7862:“不支持在 Pod 创建时间之外提升 CPU”“不支持提升内存资源(因为 in-place resize 特性目前不支持内存 limit 下调)”。后者还附带了明确的上下游依据,说明拒绝该能力的技术原因,这种“给出理由的 Non-Goal”最有说服力。
Proposal:写“什么”,不写“怎么做”
Proposal 是在高层描述提议的变更,模板明确区分:
This is the "what", not the "how" — implementation details belong in Design Details below.
评审者应只读这一节就能理解用户可见行为,而不需要读任何代码。因此 Proposal 通常写成对 API 或行为的简要清单,例如 AEP-7862 的 Proposal 仅三条:给VerticalPodAutoscalerSpec增加StartupBoost字段;给ContainerResourcePolicy增加StartupBoost字段;允许在 VPA 对象中存在StartupBoost配置时仅启用启动提升而无需同时使用传统 VPA 功能。每条都描述“新增什么、用户能配置什么”,不涉及内部实现。
Design Details:设计落地细节
Design Details 是 AEP 最核心、篇幅最大的部分,模板要求写清“how”,包括:
API types, flag names, component interactions, and any non-obvious behavior belong here. Code snippets and YAML examples are welcome when they clarify intent.
即 API 类型、命令行 flag 名称、组件交互以及任何不易察觉的行为都应放在这里,鼓励使用代码片段和 YAML 示例来澄清意图。下面结合模板的六个子节逐一展开。
API Changes:字段、校验与默认值
如果 AEP 新增或修改 VPA API(autoscaling.k8s.io/v1),必须描述新类型、校验规则与默认行为,并尽量给出 Go struct 定义;若没有 API 变更则删除此节。
真实案例:AEP-7862 在 API Changes 中给出了完整的 Go struct 定义,并逐字段说明必填/可选、类型、默认值与合法组合约束。以StartupBoost.CPU为例,其字段约定如下表:
| 字段 | 必填性 | 类型 | 说明与约束 |
|---|---|---|---|
Type | 必填 | string | 提升方式,取Factor或Quantity;未知值按“不提升”处理以保证前向兼容 |
Factor | 条件必填 | integer | 推荐 CPU request 的倍数(如2表示翻倍);Type=Factor时必填,Type=Quantity时禁止;默认 1 |
Quantity | 条件必填 | resource.Quantity | 额外追加的 CPU 量(如"500m"、"1");Type=Quantity时必填,Type=Factor时禁止 |
DurationSeconds | 可选 | integer | Pod 进入Ready后保持提升状态的秒数;默认 0 |
模板要求的“校验规则与默认行为”在该 AEP 中体现为:提升后的 CPU 值受--max-allowed-cpu-boost命令行 flag 上限约束;建议为被提升容器配置 Readiness 或 Startup 探针,确保应用真正就绪后才执行“去提升”。此外,该 AEP 还专门用一节“Priority ofStartupBoost”阐明新字段的优先级——它优先于VerticalPodAutoscalerSpec与ContainerResourcePolicy中的其他字段,但TargetRef、ContainerName、ControlledValues除外;这意味着提升可以越过MaxAllowed、甚至在 CPU 被排除出ControlledResources时仍然生效。这类“字段优先级”的显式声明,正是模板所说“非显而易见行为属于这里”的实践。
Test Plan:单测 + e2e 双轨
模板要求至少说明两类测试:
- 单元测试:覆盖新增逻辑;
- e2e 测试:覆盖用户可见行为,并说明覆盖哪些场景。
集成测试对大多数 AEP 不是必需的,但若适用应提及。真实 AEP 通常会在该节枚举 e2e 场景矩阵。AEP-7862 的 Test Plan 即列出:提升应用于 Pod 全部容器、仅部分容器,以及“探针 ×DurationSeconds”四种组合下的去提升时机(无探针且未指定时长 → 立即去提升;无探针但指定 60s → 60s 后去提升;有探针且未指定时长 → PodReady后去提升;有探针且指定 60s →Ready后 60s 去提升),并验证“原地缩回失败时 Pod 不被驱逐”。AEP-4566 则写明通过 e2e 更新 VPA 对象的spec.updatePolicy.minReplicas并验证 Updater 行为随之改变。
Feature Enablement and Rollback:特性门控与回滚语义
若特性由 feature gate 门控,模板要求回答四个问题:feature gate 名称;依赖该 gate 的组件(如 updater、admission-controller、recommender);启用后发生什么;启用后禁用会怎样(特别是已配置新字段的 VPA 对象会如何)。若改动不受门控(例如带安全默认值的向后兼容 API 扩展),则要显式声明并说明无需 gate 的理由。
AEP-7862 是门控特性的完整范例:gate 名为CPUStartupBoost,依赖组件为 admission-controller 与 updater;启用后 admission-controller 接受带StartupBoost的 VPA 对象并执行提升、updater 注册 Pod 事件处理器并启动去提升 worker;禁用后 admission-controller 拒绝新对象并返回说明性错误、遇到已配置对象时不提升,updater 不注册处理器,已带提升注解的 Pod 将不被去提升。它还说明启用该 gate 时 updater 接受--concurrent-cpu-startup-boost-syncsflag(默认 1,控制并发去提升的 worker goroutine 数量)。
Graduation Criteria:从 alpha 到 GA 的判据
模板要求用少量条目描述特性从 alpha 到 beta、再到 GA 需要满足的条件,典型信号是“测试连续 N 个发布稳定”“无针对该 gate 的未关闭 bug”“用户反馈积极”。若改动不经历毕业生命周期(如纯 bug 修复),则删除此节。AEP-8818 即给出了 alpha 阶段的毕业判据条目。
Version Skew:多组件版本错位
VPA 由多个组件组成(recommender、updater、admission-controller),模板要求描述滚动升级期间版本不一致的后果,例如新 recommender 写入了旧 updater 不理解的字段时会发生什么。若 feature gate 能完全缓解错位(所有组件必须先启用 gate 行为才生效),也需明确说明;若只影响单个组件,可删除此节。
Kubernetes Version Compatibility:上游 K8s 版本依赖
当 AEP 依赖上游 Kubernetes 特性(如 KEP-1287 原地更新)时,必须写明所需的最低 Kubernetes 版本,以及在旧版本上 VPA 的行为。例如 AEP-7862 明确:StartupBoost假定运行在启用 KEP-1287 beta 版本的 Kubernetes 1.33+ 上,否则去提升可能失败、Pod 可能在整个生命周期内保持提升状态。AEP-4016 则梳理了 KEP-1287 从 1.27 alpha 到 1.33 beta 的演进,并特别指出 beta 初版中resizePolicy: PreferNoRestart的 Pod 禁止下调内存 limit 这一约束对 VPA 补丁行为的影响。
Implementation History:用绝对日期记录里程碑
模板要求用绝对日期(YYYY-MM-DD)记录:初版、重大设计变更、特性随首个 VPA 版本发布、升入 beta/GA。该节既是演进记录,也是评审者评估设计成熟度的依据。AEP 模板给出的占位行是- YYYY-MM-DD: initial version;AEP-7862 的 Implementation History 完整展示了从 2025-03-20 初版到 2026-08-11 的七次迭代,其中包括startupBoost.cpu.duration更名为durationSeconds、Type字段从可选改为必填、解除与InPlaceOrRecreate模式的耦合等关键设计转折。
Alternatives:记录被否决的方案
模板要求说明考虑过哪些其他方案、为何被否决:
Even a short note here helps future readers understand the design space and prevents the same alternatives from being re-proposed.
即使只有简短说明,也能帮助未来读者理解设计空间,避免同样的备选方案被重复提出。AEP-4566 的 Alternatives 一节记录了“维持现有全局--min-replicas行为”和“复用 Cluster Autoscaler 注解”两个被否方案及理由,可作为该节的写作参照。
从模板到落地:真实 AEP 如何组织正文
除了逐节拆解,观察真实 AEP 还能发现模板骨架之外的两种常见扩展方式,这对新提案作者有直接借鉴价值:
其一,按需增删子节,但保持骨架主线。模板是“骨架”(skeleton)而非“囚笼”。AEP-7862 在 Design Details 下增加了Workflow(逐步描述从配置到提升、再去提升的完整流程)、Validation(细分为静态校验与动态校验)、Reactive Unboosting Architecture(事件驱动去提升架构)与Mitigating Failed In-Place Downsizes(避免失败原地缩容引发驱逐循环)等子节,并增补了Examples章节给出六组 YAML 配置示例;同时由于该特性不经历 graduation 生命周期且无 version skew 问题,它省略了模板中的 Graduation Criteria 与 Version Skew 子节。而 AEP-8818 则额外引入Risk Mitigation章节分析内存 limit 下调风险。AEP-4016 更详细到比较Off/Recreate/InPlaceOrRecreate三种 UpdateMode 的行为差异。
其二,用“预置字段清单 + 判定条件”组织 Design Details。成熟 AEP 会在设计细节里给出新旧行为对照、判定条件与示例配置,让实现者和评审者对“何时触发、触发后做什么”有确定性的理解。例如 AEP-7862 在 Workflow 中明确:提升基准值为 VPA 推荐的 CPU request(推荐不可用或为零时退化为 Pod spec 原始 CPU request);CPU limit 是否随提升取决于ControlledValues的取值——RequestsOnly时提升后的 request 被限制在原始 limit 之下以保持 Pod QoS,RequestsAndLimits(默认)时按原始 limit/request 比例同步提升 limit,比例无法建立(如未设置 limit)则不改动 limit。这种精确到“每个分支行为”的描述,正是模板要求“包含足够细节使读者能评估方案是否健全”的体现。
与 VPA 源码的对应关系:AEP 术语背后的实现锚点
AEP 中反复出现的术语(UpdateMode、feature gate、组件名称)都能在仓库源码中找到对应实现,这既是评审的落点,也是新提案作者需要对齐的事实基础:
UpdateMode 枚举定义位于 vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1/types.go#L216-L253,包含
Off、Initial、Recreate、Auto、InPlaceOrRecreate、InPlace六种取值(Auto已被标记为 Deprecated,建议显式使用其他模式);同一文件中 PodUpdatePolicy 定义了updateMode、minReplicas、evictionRequirements、evictAfterOOMSeconds等字段,UpdateMode的合法取值由+kubebuilder:validation:Enum注解约束,对应模板 API Changes 一节所说的“校验规则”。helpers.go 中的GetUpdateModes则汇总了全部模式(并跳过已废弃的Auto)。AEP-4566 的
minReplicas字段已作为PodUpdatePolicy.MinReplicas落地(见 types.go#L196-L200),其注释明确“仅允许正值,覆盖全局--min-replicasflag”,与该 AEP 的 Proposal 完全一致。AEP-8818 的
InPlace模式也已进入枚举与常量定义(见 types.go#L246-L252),注释指出它“只尝试原地更新、永不驱逐”,并标注了所需的 VPA 级 gateInPlace与集群级 gateInPlacePodVerticalScaling——这正是模板中 Feature Enablement and Rollback 一节要求交代的“哪些组件依赖该 gate”。VPA 三组件架构(recommender、updater、admission-controller)对应仓库中的 vertical-pod-autoscaler/pkg/recommender、vertical-pod-autoscaler/pkg/updater、vertical-pod-autoscaler/pkg/admission-controller 三个目录,AEP 中关于“组件交互”的描述最终都会落到这些组件的具体行为上。例如 AEP-8905 指出
GetContainersResourcesForPod同时被 Updater 与 Admission Controller 使用,因此推荐与补丁逻辑的改动可以收敛在单一方法内。
这种“提案术语 ↔ 源码常量/结构体”的对应关系,提醒 AEP 作者:撰写 Design Details 时应尽量引用pkg/apis/autoscaling.k8s.io/v1/types.go等真实类型定义,让提案与实现基线保持一致,评审时也更容易核对。
一份高质量 AEP 的检查清单
综合模板注释与真实 AEP 的实践,可归纳出以下写作检查清单:
- 启动正确:已建跟踪 issue,目录名遵循
NNNN-short-descriptive-title规范,PR 按主题拆分且尽量小。 - 先立骨架后填肉:Summary 与 Motivation 先行足以启动讨论;设计定型后再补齐其余章节;实现过程中出现重大变化时编辑原 AEP 而非新开一份。
- 动机可证:Motivation 链接了 issue/用户报告;Goals 每条都可测试;Non-Goals 明确边界并尽量给出理由。
- What/How 分离:Proposal 只写用户可见行为;实现细节全部沉淀在 Design Details。
- 设计细节完整:API 变更含 Go struct、校验规则、默认值;交互与 flag 名称明确;复杂行为配 YAML/代码示例;删除了不适用子节(Graduation Criteria、Version Skew 等)而非留空。
- 门控语义清楚:有 gate 时写清名称、依赖组件、启用/禁用行为;无 gate 时显式声明原因。
- 兼容性与演进明确:依赖上游 K8s 特性时写明最低版本与降级行为;Implementation History 用绝对日期记录里程碑;Alternatives 至少简述被否决方案。
总结
AEP 模板为 VPA 子项目提供了统一、轻量、聚焦的设计提案框架:它以 KEP 的经典逻辑链为骨架,用 Summary/Motivation/Proposal/Design Details/Implementation History/Alternatives 六个部分覆盖“为什么、做什么、怎么做、怎么验证、如何演进、还有哪些备选”,并允许作者按特性实际需要增删子节。对照仓库中已合并的 AEP 实例可以看到,模板的每个章节要求都有真实的落地范式——从 API 字段表、feature gate 矩阵到 e2e 场景枚举,再到与pkg/apis/autoscaling.k8s.io/v1/types.go中UpdateMode枚举的对应关系。撰写新 AEP 时,以 NNNN-aep-template/README.md 为骨架、以 7862-cpu-startup-boost 等成熟提案为参照,即可产出一份信息密度高、可评审性强的设计文档。
【免费下载链接】autoscalerAutoscaling components for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/au/autoscaler
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考