Kubernetes 单体仓库拆分史:2017 贡献者峰会 "Breaking Up The Monolith" 讨论实录与技术复盘
【免费下载链接】communityKubernetes Community Documentation项目地址: https://gitcode.com/GitHub_Trending/com/community
2017 年 12 月 5 日,KubeCon 前夜,Kubernetes 贡献者峰会(Contributor Summit)在奥斯汀举行,采用"非结构化非会议(unconference)"的开放式鱼缸讨论形式(详见 ContribSummitInformation.md)。其中一场由 Josh Berkus(@jberkus)与 Aaron Crickenberger(@spiffxp)担任记录员的圆桌——breaking-up-the-monolith.md——围绕"是否以及如何拆掉 kubernetes/kubernetes 单体仓库"展开了针锋相对、信息密度极高的辩论。这场讨论记录了当时项目在代码组织上的核心痛点、候选拆分清单(kubectl、client-go、kubeadm、云厂商驱动等)、staging 机制、发布与测试基建的缺口,也直接影响了后来 Kubernetes 多仓库治理格局的形成。读完本文,你将完整还原这场关键讨论的各方论点、决策脉络,并结合本仓库的后续文档理解其历史走向。
一、背景:为什么 2017 年底必须谈"拆库"
彼时 Kubernetes 已经拥有约 90 个仓库(bgrant 在会上的原话:"We're already in the land of 90 repos"),但核心代码库 kubernetes/kubernetes 仍然是一个巨型单体仓库(monorepo)。会议记录开篇即点明本次讨论的三大主题:构建流程(build process)、Issue 跟踪(issue tracking)、工程后勤(logistics)。
与会者反复强调的动机可以归纳为两条主线:
- 核心无法持续以同样速度增长(erictune):"as the project matures the core can't keep growing at the same rate",项目成熟后核心代码库的膨胀速率必须被控制;
- 开发者体验恶化(mattfarina):单体仓库让新贡献者难以进入 Issue 队列、难以找到可贡献的切入点,"difficulty to contribute pushes people away from contributing";
- Issue 无人问津(thockin):主仓库中超过 6 周无人处理的 Issue 比比皆是,仅 network 相关就有 400~500 个被废弃的 Issue;
- 大量目录没有 OWNERS 文件(spiffxp):数百个目录缺乏负责人,导致通知泛滥、路由混乱。
这些问题的本质,是仓库规模增长与治理能力之间的失衡。
二、第一个问题:我们是否 100% 承诺拆分单体仓库
会议第一轮交锋围绕"拆分意愿"展开,结论是**"承诺拆分,但必须先定义拆分意味着什么"**。长期尝试维护单体仓库"太昂贵了"("We've been trying the monolith for so long and it's too expensive"),但支持与反对双方提出了截然不同的视角:
| 发言者 | 立场 | 核心观点 |
|---|---|---|
| erictune | 支持(有限度) | 生态可以增长,但"狭义定义的核心"不应继续膨胀 |
| mattfarina | 支持 | 贡献难度把潜在贡献者推走 |
| clayton | 谨慎 | kubectl 永远不会更简单,也许写一个新的反而更容易;"为什么建一个东西而不是花两倍成本建两个"(指拆出一个高性能 client-go + 一个面向人类、可复用的重写版 client-go) |
| bburns | 反对声音 | 我们从不量化拆分的成本,只因为"更干净"就喜欢拆,却没有估算人力与复杂度代价 |
| lavalamp | 反驳 bburns | 我们已经估算过成本,明知会很痛苦,但别无选择 |
| timstclair | 质疑落地 | 没有人回答过"如何把一组二进制作为一次发布交付",没有统一计划;测试基建如何覆盖所有组件也是未知数 |
| bburns | 补充质疑 | e2e 失败时如何定位导致失败的 commit |
| dims / matt | 提出清单 | 应该列出四五个优先级最高的外移项 |
其中 timstclair 提出的两个问题——多仓库下的发布交付计划与测试基建覆盖——成为贯穿整场讨论、乃至之后数年 Kubernetes 代码库治理的核心难题。lavalamp 则给出了一个关键的架构设想(文内标注 TODO link):主仓库(main repo)退化为"集成点",二进制产物由其他仓库生产。
三、第二个问题:拆分到底要解决什么问题
会议第二环节尝试厘清目标,而非手段。两个基本假设被摆上桌面:
- 贡献者速度与(新)贡献者体验正相关;
- "一大团纠缠的面条"(big tangled ball of pasta)难以贡献。
围绕"是否必须拆成独立仓库"出现了重要的分歧与深化:
- 模块化不一定等于多仓库(jberkus):其他大型项目经验表明,关键在于"模块化架构",而不必然是"多个仓库";
- 在仓库内部模拟多仓库(thockin):与其拆库,不如"移动代码"直到仓库内部看起来像多个子仓库——例如把 kubelet 相关逻辑全部集中到一个目录(除一个 util 目录外),或许本身就是一种改进;
- 先拆云厂商驱动(与会共识):"First thing: we're breaking up cloud providers, it helps let the long tail of cloud providers go out"。云厂商是第一个拆出去的对象,存储提供商随后也应有清晰接口;
- 明确的接口边界(dchen1107,时任发布经理):发布管理成本巨大,作为发布经理"我不知道另一个仓库里有什么";但清晰的 API 与接口并不需要独立仓库——她举了 Docker 与 CRI 的例子:不搬仓库也拿到了干净的 API;
- 决策机制缺失(robertbailey):提出本议题时以为大家已达成拆分共识,但显然没有;需要弄清"谁是决策者 / 决策者群体";
- 自动化与通知(spiffxp):多仓库对 GitHub 通知更友好,机器人改善了自动化但未解决通知分级;也许该改进通知路由而不是拆库;
- 小仓库接入门槛(solly):如果拆分,必须让小型仓库更容易接入自动化与工具链,"我不该自己摸索该问谁",应该有文档,不能出现 Heapster 那样"掉进裂缝里"的仓库。
bgrant 的一锤定音值得注意:"We're already in the land of 90 repos. We don't need to debate splitting, we're already split."——从治理现实看,拆分早已发生(incubator、kubernetes-client 等),争论的焦点其实是如何把拆分做对,尤其是让 API 类型、SDK 与通用工具链真正可复用("We need SDKs to build kube-style APIs")。
四、候选拆分清单:kubectl、client-go、kubeadm 与云厂商
会上形成了初步的"外移候选清单",这份清单与同一峰会其他分会场(如 cloud-provider.md)以及 2017 年 5 月领导力峰会上的 Code Organization and Release Process Improvement 高度呼应:
| 候选组件 | 会上讨论要点 | 后续走向(以本仓库文档为据) |
|---|---|---|
| kubectl | clayton 认为 kubectl 本身太大,值得围绕"新东西"重建社区;lavalamp 形容其为"拉入大量包、技术难以下手"的意大利面代码 | 已在拆分依赖的过程中,拥有独立仓库并迁移 Issue(见 0300-0345_CODEORGANIZATION.md) |
| client-go | 已独立发布,属于"另一个量级"的问题,需另开会讨论;clayton 提出"高性能版 + 面向人类重写版"双轨思路 | 对应 kubernetes-client 多语言客户端生态 |
| kubeadm | 留在主仓库是为了赶上发布列车(release train);曾尝试移出但失败;luxas(Lucas Käldström,时任 kubeadm 负责人)提出 kubeadm 仓库必须"权威"并能纳入构建 | 后续成立 Kubeadm Adoption 工作组推动采纳(见 archive/wg-kubeadm-adoption/README.md) |
| 云厂商驱动(cloud providers) | 首要拆分对象;dims 举例 Google KMS provider 被移出、gRPC 接口 PR 未进 1.9,说明在树外开发更灵活 | 同峰会 cloud-provider.md 记录了 cloud-controller-manager 拆分进展 |
| kubelet / kube-proxy | thockin 提出疑问:拆这些能带来具体收益吗,还是会带来更多痛苦?"我们清楚这会拖慢节奏" | 未在本次达成共识,留待后续 |
| 存储提供商 | 若拆分应有清晰接口 | 后续由 CSI 承接(同峰会 cloud-provider 讨论中亦有提及) |
会议还记录了"已完成 / 进行中"的拆分成果,作为可行性参考:API machinery(staging 化后解除了阻塞)、cloud provider、kubernetes-client 组织。bgrant 总结称:monorepo 中的"velocity 是静态的"("the velocity of things in the monorepo are static")。
五、绕不开的三大工程挑战:发布、测试、依赖
5.1 发布管理:多仓库如何拼出一次发布
这是 timstclair 抛出的最尖锐问题:"没有人回答过我们如何把一组二进制作为一次发布交付,没有统一计划。"其难点在于:
- 发布经理无法掌握其他仓库内容(dchen1107 作为时任发布经理的切身之痛);
- 安全更新必须快速送达(Cloud Foundry 两周构建流程被引为反面案例);
- 多仓库需要"组装发布":各组件在各自仓库测试充分后,由主仓库集成组装(参见 0300-0345_CODEORGANIZATION.md 中"Multi-repo requirements"一节);
- luxas 特别强调 kubeadm 的"攻击计划":需要为多仓库做一次发布,kubeadm 仓库要权威,且能纳入构建。
5.2 测试基建:谁来测、怎么定位回归
与会者担忧拆分后的测试覆盖问题:
- timstclair:"how are you actually going to get test infra to test all the things";
- bburns:"how do you actually find the commit that causes a failure in e2e";
- 会议结论倾向:用更小、更聚焦的测试取代过度依赖 e2e 的做法("Need better, smaller tests overall"),"不要在 e2e 上验证未经文档化的功能"。
5.3 依赖管理:godeps 的噩梦
timallclair 直言:"我担心依赖管理,godeps 已经是噩梦,多仓库只会更糟。" 这一担忧在后续 Kubernetes 全面转向 Go modules 后才得到缓解。此外 dims 指出 monorepo 的连带污染问题:vendor 会把不关心的 SDK(如 AWS SDK)拖进来——"如果只做 OpenStack 相关工作,在主仓库里很难获得合入批准,但在自己的仓库里就容易得多"。
六、staging 机制:在拆与不拆之间的第三条路
本场讨论反复出现的"staging"概念,值得单独说明。它是 Kubernetes 在仓库内部模拟多仓库的中间态:代码仍留在主仓库,但按 k8s.io 包路径组织成"伪仓库",通过符号链接进入 vendor 目录供 Go 工具链消费,再由发布机器人用git filter-branch将各 staging 目录切分成真实仓库推送到外部(详见本仓库文档 contributors/devel/sig-architecture/staging.md)。
会上围绕 staging 的价值与边界形成了几个重要判断:
- "staging 状态是解决了一半的状态"(lavalamp):API machinery 正是因为到达 staging 状态而被解除了阻塞;thockin 则认为 staging 已经"解决"了问题,因为"你得先把纠缠的依赖解开才能 staging";
- staging 可作为"已拆分"的观察窗口(pwittrock):可以从 staging 仓库的实例中看到拆分带来的收益或问题;
- erictune 的呼吁:请把"已经开工但没拆完"的分拆工作做完("finish some of our started-but-not-finished breakaparts");
- 同峰会 cloud-native-design-refactoring-across-k8s.md 也列出了跨仓库重构的相关 Issue 与 util 目录整合工作,可视作 staging 路径上的具体任务。
根据 staging.md 的记载,该机制最终演化为成熟的发布机器人(publishing bot)体系:支持多分支发布(master 及 release-1.28 至 release-1.31 等)、为发布仓库自动打kubernetes-前缀标签、并自 v1.17.0 起同步生成与主仓库 tag 对应的语义化v0.x.y标签以无缝衔接 Go modules。
七、没有结论的结论:走向"软件还是发行版"之问
这场讨论没有形成投票式的决议,但沉淀了几点关键共识:
- 拆分已既成事实,争论焦点是治理(bgrant:"我们已经有 90 个仓库");主仓库将演化为集成点,二进制产物由其他仓库生产(lavalamp);
- 必须量化成本:bburns 的"我们不测量成本"之问,与 lavalamp"我们已经估算过"的回答,共同指向同一个行动——拆分必须基于成本收益而非审美偏好;
- 扩展点需要接口而非拆库:CRI(Docker 例)、cloud provider、CRD、SDK 都是"不搬仓库也能拿 API"的证明;
- 对基础设施的依赖会加重(spiffxp):"增加对集成工具的依赖会带来现在没有的开销与流程",但多数 OSS 从业者期望多仓库,且 GitHub 通知在多仓库下更易管理;
- 自动化接入要有文档与统一入口(solly):不能让小仓库"掉进裂缝";
- thockin 将终极问题抛给全场:"我们是'一个软件'还是'一个发行版'(a piece of software or a distribution)?"——这个问题的答案决定了 monorepo 的未来形态。
回望本仓库的目录结构,这场 2017 年会议所讨论的分拆蓝图——kubectl 归 SIG CLI、云厂商驱动外置、client-go 独立发布、kubeadm 拥有独立工作组的采纳计划、staging 目录与发布机器人常态化——都在后续 Kubernetes 社区治理文档中得到了印证。对于研究大型开源项目代码库治理的工程师而言,这份会议记录是理解"monorepo 拆分之痛"的第一手史料:它诚实地记录了成本、分歧、技术债务与长期投入,而非一份粉饰过的决策白皮书。
延伸阅读
- 本场会议原始记录:breaking-up-the-monolith.md
- 2017 年 5 月领导力峰会同主题记录:0300-0345_CODEORGANIZATION.md
- staging 目录与发布机制:contributors/devel/sig-architecture/staging.md
- 云厂商拆分进展:events/2017/12-contributor-summit/cloud-provider.md
- kubeadm 采纳工作组:archive/wg-kubeadm-adoption/README.md
- 峰会整体信息与议程:events/2017/12-contributor-summit/ContribSummitInformation.md
【免费下载链接】communityKubernetes Community Documentation项目地址: https://gitcode.com/GitHub_Trending/com/community
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考