ingress-nginx 的 KEP(Kubernetes Enhancement Proposal)流程:从提案模板到社区共识
【免费下载链接】ingress-nginxIngress NGINX Controller for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/in/ingress-nginx
导读
本文以 docs/enhancements/README.md 为核心,系统讲解 Ingress NGINX Controller 项目如何借鉴 Kubernetes 社区的 KEP(Kubernetes Enhancement Proposal)机制来规划、沟通与沉淀大型功能改动。你将了解:KEP 的适用场景与收益、完整的提案文件结构(元数据、Summary、Motivation、Proposal、Design Details 等)、标准模板的填写步骤,以及项目内三份真实 KEP(动态 SSL、可用区感知路由、容器拆分)是如何一步步演变为实际功能的。读完本文,你可以直接照搬该模板,为 ingress-nginx 的社区协作提出自己的结构化提案。
KEP 是什么?为什么 ingress-nginx 要采用它
KEP(Kubernetes Enhancement Proposal)是 Kubernetes 社区用于"提出、沟通并协调新工作"的标准方式。ingress-nginx 作为 Kubernetes 生态中最常用的入口控制器之一,其功能演进往往牵涉数据面(NGINX)、控制面(Go Controller)与 Lua 脚本等多个模块,因此项目官方在 docs/enhancements/README.md 中明确宣布采纳该机制。
文档明确指出 KEP 的定位:
- 不是强制要求:KEP 仅在改动"范围广泛、影响项目大部分模块"时才需要;
- 但强烈鼓励使用:长此以往,在同一个地方积累丰富 KEP 集合,会让社区更容易追踪正在发生的事,并形成结构化的历史档案。
使用 KEP 的收益
README 从"KEP 使用者"角度列出了核心收益:
- 在可被搜索引擎检索到的 Kubernetes 生态站点上获得曝光;
- KEP 之间可交叉索引,方便用户找到关联提案及其当前状态;
- 提供明确的、带 approvers 与 reviewers 的决策流程,让决策更结构化、更可追溯、更经得起时间检验。
该项目明确表示,其灵感来源于 IETF RFC、Python PEP 和 Rust RFC——即"以公开、编号、可版本化文档承载技术决策"的成熟社区治理模式。
开始一个 KEP:标准模板与填表步骤
KEP 的起点是 YYYYMMDD-kep-template.md 模板。文件命名规则为YYYYMMDD-my-title.md,其中YYYYMMDD是提案首次起草的日期,标题全部小写,空格与标点替换为-(如20190724-only-dynamic-ssl.md)。
完整的 KEP 文件结构
模板给出了一个 KEP 文档应包含的全部章节,从源码目录看,每个章节在真实 KEP 中都被逐段落实:
| 章节 | 作用 | 模板要求 |
|---|---|---|
| YAML Front Matter | 元数据区 | 记录 title、authors、reviewers、approvers、editor、creation-date、last-updated、status、see-also、replaces、superseded-by |
| Table of Contents | 目录 | 用<!-- toc -->/<!-- /toc -->包裹,由脚本自动生成 |
| Summary | 摘要 | 至少一段话,可直接复用到 release notes 或开发路线图 |
| Motivation | 动机 | 说明为何重要、对用户的价值,可拆分 Goals 与 Non-Goals |
| Proposal | 提案正文 | 可选 User Stories、Implementation Details/Notes/Constraints、Risks and Mitigations |
| Design Details | 设计细节 | 关键是 Test Plan(直到针对某个 release 时才强制要求) |
| Implementation History | 实施历史 | 记录 KEP 生命周期中的重大里程碑 |
| Drawbacks / Alternatives | 可选 | 记录"为什么不实现"与"其他方案" |
Metadata 元数据区详解
模板开头的 YAML 块是 KEP 工具化的关键支撑,各字段含义如下:
--- title: KEP Template authors: - "@janedoe" reviewers: - TBD - "@alicedoe" approvers: - TBD - "@oscardoe" editor: TBD creation-date: yyyy-mm-dd last-updated: yyyy-mm-dd status: provisional|implementable|implemented|deferred|rejected|withdrawn|replaced see-also: - "/docs/enhancements/20190101-we-heard-you-like-keps.md" replaces: - "/docs/enhancements/20181231-replaced-kep.md" superseded-by: - "/docs/enhancements/20190104-superseding-kep.md" ---其中status字段定义了 KEP 的完整生命周期状态机:provisional(草案)、implementable(可实施)、implemented(已实施)、deferred(推迟)、rejected(拒绝)、withdrawn(撤回)、replaced(被取代)。see-also、replaces、superseded-by用于建立 KEP 之间的关联关系,配合模板中的"交叉索引"收益使用。
五步走:模板推荐的启动流程
模板给出了明确的起步步骤:
- 复制模板:创建
YYYYMMDD-my-title.md; - 填写 overview 章节:即 Summary 和 Motivation,建议先在 issue 中预热想法;
- 创建 PR:指派给赞助该流程的成员;
- 创建 issue:填写 enhancement 跟踪 issue 的全部字段;
- 尽早合并:先只提交 Overview 部分,后续 PR 增量补充细节——凡是标记为
provisional的内容都视为"进行中的工作文档",允许变更。同时坚持"单主题 PR",让讨论保持聚焦。
目录(TOC)的自动化维护
模板要求 TOC 使用<code><!-- toc --&rt;<!-- /toc --&rt;</code>标签包裹(即<!-- toc -->注释),并通过 hack/update-toc.sh 自动生成。该脚本的核心逻辑是:
go install ./vendor/github.com/tallclair/mdtoc grep --include='*.md' -rl docs/enhancements/* -e '<!-- toc -->' | xargs mdtoc --inplace即用mdtoc工具扫描docs/enhancements/下所有含<!-- toc -->标记的 Markdown 文件并原地更新目录——这也解释了为何三份真实 KEP 中都能看到自动生成的 TOC。
三份真实 KEP 拆解:提案如何落地为代码
docs/enhancements/目录下已有三份按模板撰写的真实 KEP,它们分别对应项目演进中的三个关键决策,可以作为撰写自己 KEP 的"最佳实践范本"。
案例一:20190724-only-dynamic-ssl.md —— 移除静态 SSL 配置模式
这份 KEP 的元数据完整展示了 approvers/reviewers 的分工(作者@aledbf,评审与审批@ElvinEfendi),status: implementable表明已进入可实施阶段。其核心论证链条:
- Summary:自 0.19.0 起可用 Lua 实现无需 reload 的 SSL 证书配置,0.24.0 起动态模式成为默认;
- Motivation:静态配置意味着 reload,而 reload 影响绝大多数用户;
- Goals:废弃
--enable-dynamic-certificates标志、清理代码库;Non-Goals:不改变证书认证相关功能; - Proposal:移除静态 SSL 配置,将
ssl_certificate与ssl_certificate_key指令从各 server 块移到http段以避免日志报错; - Alternatives:保留双实现。
这份 KEP 体现了"用一个提案解决一个明确问题"的最小化范例——目标、非目标、方案与替代方案一目了然。
案例二:20190815-zone-aware-routing.md —— 可用区感知路由
这是内容最详实的一份 KEP,完整示范了 Proposal 章节应有的工程深度。背景是跨可用区(inter-zone)流量会产生额外成本与延迟,提案目标是让 ingress-nginx 优先把请求转发到同可用区(zone-local)的 endpoint。其核心设计要点:
- 控制器通过 downward API 将节点名注入为环境变量,启动时查询 API 获取节点详情,并从
failure-domain.beta.kubernetes.io/zone注解提取当前 Pod 所在可用区; - 控制器监听节点 create/update 事件,在内存维护"节点名 → 可用区"映射,生成 endpoints 时通过
.subsets.addresses[i].nodeName关联可用区;备选方案是启动时全量拉取节点建表、缺失时按需查询,以减少对 API server 的 watch 压力; - 在 Lua 侧为每个 backend 初始化两个 balancer 实例(全量 endpoints 与仅当前可用区 endpoints),优先使用 zonal balancer,不存在时回退到通用 balancer;可用区故障时依赖就绪探针失效使该 backend 无可用 endpoint,从而自然回退;
- 特性通过 ConfigMap 开关启用,便于出现问题后回滚。
该提案明确列出了 Goals(best-effort 选择 zone-local endpoint、不影响 canary 功能、无可用区 endpoint 时仍可正常工作)、Non-Goals(假设 endpoint 分布足以消化本可用区流量;仅依赖failure-domain.beta.kubernetes.io/zone,不支持其他场景)以及 Drawbacks(对 Kubernetes API server 增加负载)。
这一 KEP 提出的设计方向与当前仓库源码中的可用区相关处理逻辑存在对应关系——在 internal/ingress/controller/endpointslices.go、internal/ingress/controller/controller.go 及模板生成代码 internal/ingress/controller/template/template.go 中均可检索到 zone 相关字段的处理痕迹,可以作为追踪该特性演进起点的索引。
案例三:20231001-split-containers.md —— 容器拆分提案
这份 KEP 面向镜像架构演进,其内容格式略有不同(未使用标准 YAML 元数据,更接近设计草稿),重点规划了控制面与数据面的拆分:
- 一个容器只放 NGINX 相关文件(不挂载 ServiceAccount),另一个容器只放控制器文件(最小化 Go 程序,SA 只挂载到控制器);
- NGINX 容器内需要一个极小的 HTTP 监听器,仅负责启动、停止与 reload NGINX;
- 明确了 NGINX 容器的端口规划:公网 HTTP/HTTPS 端口 80/443;Lua 配置端口 10246(HTTP)与 10247(Stream);3333(临时)为 Dataplane 控制器的 HTTP server,提供
/reload(POST,config参数指定待替换的临时 nginx.conf 路径)与/test(POST,config参数指定待测试的配置文件路径); - 给出了挂载空 ServiceAccount 的 Pod 示例 YAML、NGINX 配置映射目录清单(Lua 脚本、日志、pid、GeoIP、SSL、auth、Modsecurity、OTEL/Opentracing 配置等)以及可移除文件清单与模块清单。
从源码看,该 KEP 的落地痕迹非常清晰:仓库中确实存在独立的 Dataplane 入口 cmd/dataplane/main.go,其启动流程为解析 flags(ingressflags.ParseFlags)、创建必填目录、初始化 Prometheus 注册表与指标收集器、创建controller.NewNGINXController,并通过ngx.Start()启动 NGINX 控制器逻辑;而 internal/ingress/controller/config/config.go 中的ListenPorts结构体精确刻画了运行所需端口集合:
// ListenPorts describe the ports required to run the // NGINX Ingress controller type ListenPorts struct { HTTP int `json:"HTTP"` HTTPS int `json:"HTTPS"` Health int `json:"Health"` Default int `json:"Default"` SSLProxy int `json:"SSLProxy"` }在 internal/ingress/controller/controller.go 中,这些端口被逐一用于启动监听。可见 KEP 文档中规划的端口与目录拆分,最终演化为当前仓库中cmd/dataplane与internal/ingress/controller的模块化实现。
撰写高质量 KEP 的实践要点
综合 README、模板与三份真实案例,可以提炼出以下可复用的写作准则:
- 先用 Summary 定调:Summary 是 release notes 与路线图的素材来源,应在实现前写好,避免实现者分心;
- Goals 与 Non-Goals 缺一不可:Non-Goals 明确"范围外"内容,能有效聚焦讨论并推进进度(参考 zone-aware routing 对 canary 特性的排除);
- Proposal 落到实现细节:真实 KEP 会具体到端口号、Lua 模块加载时机(如
init_by_lua阶段)、API 调用方式与回滚策略; - 尽早合并、增量完善:先合并 Overview,后续 PR 补充细节;
provisional状态即"活文档"; - 用 Implementation History 记录里程碑:包括 Summary/Motivation 合并(表示被接受)、Proposal 合并(表示设计达成一致)、实现启动日期、首次随哪个 release 发布、何时 GA 或退役;
- Test Plan 到 release 阶段再补全:模板明确注明该节"直到针对某个 release 时才需要",但需考虑 e2e、集成测试与单测的总体策略,并遵循 Kubernetes 测试指南;
- 善用可选章节:Drawbacks(为什么不该实现)与 Alternatives(其他可行方案)用于记录决策上下文,避免后人重复讨论。
从提案到共识:KEP 在项目协作中的定位
从仓库整体看,KEP 机制是 ingress-nginx 社区治理的一部分:提案(docs/enhancements/)→ 代码实现(internal/、cmd/)→ 测试验证(test/e2e/)→ 版本发布(changelog/、charts/ingress-nginx/changelog/)形成完整闭环。三份 KEP 恰好覆盖了项目演进的三个典型层次——功能废弃(动态 SSL)、行为增强(可用区路由)、架构重构(容器拆分),说明这套流程既能承载小范围决策,也能承载影响整个镜像与部署模型的大改动。
对于想要参与 ingress-nginx 社区贡献的开发者,最直接的上手路径是:先在 issue 中预热想法 → 复制 YYYYMMDD-kep-template.md 为YYYYMMDD-你的标题.md→ 完成 Summary 与 Motivation → 尽早创建 PR,随后增量补充 Proposal、Design Details 与 Implementation History。这样你的设计决策就能像 RFC 一样,成为这个社区可检索、可追溯、经得起时间检验的公共档案。
【免费下载链接】ingress-nginxIngress NGINX Controller for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/in/ingress-nginx
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考