侧边栏壁纸
  • 累计撰写 228 篇文章
  • 累计创建 228 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

从 Jenkins 到 GitOps:微服务交付体系的一次渐进式演进复盘

zhanjie.me
2026-02-07 / 0 评论 / 0 点赞 / 3 阅读 / 0 字

这是“微服务平台治理”系列的第五篇。
如果前几篇分别解决了服务怎么跑、跑在哪、怎么进来、出了问题怎么看,那么这一篇真正要回答的,就是这些已经被治理过的系统,应该如何被更可控地交付和变更。

摘要

这次交付体系演进,并不是一个“旧平台下线、新平台上线”的替换故事。真实发生的变化,是交付开始从工具链拼接逐步走向平台对象驱动:对外,平台尝试把研发和测试的交付入口收敛成更低心智负担的声明式对象;对内,平台开始把分散在 Jenkins、ArgoCD、Kubernetes 等系统中的 deploy change 状态收敛成统一对象和统一状态面。GitOps 在这里不是一夜替换掉 Jenkins 的新系统,而是一种逐步进入交付体系的治理方式。

系列导航

正文

0. 导语:交付问题不只是“怎么发”,而是“怎么把变更管起来”

在很多团队里,交付体系最先解决的,通常都是执行效率问题:

  • 代码怎么构建
  • 制品怎么分发
  • 应用怎么部署
  • 发布失败后怎么回滚

只要把这些动作从人工操作收敛成自动化流水线,交付体系就已经能带来非常明显的收益。

但当平台继续往微服务、容器化和平台治理演进之后,交付问题会开始变化。
这时候,交付体系面对的已经不只是“怎么把一个版本发出去”,而是更底层的问题:

  • 用户应该通过什么入口发起一次交付
  • 平台应该如何理解这次变更想达成什么目标
  • 一次 deploy change 应该以什么对象被承接
  • 这次 change 当前处于什么状态
  • 后续的审计、排障和 RCA,能否围绕这次变更形成统一视图

也就是说,交付体系真正难的,开始不再只是执行链路自动化,而是变更治理。

这也是为什么当我们已经完成了运行时治理、容器平台建设、入口流量治理和可观测平台建设之后,会越来越明显地感觉到:如果交付体系仍然主要停留在“Jenkins 触发一下、脚本执行一下、系统分别记一段状态”的模式里,那么整个平台虽然已经在很多层面变得更结构化,但交付这一层仍然会显得有些割裂。

从这个角度看,GitOps 在我们的场景里,并不是一个“突然上线的新平台”,也不是一个“一夜替换掉 Jenkins 的标准答案”。它更像是一种开始逐步进入交付体系的治理方式。

这次演进真正想解决的,也不是“把所有旧链路推倒重来”,而是两件更本质的事情:

  • 面向研发、测试收敛平台入口,让用户通过更低心智负担的声明式 YAML 发起交付
  • 面向平台收敛 deploy change 的状态与事件,让一次变更拥有更清晰的对象边界、状态边界和审计边界

所以这篇文章想复盘的重点,不是 GitOps 工具本身怎么配置,而是当微服务平台已经拥有运行时平台、入口治理和可观测能力之后,交付体系为什么也必须从“工具链拼接”逐步走向“平台对象驱动”。

1. 改造前:Jenkins 主导发布解决了什么,又留下了什么边界

如果回头看我们原来的交付体系,其实它并不弱。甚至可以说,在相当长一段时间里,它已经很好地解决了“自动化发布”这件事。

整体上,这套链路大致由几部分组成:

  • Jenkins / GitLab Runner 负责构建
  • Harbor 负责承接镜像和制品
  • Ansible 与部分脚本能力继续承接一些发布动作
  • ArgoCD 开始进入部分声明式发布场景
  • Kubernetes 原生能力本身也提供了一部分 rollout 与回滚支持

从结果上看,这套体系已经把很多原本需要人工操作的事情自动化了。应用不再需要手工打包、手工发版、手工拷贝和手工重启,CI/CD 这条链路已经具备了比较成熟的执行能力。

如果文章只停在“有没有自动化”这个层面,那其实已经可以说它是成功的。但问题在于,平台继续演进之后,新的边界开始逐渐显现出来。

1.1 旧交付体系首先解决的是“执行效率”问题

早期交付体系最直接的价值,是把发布动作从人工操作收敛成了一条自动化执行链路。

它能比较稳定地完成这些事:

  • 从代码仓库拉取代码
  • 触发构建
  • 生成镜像或制品
  • 推送到 Harbor
  • 触发部署或同步动作
  • 利用已有平台能力完成上线与回滚

这一阶段的核心目标其实很明确:减少人工、提升效率、降低重复劳动。

从这个角度看,Jenkins 作为交付体系的中心是非常自然的。因为它最擅长的,就是把原本分散的脚本步骤和流水线步骤组织成一条可以被重复执行的流程。

1.2 但随着平台结构化程度提高,交付入口开始显得过于分散

问题并不在于 Jenkins 不能用,而在于当平台其他层已经越来越结构化时,交付入口仍然相对分散。

对研发和测试来说,一次交付往往并不只是“点一下发布”这么简单。在很多情况下,他们需要理解的,其实是多套系统的组合关系:

  • 哪个 Jenkins job 负责什么
  • 哪段 GitLab Runner 流水线在起作用
  • 哪些参数该怎么传
  • ArgoCD 那边的同步对象是什么
  • 某些部署动作最终落到哪里

也就是说,底层执行链路虽然已经自动化了,但用户视角下的入口并没有真正被收敛。

这会带来一个很典型的问题:平台内部的复杂度,仍然有一部分外溢到了用户侧。研发和测试虽然不一定需要亲自维护底层工具,但仍然需要理解不少底层工具语义,这会不断抬高使用成本。

1.3 deploy change 的状态散落在多个系统里

除了入口分散,另一个越来越明显的问题是:一次交付变更的状态,散落在太多不同系统里。

同样是一次发布,你可能会在不同地方看到不同片段的信息:

  • Jenkins 里有一段构建和执行记录
  • Harbor 里有镜像与制品信息
  • ArgoCD 里有同步状态
  • Kubernetes 里有 rollout 状态
  • 其他日志系统里还有附加执行痕迹

每个系统都记录了一部分事实,这本身没有错;但问题在于,这些事实并没有天然围绕“一次 deploy change”被收敛成一个统一对象。

这样做的后果是:

  • 审计时需要人工拼接
  • 排障时需要在多个系统间来回切换
  • 很难回答“这次变更现在到底处于哪个阶段”
  • 也很难回答“这次变更到底影响了哪些对象”

换句话说,旧交付体系更擅长把事情做完,但不擅长把“这次变化本身”以平台对象的方式沉淀下来。

1.4 平台越成熟,交付越不能只停留在“脚本驱动”

如果平台还停留在早期阶段,这种割裂感其实不会特别明显。因为那时最重要的是“能发出去”,而不是“变更对象是否足够结构化”。

但当平台逐渐具备了:

  • 运行时治理
  • ACK 容器承载
  • APISIX 入口治理
  • 三层可观测能力

之后,交付这一层如果仍然主要靠脚本和工具链拼接去承接,就会越来越像整个平台里最缺乏统一抽象的一环。

这时候问题就不再是“执行链路能不能工作”,而是:

  • 这套执行链路是不是已经足够适合平台继续演进
  • 用户是不是还在为底层复杂度买单
  • 平台是否已经拥有了围绕 change 的统一对象与统一状态面

小结

所以回头看,Jenkins 主导的旧交付体系并不是“不行”,而是它更适合解决“自动化执行”问题,而不是“交付治理”问题。

它已经很好地解决了构建、制品和发布动作自动化,但随着平台演进,新的问题开始浮现出来:

  • 用户入口还不够收敛
  • 变更状态还不够统一
  • 审计和 RCA 还缺少围绕 change 的结构化承载对象

也正是从这里开始,我们才真正开始需要 GitOps 思维。

2. 为什么开始需要 GitOps 思维

很多时候,一提到 GitOps,最容易出现的误解就是:是不是因为 Jenkins 不够好了,所以才要换成 GitOps?

但对我们来说,答案恰恰不是这样。

这次演进并不是因为旧体系完全失效了,也不是因为某个工具突然“不先进”了。真正推动 GitOps 思维进入交付体系的原因,是整个平台本身已经开始越来越结构化,而交付这一层如果不跟着变化,就会越来越显得割裂。

2.1 平台其他层已经逐渐声明式化了

如果把前面几篇文章放在一起看,这个变化其实很明显。

在 Nacos 那篇里,我们已经把:

  • 配置治理
  • 注册治理
  • 环境边界

逐渐收敛成一套更明确的运行时模型。

在 ACK 那篇里,我们又把:

  • 工作负载
  • 生命周期
  • 健康状态
  • 扩缩容
  • 运行时承载能力

逐渐放进了 Kubernetes 这套声明式平台对象中。

在 APISIX 那篇里,入口层流量治理也开始变成:

  • 规则化
  • 条件化
  • 可切换
  • 可收敛变更面

而到了可观测平台这一篇,指标、日志、链路也已经不再只是零散工具,而开始围绕结构化信号和定位路径来组织。

也就是说,平台的很多层面都已经开始从“命令式操作”走向“对象化治理”。

如果交付体系仍然主要停留在“触发脚本、执行流水线、各系统分别记录状态”的阶段,那么它就会越来越成为整套平台里最不一致的一层。

2.2 GitOps 在这里更像一种治理方式,而不是单一工具替换

从这个角度看,我们开始需要的其实不是某个具体工具,而是一种新的交付治理方式。

这种方式至少包含几个明显的特征:

  • 发布对象应该更声明式
  • 变更目标应该更清晰
  • 平台应该知道“期望状态是什么”
  • 回滚不应该只是“再跑一次旧流程”,而应该尽可能回到旧的声明状态
  • 审计不应该只看谁点了按钮,而应该看 Git 中到底声明了什么变化

这些思路,本质上就是 GitOps 的治理方向。

所以对我们来说,GitOps 真正有吸引力的地方,不是“它替代 Jenkins”,而是它让交付这件事第一次有机会拥有:

  • 更清晰的声明边界
  • 更清晰的状态边界
  • 更清晰的审计边界

2.3 旧体系更擅长执行流程,GitOps 更擅长收敛目标状态

如果一定要对比两者的侧重点,我会更愿意这样理解:

  • Jenkins 更擅长组织执行流程
  • GitOps 更擅长收敛目标状态

这两者并不天然冲突。

前者关心的是:

  • 这一步怎么跑
  • 那一步怎么串
  • 谁负责触发构建
  • 谁负责触发部署

后者关心的是:

  • 最终系统应该变成什么状态
  • 当前状态和目标状态是否一致
  • 变更是不是以声明形式可回溯
  • 回滚是不是可以回到旧的目标状态

当平台还在早期阶段时,流程自动化往往更重要;但当平台逐渐成熟之后,目标状态治理的重要性就会越来越高。

也正因为这样,GitOps 并不是来“否定”原有流水线,而是来补上原有流水线在状态治理这一侧的不足。

2.4 GitOps 的引入,本质上是为了让交付更像平台,而不是更像脚本集合

从平台演进角度看,这一点尤其重要。

如果交付只是一些流水线脚本和工具链的组合,那么它虽然能工作,但很难像运行时平台那样拥有统一对象、统一状态和统一边界。而一旦引入 GitOps 思维,交付就开始不再只是“执行一些动作”,而更像是在维护一个平台所认知的目标状态。

这件事会直接影响后面的很多能力:

  • 用户入口是否能进一步收敛
  • 变更状态是否能统一回收
  • 回滚是否更清晰
  • 审计是否更结构化
  • AI RCA 以后有没有结构化 change 数据可以用

也就是说,GitOps 在这里真正改变的,并不是“多一个工具”,而是交付开始从“流程执行系统”往“平台治理系统”方向走。

小结

所以回头看,我们开始需要 GitOps 思维,并不是因为 Jenkins 不够用了,而是因为平台已经进入了一个新的阶段:

  • 运行时越来越对象化
  • 环境边界越来越结构化
  • 可观测越来越信号化
  • 那么交付也必须开始走向声明式与状态化治理

GitOps 在我们的场景里,并不是一套一夜替换掉 Jenkins 的新系统,而是一种逐步进入交付体系的治理方式。

3. 这次演进真正想解决的两个问题

如果继续往下问,一个最关键的问题就是:

这次交付体系演进,到底想解决什么?

如果不先把这个问题讲清楚,整篇文章很容易写散。因为从工具角度看,这里面会涉及 Jenkins、GitLab Runner、Harbor、Tekton、ArgoCD、Kubernetes 等很多组件;但如果只是把工具挨个写一遍,就会丢掉这篇文章最有价值的部分。

在我们的实践里,这次演进真正想解决的,其实可以收敛成两个问题。而且这两个问题,一个面向用户,一个面向平台。

3.1 面向用户:把交付入口收敛成更低心智的声明式对象

第一个问题,是用户入口问题。

随着系统越来越复杂,研发和测试在发起一次交付时,往往不得不理解很多并不属于他们核心职责的底层细节:

  • Jenkins job 怎么组织
  • 哪些参数该怎么填
  • 底层到底是 Tekton 还是 ArgoCD
  • 哪条链路会触发构建
  • 哪条链路会触发部署
  • 某次发布应该通过哪个系统入口完成

这类复杂度如果长期停留在用户视角里,就会有两个明显问题:

  • 用户使用成本不断升高
  • 平台内部复杂度持续外溢

所以这次演进的第一个核心目标非常明确:不是让用户“学会更多平台工具”,而是让平台把复杂度收回去,让用户面对更稳定、更低心智负担的声明式入口。

也就是说,用户应该提交的是“我要发什么、发到哪里、用什么参数”这类声明,而不是直接操作底层执行引擎。

从这个角度看,声明式 YAML 的价值不在“格式是 YAML”,而在于它把交付入口从工具语义收敛到了平台语义。

3.2 面向平台:把 deploy change 收敛成统一对象和统一状态面

第二个问题,是平台状态问题。

旧交付体系已经能做很多事,但一次 deploy change 的信息仍然散落在多个系统中。这导致平台虽然能执行变化,却很难围绕“这次变化本身”形成统一视图。

所以第二个核心目标,就是把一次变更尽量收敛成一个平台对象,并让状态围绕这个对象统一沉淀下来。

也就是说,平台需要尽量回答清楚这些问题:

  • 这次 change 是什么
  • 目标是什么
  • 当前运行到了哪个阶段
  • 关联了哪些底层执行对象
  • 哪一步失败了
  • 最终对哪些运行对象产生了影响

这件事对平台治理非常重要。因为一旦 change 拥有了统一对象和统一状态面,那么很多过去必须靠人工拼接的事情,都会开始变得更清晰:

  • 发布过程更容易观察
  • 失败点更容易定位
  • 审计更容易落地
  • 未来 AI RCA 也更容易获得结构化输入

3.3 这两个目标表面上不同,本质上是一件事

从表面上看,“收敛用户入口”和“收敛平台状态”像是两件事。但如果更深入一点看,就会发现它们其实是同一个平台问题的两个面。

对外,平台需要把复杂度收回来,给用户一个更低心智负担的声明式入口。对内,平台又必须把执行结果和变更状态收回来,形成统一的对象视图。

如果只做前者,不做后者,那么平台只是把入口包装了一层,但内部状态仍然是碎片化的;如果只做后者,不做前者,那么平台虽然有统一状态面,但用户还是得直接面对过多底层工具语义。

所以真正完整的方向应该是:

  • 对外收敛入口
  • 对内收敛状态

这也是为什么我们后面会把交付体系逐步抽象成“平台对象 + 底层执行引擎”的分层结构。

小结

所以如果要用一句话概括这次演进真正要解决的问题,我会更愿意这样说:

这次交付体系升级,表面上是在引入 GitOps,实际上是在做两件更底层的事情:对外收敛用户入口,对内收敛变更状态。

4. 对外:为什么要把交付入口收敛成声明式对象

真正的问题并不是“用户从哪个页面点发布”,而是用户到底应该面向什么语义发起交付。

当平台内部已经同时存在 Jenkins、GitLab Runner、Harbor、Tekton、ArgoCD、Kubernetes 等多套能力时,如果用户仍然需要直接理解这些底层系统的语义,那么平台虽然帮忙“做了事”,却没有真正帮用户“收复杂度”。

这也是为什么我们越来越明确地意识到:用户不应该直接面向底层执行引擎,而应该面向更稳定的声明式平台对象。

4.1 用户真正关心的,不应该是底层工具,而是交付意图

从研发和测试的视角看,他们真正想表达的,通常不是:

  • 我要触发哪个 Jenkins job
  • 我要运行哪条 Tekton Pipeline
  • 我要改哪个 ArgoCD Application
  • 我要点哪一个系统里的哪个按钮

他们真正关心的,更多是这类问题:

  • 我要发布哪个服务
  • 我要用哪个版本或分支
  • 我要发到哪个环境
  • 这次发布有哪些参数
  • 这是不是一次验证性发布
  • 我现在只是想让平台帮我完成一次标准 change

也就是说,用户真正拥有的是“交付意图”,而不是“执行引擎细节”。

如果平台不能把这两者分开,那么底层工具越多,用户的心智负担就会越重;而一旦平台把入口收敛成声明式对象,用户表达的就不再是“调用哪个工具”,而是“声明我要做什么”。

4.2 声明式 YAML 的价值,不在格式,而在边界收敛

很多时候,一说到“声明式入口”,最容易让人把注意力放到 YAML 本身。但在我们的实践里,真正重要的其实从来不是“是不是 YAML”,而是:

  • 用户提交的是不是平台对象
  • 这个对象表达的是不是用户意图
  • 它是不是已经把底层工具细节隔离掉了

YAML 只是承载形式,真正有价值的是对象边界。

当研发或测试提交一份声明式对象时,平台更希望它表达的是:

  • 这次 change 属于什么类型
  • 它作用于哪个服务或哪个模板
  • 它的目标环境是什么
  • 它带了哪些参数
  • 平台后续应该如何把它翻译成底层执行动作

一旦这一层成立,用户入口就会从“记住很多工具和流程”变成“提交一个稳定的平台对象”。

4.3 为什么用户不应该直接操作 Tekton、ArgoCD 或 Jenkins

这件事可以说得更直接一点:

用户不应该直接操作 Tekton、ArgoCD 或 Jenkins,并不是因为这些工具不好,而是因为它们的语义本来就不属于用户侧。

Jenkins 擅长的是流程组织。
Tekton 擅长的是流水线编排。
ArgoCD 擅长的是声明状态同步。
而用户真正想表达的,并不是“我要使用某种流程编排引擎”,而是“我要完成一次交付”。

如果用户直接面向这些工具,那么平台就会不断把内部实现细节暴露到外部。表面上看,这似乎提高了“灵活性”,但实际上会带来三类问题:

  • 用户需要理解过多底层模型
  • 平台后续很难替换或重组底层实现
  • 交付入口难以形成稳定、统一的语义

所以更合理的方式,不是让用户变成工具专家,而是让平台把这些工具收进内部,通过更稳定的平台对象去承接用户意图。

小结

所以回头看,把交付入口收敛成声明式对象,真正解决的不是“让用户少填几个参数”,而是把平台内部复杂度从用户侧收回来。

声明式入口真正收敛的,不只是操作入口,而是平台语义。

5. 对内:为什么要把执行面拆成平台对象与底层引擎

一旦用户入口被收敛成高层对象,平台内部就不能再只是“收到请求后执行一些脚本”。它必须进一步回答:用户声明如何被翻译、由谁翻译、翻译之后交给谁执行、状态又由谁统一回收。

在我们的实践里,更合理的方式是把执行面拆成三层来理解:

  • 用户入口层
  • 平台控制层
  • 底层执行引擎层

5.1 用户入口层:表达“我要做什么”

这一层面向研发和测试,职责很明确:

  • 接住用户提交的声明式对象
  • 表达用户的交付意图
  • 不暴露底层执行细节

用户在这一层真正描述的是:

  • 我要发什么
  • 发到哪
  • 用什么参数
  • 这次变更属于什么场景

5.2 平台控制层:负责把意图翻译成执行对象

声明式对象本身不会自动完成交付,它还需要一层平台控制面来把“用户意图”翻译成“底层执行对象”。

这一层是真正的平台大脑,它要做的事情包括:

  • 解析用户声明
  • 校验参数
  • 选择底层执行路径
  • 生成或驱动对应的执行对象
  • 统一感知执行状态
  • 把分散在底层系统里的状态再收回来

也正是因为这一层存在,平台对象和底层引擎才能真正解耦。

5.3 底层执行引擎层:继续承接具体执行,但不再直接暴露给用户

再往下一层,才是底层执行引擎。

在我们的场景里,这一层并不是单一工具,而是一个混合执行面:

  • Jenkins / GitLab Runner 继续承接 build 与分发
  • Tekton 可以承接部分流水线编排
  • ArgoCD 承接声明式同步与部署
  • Kubernetes 本身继续承接 rollout 与回滚状态

这一层仍然非常关键,因为所有真正的 build、sync、deploy、rollback,最终都要在这里落地。
但和旧模式不同的是,这一层不再应该直接成为用户入口,而更适合作为平台内部的执行引擎存在。

小结

所以回头看,把执行面拆成平台对象与底层引擎,真正解决的并不是“架构看起来更优雅”,而是让交付体系第一次从工具链拼接,开始进入平台对象驱动。

用户不应该直接操作底层引擎,而应该通过平台对象触发它们;平台真正要做的,是把意图翻译成执行,并把执行状态再统一收回来。

6. 为什么这条路不是替换,而是渐进式收敛

既然要走向 GitOps 和声明式交付,一个很自然的问题就是:是不是就意味着旧的 Jenkins 体系应该被整体替换掉?

在真实平台演进里,答案通常没有那么简单。至少对我们来说,这条路从来都不是“推倒重来”,而更像是一种渐进式收敛。

6.1 真实平台演进很少是一夜切换

真实世界的交付体系几乎从来不是这样演进的:

  • 旧系统今天停掉
  • 新系统明天全量上线
  • 从此全面 GitOps

更常见的其实是长期混合态:

  • Jenkins / GitLab Runner 仍然承接部分构建与分发
  • ArgoCD 开始承接声明式发布
  • Kubernetes 原生能力继续承接 rollout 与回滚
  • 平台对象逐步开始把这些能力收敛起来

这种混合态不是失败,而恰恰是平台演进最真实的样子。

6.2 旧能力不是负担,而是现有资产

如果只从“新技术替换旧技术”的角度看,旧链路很容易被描述成包袱。但从平台治理角度看,旧链路首先是资产。

比如 Jenkins 在构建流程组织上依然很有价值。
GitLab Runner 在 CI 上也依然承担着成熟能力。
Harbor、Kubernetes 原生 rollout、ArgoCD 的同步能力,也都各自解决了非常具体的问题。

所以问题并不是“旧系统要不要全部废弃”,而是:

  • 哪些能力应该继续保留
  • 哪些职责应该开始上移到平台对象层
  • 哪些入口应该对用户隐藏
  • 哪些状态应该重新被统一表达

6.3 GitOps 真正带来的,不是替换执行引擎,而是收敛交付语义

GitOps 在这里真正带来的变化,不一定是:

  • Jenkins 消失了
  • 所有执行都改由某个新引擎完成

它更重要的变化其实是:

  • 交付目标开始更声明式
  • 平台对象开始更稳定
  • 变更面开始收敛
  • 回滚边界开始更清晰
  • 审计边界开始更结构化

也就是说,GitOps 真正进入体系,首先体现在“语义收敛”上,而不是“工具替换”上。

小结

所以回头看,这条路真正值得强调的,不是“旧体系被新体系替代了”,而是交付体系开始从分散工具链,逐步收敛成一套更有平台语义的结构。

GitOps 在这里不是推倒重来的替换方案,而是让交付入口、目标状态和变更边界逐步收敛起来的治理方向。

7. deploy change 为什么必须有统一状态面

平台真正难管理的,从来不是“有没有执行动作”,而是“执行动作发生之后,平台还能不能把这次变化认出来、描述清楚、持续跟踪下去”。

这就是 deploy change 必须被当成统一对象来承接的原因。

7.1 旧模式里,一次 change 的状态天然是碎片化的

在旧交付模式下,一次发布虽然也能完成,但它的状态往往天然散落在多个系统中:

  • Jenkins 里有构建记录
  • GitLab Runner 里有某段流水线记录
  • Harbor 里有镜像信息
  • ArgoCD 里有同步状态
  • Kubernetes 里有 rollout 状态
  • 日志系统里还有额外执行痕迹

每一块信息都是真的,但它们没有自然围绕“这次 change”形成一个统一对象。

这会带来几个非常现实的问题:

  • 很难一眼看出这次变更当前处于哪个阶段
  • 很难统一回答这次变更关联了哪些底层对象
  • 失败时很难快速判断究竟卡在哪一层
  • 审计时需要人工拼接多个系统的记录

7.2 统一状态面,本质上是在让 change 成为平台对象

一旦我们说“要做统一状态面”,本质上其实是在说:

  • 平台应该把一次 deploy change 识别成一个独立对象
  • 这个对象应该有自己的生命周期
  • 平台应该持续感知它的当前阶段和最终结果

也就是说,平台需要尽量回答这些问题:

  • 这次 change 的目标是什么
  • 当前执行到哪一步了
  • 底层创建了哪些执行对象
  • 哪一步失败了
  • 当前是 waiting、running、successful 还是 failed
  • 它最终对哪些运行对象产生了影响

一旦这一层成立,交付就不再只是一些执行痕迹,而开始真正拥有对象语义。

7.3 为什么这对审计和 AI RCA 都很重要

统一状态面的第一个直接收益,就是审计会更清楚。

审计真正关心的,并不只是“谁点了按钮”,而是:

  • 什么时候发生了一次 change
  • 这次 change 想达成什么目标
  • 实际触发了哪些执行动作
  • 最终结果是什么
  • 有没有失败、回滚或中断

而从更长远的角度看,统一状态面还会直接影响 AI RCA。因为很多问题最终都绕不开这些判断:

  • 这次异常是不是发生在某次变更之后
  • 当时有没有发布动作
  • 变更影响了哪些服务
  • 哪个 change 最可能和当前故障相关

如果平台没有统一状态面,这些信息就会散落在多个系统里,AI 很难拿到一条清晰的 change 线索。

小结

所以回头看,deploy change 必须有统一状态面,并不是因为“多一个状态页看起来更完整”,而是因为平台只有把 change 承接成对象,才真正拥有了理解变化、审计变化和分析变化的能力。

统一状态面真正要解决的,不是“把几段状态放到一起看”,而是让一次 deploy change 第一次真正成为平台能理解的对象。

8. Demo 代码在这里承担什么角色

文中能够公开展示的代码,并不是生产交付平台本身,而是我在早期技术验证阶段抽出来的一组 Demo。

它的目的并不是复刻完整生产链路,而是验证一些更底层的抽象是否成立。换句话说,它更像一个“技术调用验证样机”,而不是一个可以直接代表真实投产系统的代码快照。

这份 Demo 最适合承担的,并不是“证明整条生产链路怎么跑”,而是证明下面这些关键设计方向是成立的:

  • 用户是否可以通过更低心智的声明式对象发起交付
  • 平台是否可以把用户入口和底层执行引擎解耦
  • 一次交付 change 的状态,是否可以被统一回收到平台对象上

也就是说,Demo 更像是这篇文章里的“抽象佐证”。

这种写法反而更稳,也更专业。因为它既没有回避实现事实,也没有模糊代码边界。

公开能展示的代码,不是生产交付平台本身,而是早期技术验证阶段用来验证“声明式入口”和“统一状态面”这两个抽象是否成立的 Demo。

9. 代码引用怎么规划

既然 Demo 在这篇文章里承担的是“抽象示意”而不是“生产实现证明”,那么代码引用就应该非常克制。

最合适的原则只有一条:

代码只证明“思路成立”,不证明“生产完整性”。

所以这篇最适合引用的,不是底层 controller 的具体 reconcile 细节,也不是 Tekton/ArgoCD 的具体拼装细节,而是对象模型本身。

正文里最适合引用的代码类型,通常只有这几类:

  • 用户入口对象定义
  • 平台流水线对象定义
  • 执行实例对象定义
  • status 字段或统一状态结构

我建议正文里的代码引用控制在 2 到 3 处最合适:

  • 第一处:用户入口对象
  • 第二处:平台执行对象
  • 第三处:状态字段

这样既能说明问题,又不会把整篇文章拖进 Demo 代码讲解。

另外,这篇其实更适合配一张“对象关系图”,而不是堆很多代码。因为它真正要说明的是:用户入口、平台对象和底层引擎之间,到底是怎么分层的。

10. 结语:GitOps 不是终点答案,而是交付治理方向

回头看这次交付体系演进,真正发生变化的,并不是“某个新工具替代了某个旧工具”,而是交付开始从“工具链拼接”逐步走向“平台对象驱动”。

在旧模式里,Jenkins 主导的交付体系已经很好地解决了自动化执行问题。构建、制品、发布、回滚,这些动作本身并不弱,甚至可以说已经足够成熟。

但随着平台逐步完成:

  • 运行时治理
  • ACK 容器平台承载
  • APISIX 入口流量治理
  • 指标、日志、链路三层可观测

交付体系如果仍然停留在“流水线执行得出去就算完成”的阶段,就会越来越显得割裂。因为平台其他层已经开始拥有对象边界、状态边界和治理边界,而交付这一层如果没有类似的抽象,就很难继续支撑平台往下演进。

也正因为这样,GitOps 在我们的场景里,真正带来的并不是一个“新工具替换旧工具”的故事,而是三件更深层的变化:

  • 用户入口开始从底层工具语义,收敛到更低心智负担的声明式对象
  • 平台开始把交付过程从若干执行痕迹,收敛成围绕 change 的统一对象和统一状态面
  • 交付体系开始为审计、问题追踪和未来 AI RCA 提供更结构化的上下文基础

从这个角度看,GitOps 对我们来说,不是某个孤立的产品答案,而是一种更适合平台长期演进的交付治理方向。

如果要用一句话来总结这次演进,我更愿意这样说:

GitOps 在这里不是为了替换 Jenkins,而是为了让交付体系第一次真正开始拥有声明边界、状态边界和审计边界。

延伸阅读

  • 下一篇我会继续写“从可观测到 AI RCA”,把 change、观测信号和根因分析进一步串起来
  • 这一篇和前面的 Nacos、ACK、APISIX、三层可观测一起看,会更容易看到整套平台治理是如何层层衔接的
0

评论区