阶段一 · CI 流水线与制品

CI/CD 核心概念

一句话总结

CI/CD 的本质是把"提交代码 → 上线运行"之间所有重复的人工动作,变成一条确定,可复现,自动触发的流水线;
CI 管"代码能不能合",CD 管"产物能不能上".

从一个发布日的灾难说起

先看没有 CI/CD 的团队是怎么发布的:

周五下午,三个人的功能要一起上线:

  1. 小 A 在本地 git merge 三个分支 → 手动解冲突,漏了一处
  2. 本地 mvn package 打出 jar → "在我机器上是好的"
  3. scp 到服务器,手动停服务,换 jar → 漏配了一个环境变量
  4. 重启,刷页面 → 500
  5. 回滚:翻聊天记录找上一个 jar 在哪 → 找不到了
  6. 加班到凌晨 → 周一线上还有残留 bug

这里每一步都依赖"人记得做,做对,做完整".人是不可靠的:会忘,会手滑,会"我以为别人做了".CI/CD 要解决的根本矛盾就是--软件交付的频率和复杂度在上升,而人工操作的可靠性是恒定的(且很低).

手工发布像每次做菜都临时回忆菜谱,凭手感放盐;
CI/CD 像把菜谱写成精确到克的程序,交给一台永远不走神的机器执行--同样的输入,永远得到同样的输出.

CI,持续交付,持续部署:三个容易混的词

"CI/CD"这个缩写其实塞了三个概念,很多人混着用.先把它们拆清楚,这是后面所有内容的坐标系.

CI:持续集成(Continuous Integration)

关注点:代码能不能安全地合进主干.

"集成"指的是把多个开发者的代码合并到一起.在没有 CI 的年代,大家各自在分支上开发几周,最后一次性合并--这叫"集成地狱":冲突堆积如山,谁也不知道合并后还能不能跑.

持续集成的主张是:频繁地(每天甚至每次提交)把代码合进主干,每次合并都自动跑构建和测试,让冲突和问题在产生的当天就暴露,而不是攒到最后.

开发者 push / 提 PR


自动触发 CI:
┌─────────────────────────────┐
│ 拉代码 → 编译 → 跑单测 → 静态检查 │
└─────────────────────────────┘

├── 全绿 → 允许合并
└── 有红 → 阻止合并,通知作者

注意:CI 的产出是一个判断("这次提交健不健康"),它本身不负责把代码送到任何地方.

CD 之一:持续交付(Continuous Delivery)

关注点:任何时刻,主干代码都能一键发布到生产--但"按不按那个键"由人决定.

持续交付在 CI 之后接管:CI 验证通过的代码,被自动构建成制品,自动部署到测试/预发环境,跑更重的测试.到这一步,产物已经"随时可上生产",但上生产这一下,需要人点一下"批准".

CD 之二:持续部署(Continuous Deployment)

关注点:连"批准"那一下也自动化--通过所有关卡的代码,自动上生产,无人工介入.

持续部署是持续交付的更激进版本:去掉了最后的人工审批.开发者合并代码后,只要一路绿灯,几分钟后就在生产环境跑起来了.

持续交付(Delivery)和持续部署(Deployment)的整条流水线几乎一样,唯一区别是生产发布前有没有人工审批关卡.Delivery = 自动到"可发布",发布按钮留给人;Deployment = 连按钮都自动按.绝大多数团队做到持续交付就足够了--把发布权留在人手里,是一种刻意保留的安全阀.

三者的边界(箭头表示自动,⏸ 表示人工):

持续集成        持续交付              持续部署
(CI) (Delivery) (Deployment)

提交代码 ──▶ 编译+测试 ──▶ 构建制品+部署到预发 ──▶ 生产
│ │
到这里都自动 ⏸ 人工批准 vs (无 ⏸,直接自动)

几个绕不开的术语

这些词会贯穿阶段一的全部四篇,先在这里建立准确认知.

制品(Artifact)

制品是构建过程的产物--可以被部署的那个东西.它是源代码经过编译/打包后的"成品",形态取决于技术栈:

技术栈 典型制品
Java .jar / .war
前端 打包后的静态资源(dist/)
Go 编译出的二进制
云原生(本系列重点) 容器镜像(Container Image)

制品有一条铁律:一次构建,到处部署(Build Once, Deploy Anywhere).同一个制品依次走过测试,预发,生产,中间绝不重新构建.原因很简单--如果每个环境都重新打包,你在生产跑的就不是测试验证过的那个东西了.这条原则在第 03 篇会反复出现.

制品就像出厂封箱,贴了唯一序列号的产品.质检(测试环境),仓库(预发),商店(生产)流转的是同一个箱子;没人会在每个环节拆开重造一个,否则序列号就失去意义了.

环境(Environment)

环境是运行制品的一套独立基础设施.典型的多环境流转:

dev(开发)  →  staging/pre(预发,尽量贴近生产)  →  prod(生产)
越靠右,越接近真实用户,出错代价越高,关卡越严

环境之间的差异(数据库地址,密钥,副本数等)不应该写死在制品里--制品是同一个,差异通过配置 注入.这正是第 06 篇 Helm / Kustomize 要解决的问题.

流水线与阶段(Pipeline & Stage)

流水线(Pipeline)是把整个交付过程拆成一串有序的阶段(Stage),前一阶段成功才进入下一阶段:

[ 检出代码 ] → [ 编译 ] → [ 单元测试 ] → [ 构建镜像 ] → [ 安全扫描 ] → [ 部署预发 ] → [ 部署生产 ]
↑ ↑
这些就是"阶段" 任一阶段失败,流水线中止

拆成阶段的好处是快速失败(Fail Fast):把又快又容易挂的检查(编译,单测)放前面,几十秒就能拦住大部分问题,不用等十几分钟跑完全部才发现编译都过不了.

质量门禁(Quality Gate)

质量门禁是流水线中的**"卡点"--不满足条件就拦下,不让继续往下走**.常见的门禁条件:

  • 单元测试必须全部通过
  • 测试覆盖率不低于 80%
  • 静态扫描不能有"严重"级别的问题
  • 镜像漏洞扫描不能有高危 CVE

门禁是 CI/CD 能"放心自动化"的前提:正因为有一道道自动关卡把关,我们才敢让代码无人工审查地往下流.第 04 篇整篇都在讲怎么设计这些门禁.

门禁不是越严越好

门禁定得太松形同虚设,定得太严则会天天误拦,逼得团队去"绕过门禁"(比如随手把覆盖率要求从 80% 调到 10%).好的门禁应该拦住真问题 而极少误伤--这是个需要持续校准的平衡,不是一次性配置.

怎么衡量 CI/CD 做得好不好:DORA 四个指标

引入 CI/CD 不是为了"显得先进",而是为了让交付又快又稳.业界公认的度量来自 Google 的 DORA(DevOps Research and Assessment)研究,四个指标分成两组,恰好对应"快"和"稳":

维度 指标 含义
速度(快) 部署频率
(Deployment Frequency) 多久能上线一次.精英团队按需随时部署(一天多次)
变更前置时间
(Lead Time for Changes) 一行代码从提交到上线要多久.精英团队 < 1 小时
稳定(稳) 变更失败率
(Change Failure Rate) 上线后导致故障的比例.精英团队 < 15%
故障恢复时间
(Time to Restore) 出故障后多久能恢复.精英团队 < 1 小时

直觉上会觉得"发布越频繁越容易出事",但 DORA 研究的核心发现恰恰相反:速度和稳定性正相关.原因是--频繁的小批量发布,每次改动小,好排查,易回滚;而攒一大坨"季度大版本",一旦出事根本不知道是哪行代码的锅.CI/CD 让"小步快跑"成为可能,这正是它同时改善四个指标的底层逻辑.

把整个系列串起来:一张全景图

阶段一到阶段三的八篇笔记,其实就是在逐段填充下面这条流水线.现在你看不懂细节没关系,这张图是用来"挂知识"的钩子:

┌────────────────┐
│ 开发者提交代码 / 提 PR │
└────────────────┘


┌──────────────────────────────────┐
│ 基础设施即代码: 环境本身也声明式管理<br/>(第 08 篇) │
└──────────────────────────────────┘
┌─────────────────────────────────────────────────────┐
│ CI: 编译 + 单测 + 静态检查<br/>(本篇 + 第 02 篇 GitHub Actions) │
└─────────────────────────────────────────────────────┘


┌──────────────────────────────┐
│ 构建容器镜像 + 推送制品仓库<br/>(第 03 篇) │
└──────────────────────────────┘


┌───────────────────────────────┐
│ 质量门禁: 覆盖率 + 安全扫描<br/>(第 04 篇) │
└───────────────────────────────┘


┌─────────────────────────────────────────────────┐
│ GitOps: 把期望状态写进 Git<br/>ArgoCD 同步到集群(第 05-06 篇) │
└─────────────────────────────────────────────────┘


┌──────────────────────────────┐
│ 渐进式交付: 金丝雀 / 蓝绿<br/>(第 07 篇) │
└──────────────────────────────┘


┌──────────┐
│ 生产环境运行 │
└──────────┘

本篇(01)负责的是建立词汇和心智模型:CI vs CD,制品,环境,阶段,门禁,DORA.后面每一篇都会反复用到这些词.

快速回顾

  • CI(持续集成):频繁合并 + 每次合并自动构建测试,产出"代码健不健康"的判断,不负责部署
  • 持续交付 vs 持续部署:整条流水线几乎相同,差别只在生产发布前有没有人工审批;多数团队做到持续交付即可
  • 制品:可部署的构建产物(云原生场景下就是容器镜像),遵循"一次构建,到处部署"
  • 流水线 = 一串阶段,设计原则是快速失败;质量门禁是阶段间的卡点,是敢于自动化的前提
  • DORA 四指标(部署频率/前置时间/失败率/恢复时间)衡量交付的"快"与"稳",且二者正相关

CI/CD 和 DevOps 是一回事吗?

不是.DevOps 是一种文化和方法论--主张开发(Dev)和运维(Ops)打破墙,共担责任. CI/CD 是落地 DevOps 的核心技术手段之一.可以说 CI/CD 是 DevOps 的"自动化引擎",但 DevOps 还包含协作方式,监控文化,责任划分等技术之外的东西.

小项目,个人项目也需要 CI/CD 吗?

需要,而且成本很低.哪怕只是配一个"每次 push 自动跑测试 + 构建"的 GitHub Actions(第 02 篇),就能省下大量"提交后才发现编译挂了"的来回. CI/CD 的收益不取决于团队大小,而取决于你提交代码的频率--只要你还在持续改代码,它就值得.

动手练习

  1. 画交付流程:找一个你熟悉的项目(或公司项目),画出它当前"从提交代码到上线"的完整步骤,标出哪些是人工,哪些是自动.
  2. 判断成熟度:判断这个项目目前处于哪个阶段:纯手工 / 有 CI / 持续交付 / 持续部署?
  3. 复盘发布事故:用本篇的术语描述一次你经历过的发布事故:它发生在哪个"阶段"?如果有合适的"质量门禁",能否拦住它?
  4. 估算 DORA 指标:估算这个项目的 DORA 四指标各自大概是什么量级(哪怕只是数量级),找出最拖后腿的那一个.