Harness 中的操作原子链:全有或全无执行1. 核心概念:从数据库ACID到CI/CD交付链的原子性1.1 问题背景作为一名在科技行业摸爬滚打了15年的软件架构师,我见过太多因为交付流程中途失败导致生产环境陷入“半吊子”状态的噩梦:案例1(金融行业):某大型银行的新交易系统金丝雀部署到第3步(注入5%流量、启动健康检查)时,突发网络分区导致健康检查失败。原计划的金丝雀回滚流程因为操作序列没有绑定原子性,执行到第2步(暂停流量注入)时又因Harness控制器连接K8s集群超时中断。最终结果是:K8s集群里同时残留了新旧版本的Deployment,5%流量卡在旧版本无法退出,新版本健康检查探针没有被正确清理,DevOps团队花了4小时27分钟才通过手动逐Pod回滚、重新配置Ingress和探针的方式恢复生产。案例2(电商行业):某头部电商平台的618预热前,在Harness里执行“代码构建 → 镜像推送到ECR → 更新Prod的Helm Chart → 触发CloudWatch告警规则同步更新”的流水线。结果代码构建超时(实际成功99%但因为测试覆盖率统计插件的Bug被判定失败),流水线自动回滚,但只回滚了“更新Helm Chart”这一步——构建的临时镜像(因为没有绑定ECR清理与构建失败的原子性)留在了ECR的特定分支仓库,CloudWatch的临时告警规则(同步更新失败但创建成功)也没有被删除。预热期间,运维团队清理垃圾镜像和告警规则又花了不少精力,更糟的是,临时镜像的名称和正式预热版的名称混淆,导致有一台测试环境的Pod意外拉取了这个半成功的镜像。这些案例的核心问题是什么?是交付流程的各个操作环节之间缺乏“命运共同体”的绑定机制——传统的CI/CD平台(包括早期的Jenkins、GitLab CI/CD,甚至是Harness 1.x的基础版本)虽然提供了回滚步骤,但这些回滚步骤通常只是线性地放在失败分支里,没有对“正向操作序列”和“反向回滚序列”做原子性的事务封装:一旦反向回滚序列本身也失败,或者中间某个正向操作没有对应的反向回滚操作,生产环境就会留下“不可撤销的半状态”。1.2 问题描述我们把CI/CD平台中的“一组有因果依赖、必须要么全部成功执行、要么全部反向撤销到执行前的初始状态的操作集合”称为操作原子链(Atomic Operation Chain, AOC)。针对Harness平台,操作原子链需要解决的具体问题可以拆解为以下5个维度:问题维度具体描述因果依赖的显式绑定如何在Harness的Pipeline/YAML定义中,明确标识哪些Step/Stage属于同一个原子链?它们的执行顺序(正向)和撤销顺序(反向)是怎样的?全状态的可撤销性每个正向操作必须提供对应的、幂等的反向撤销操作——幂等性保证了即使反向操作多次执行,也不会产生副作用;可撤销性保证了反向操作能够100%还原正向操作带来的所有状态变更(包括基础设施、配置、数据、流量等)。执行与回滚的事务完整性原子链的执行过程必须像数据库的ACID事务一样:1.Atomicity(原子性):要么全正向执行,要么全反向撤销;2.Consistency(一致性):执行前/撤销后,系统必须处于定义好的“合法状态”;3.Isolation(隔离性,可选但重要):在原子链执行期间,外部系统(比如同一K8s命名空间的其他Pipeline、手动操作)对相关资源的访问需要被限制或协调;4.Durability(持久性):原子链的执行状态(包括每个Step的执行时间、输入输出、状态变更日志)必须持久化存储,以便在Harness控制器重启后恢复执行或回滚。失败场景的全面覆盖原子链需要处理哪些类型的失败?1.Step本身的业务失败(比如构建失败、健康检查失败、K8s Deployment更新超时);2.Step执行的基础设施失败(比如Harness Delegate掉线、K8s集群节点宕机、ECR连接中断);3.外部系统的意外变更(比如在原子链执行期间,有人手动修改了Ingress配置)。可观测性与可调试性当原子链执行或回滚失败时,如何快速定位失败的Step、查看该Step的状态变更日志、模拟反向操作的执行过程?1.3 问题解决:Harness操作原子链的核心设计思想Harness从2.x版本开始(特别是Harness NextGen,也就是现在的主流版本Harness Platform),引入了一套完整的原子性事务框架(Atomic Transaction Framework)来解决上述问题——这套框架的核心设计思想可以总结为以下3句话:1. 一切原子链都是“事务上下文(Transaction Context)”下的双向Step序列。2. 每个Step必须是“可撤销的、幂等的、可持久化的Step规范(Step Specification)”的实例。3. 原子链的执行状态由“事务日志(Transaction Log)”和“状态快照(State Snapshot)”共同保障。为了让大家更直观地理解这3句话,我们可以先看一下Harness操作原子链的整体架构示意图(Mermaid ER图 + 交互关系图),然后在后续章节逐一展开讲解。1.4 概念结构与核心要素组成Harness操作原子链的核心要素可以分为4层结构,从上到下依次是:1.4.1 用户定义层(Pipeline/YAML层)这一层是用户直接接触的部分,用户可以通过Harness Platform的UI或者编写YAML文件来定义:原子链的范围:通过atomic: true关键字或者UI中的“Toggle Atomic Group”开关,将一组连续的Step(或Stage,但Stage通常太粗粒度,不推荐作为原子链的基本单位)绑定成一个原子组(Atomic Group)。反向撤销的配置:每个Step可以配置rollbackSteps(自定义反向撤销操作),如果不配置,Harness会自动调用该Step类型默认的defaultRollback方法。事务的边界条件:比如原子链执行的超时时间、允许的重试次数(针对整个原子链,而非单个Step)、是否允许外部系统对相关资源的访问(隔离级别配置)。1.4.2 事务管理核心层(Harness Transaction Manager)这一层是整个原子链框架的“大脑”,负责:创建/销毁事务上下文:每个原子链在执行前,Transaction Manager会为其分配一个唯一的transactionId,并创建一个包含以下信息的事务上下文对象:transactionId:全局唯一标识符,用于关联事务日志和状态快照。currentStepIndex:当前正在执行(或回滚)的Step在原子链双向序列中的索引。transactionPhase:事务的当前阶段,包括INITIALIZING(初始化)、EXECUTING_FORWARD(正向执行)、EXECUTING_ROLLBACK(反向回滚)、COMMITTED(提交,全正向成功)、ROLLED_BACK(回滚完成,全反向撤销)、FAILED_TO_ROLLBACK(回滚失败,需要人工干预)。stepExecutionResults:每个Step正向执行的输入输出、状态变更日志、执行时间戳等信息。stateSnapshotBeforeTransaction:原子链执行前,相关资源的状态快照(由Step规范定义需要快照哪些资源)。调度双向Step序列:根据事务的当前阶段,调度执行正向Step序列(EXECUTING_FORWARD)或反向Step序列(EXECUTING_ROLLBACK)——反向Step序列的顺序是正向Step序列的逆序(比如正向Step1→Step2→Step3,反向就是Rollback3→Rollback2→Rollback1)。处理失败场景:如果正向Step序列中任意一个Step失败(业务失败或基础设施失败),Transaction Manager会立即切换到EXECUTING_ROLLBACK阶段,开始执行逆序的反向Step序列。如果反向Step序列中任意一个Step失败,Transaction Manager会将事务状态切换到FAILED_TO_ROLLBACK,并触发告警(邮件、Slack、PagerDuty等),同时保留所有状态变更日志和状态快照,以便人工干预。持久化事务状态:定期将事务上下文对象写入到Harness的分布式事务日志存储(Distributed Transaction Log Store,比如基于MongoDB或PostgreSQL的ACID存储)中——写入频率可以配置(比如每执行完一个Step就写入,或者每10秒写入一次),以保证在Harness控制器重启后,能够从最后一次写入的状态恢复执行或回滚。1.4.3 Step规范与执行层(Harness Step Specification Step Executor)这一层是整个原子链框架的“手脚”,负责:定义Step的规范:每个Step类型(比如K8sRollingDeploy、ECRPush、HelmUpgrade、HTTP)都必须实现Harness定义的AtomicStep接口,该接口包含以下核心方法:execute(input: StepInput, context: TransactionContext): StepOutput:正向执行方法,必须是幂等的(多次执行的结果与一次执行的结果相同)。defaultRollback(input: StepInput, context: TransactionContext): StepOutput:默认的反向撤销方法,必须是幂等的,并且能够100%还原execute方法带来的所有状态变更。captureStateSnapshot(context: TransactionContext): StateSnapshot:捕获原子链执行前相关资源的状态快照方法——状态快照可以是轻量级的(比如K8s Deployment的yaml配置、Ingress的yaml配置),也可以是重量级的(比如数据库的全量备份,但Harness不推荐在原子链中捕获重量级的状态快照,因为会影响执行效率)。validateStateConsistency(beforeSnapshot: StateSnapshot, afterRollbackSnapshot: StateSnapshot, context: TransactionContext): boolean:验证撤销后的状态是否与执行前的状态一致的方法——如果不一致,Transaction Manager会将事务状态切换到FAILED_TO_ROLLBACK。执行Step:Harness Delegate(部署在用户基础设施中的代理,负责与用户的基础设施交互)会根据Transaction Manager的调度,执行Step的execute或defaultRollback方法,并将执行结果返回给Transaction Manager。1.4.4 存储与可观测性层(Harness Transaction Log Store Observability Stack)这一层是整个原子链框架的“记忆器官”和“眼睛”,负责:持久化存储:分布式事务日志存储:存储所有原子链的事务上下文对象、Step执行结果、状态变更日志——必须是ACID兼容的分布式存储,比如MongoDB 4.0+(支持多文档事务)、PostgreSQL 11+(支持分布式事务 via 2PC或3PC,但Harness更倾向于使用MongoDB的多文档事务,因为更灵活)。状态快照存储:存储原子链执行前的状态快照——可以是分布式对象存储(比如AWS S3、GCP GCS、阿里云OSS),也可以是事务日志存储的一部分(如果是轻量级的状态快照)。可观测性:事务状态仪表盘:在Harness Platform的UI中,提供专门的“Atomic Transaction Dashboard”,展示所有原子链的执行状态、当前阶段、执行时间、失败原因等信息。Step执行日志查看:支持查看每个Step正向执行和反向回滚的详细日志(包括标准输出、标准错误、与用户基础设施的交互日志)。状态变更对比:支持对比原子链执行前、正向执行中途、反向回滚中途、反向回滚完成后的状态快照,直观地展示状态变更情况。告警机制:支持配置原子链执行失败、回滚失败、执行超时等场景的告警,告警方式包括邮件、Slack、PagerDuty、Webhook等。1.5 概念之间的关系:ER实体关系图与交互关系图为了更清晰地展示Harness操作原子链核心要素之间的关系,我们可以使用Mermaid语法绘制ER实体关系图和交互关系图。1.5.1 ER实体关系图containsforward executes (ordered)rollback executes (reverse ordered)implementscreates one per executionstoresstores before/aftermanagespersists/readsreferences (optional)executesreports results toPIPELINEATOMIC_GROUPATOMIC_STEPSTEP_SPECIFICATIONTRANSACTION_CONTEXTSTEP_EXECUTION_RESULTSTATE_SNAPSHOTTRANSACTION_MANAGERTRANSACTION_LOG_STORESTATE_SNAPSHOT_STORESTEP_EXECUTORER实体关系图的核心说明:PIPELINE:用户定义的CI/CD流水线,包含多个Stage和Step。ATOMIC_GROUP:用户定义的原子组,包含一组连续的ATOMIC_STEP,是原子链的基本单位。ATOMIC_STEP:原子组中的Step,必须实现STEP_SPECIFICATION接口。STEP_SPECIFICATION:Harness定义的AtomicStep接口,包含execute、defaultRollback、captureStateSnapshot、validateStateConsistency等核心方法。TRANSACTION_CONTEXT:Transaction Manager为每个原子组的执行创建的事务上下文对象,包含transactionId、currentStepIndex、transactionPhase、stepExecutionResults、stateSnapshotBeforeTransaction等信息。STEP_EXECUTION_RESULT:每个ATOMIC_STEP正向执行或反向回滚的结果,包含输入输出、状态变更日志、执行时间戳、成功/失败标志等信息。STATE_SNAPSHOT:原子组执行前、正向执行中途、反向回滚中途、反向回滚完成后的状态快照,由STEP_SPECIFICATION的captureStateSnapshot方法捕获。TRANSACTION_MANAGER:整个原子链框架的大脑,负责管理TRANSACTION_CONTEXT、调度ATOMIC_STEP的执行、处理失败场景、持久化事务状态。TRANSACTION_LOG_STORE:ACID兼容的分布式存储,用于存储TRANSACTION_CONTEXT和STEP_EXECUTION_RESULT。STATE_SNAPSHOT_STORE:分布式对象存储或事务日志存储的一部分,用于存储STATE_SNAPSHOT。STEP_EXECUTOR:部署在用户基础设施中的Harness Delegate的一部分,负责执行ATOMIC_STEP的execute或defaultRollback方法,并将结果返回给TRANSACTION_MANAGER。1.5.2 交互关系图(正向执行成功场景)User Infrastructure (K8s/ECR/Helm etc.)Harness Step Executor (Delegate)State Snapshot StoreTransaction Log StoreHarness Transaction ManagerHarness Platform UI/YAML ParserUser/Pipeline TriggerUser Infrastructure (K8s/ECR/Helm etc.)Harness Step Executor (Delegate)State Snapshot StoreTransaction Log StoreHarness Transaction ManagerHarness Platform UI/YAML ParserUser/Pipeline Trigger重复上述Step1的流程,执行Step2、Step3...StepN触发包含原子组的Pipeline解析YAML,发送原子组执行请求(包含Step列表、配置)生成唯一的transactionId创建初始的TRANSACTION_CONTEXT(phase=INITIALIZING)持久化初始TRANSACTION_CONTEXT发送Step1的captureStateSnapshot请求(transactionId=xxx)调用API获取Step1相关资源的初始状态返回初始状态存储Step1的初始状态到全局事务快照返回Step1的captureStateSnapshot成功响应更新TRANSACTION_CONTEXT(phase=EXECUTING_FORWARD, currentStepIndex=0, stateSnapshotBeforeTransaction=xxx)持久化更新后的TRANSACTION_CONTEXT发送Step1的execute请求(transactionId=xxx, input=xxx)调用API执行Step1的正向操作(比如创建K8s Deployment)返回Step1的正向操作结果返回Step1的execute成功响应(包含output=xxx, stateChangeLog=xxx)更新TRANSACTION_CONTEXT(currentStepIndex=1, stepExecutionResults[0]=xxx)持久化更新后的TRANSACTION_CONTEXT所有Step正向执行成功,更新TRANSACTION_CONTEXT(phase=COMMITTED)持久化最终TRANSACTION_CONTEXT返回原子组执行成功响应展示原子组执行成功的结果1.5.3 交互关系图(正向执行失败,反向回滚成功场景)User Infrastructure (K8s/ECR/Helm etc.)Harness Step Executor (Delegate)State Snapshot StoreTransaction Log StoreHarness Transaction ManagerHarness Platform UI/YAML ParserUser/Pipeline TriggerUser Infrastructure (K8s/ECR/Helm etc.)Harness Step Executor (Delegate)State Snapshot StoreTransaction Log StoreHarness Transaction ManagerHarness Platform UI/YAML ParserUser/Pipeline Trigger