名词解释教学工作区 · 课程 0008 · 形态 对比组 · 约 6 分钟 · 前置:0006 · 巡检器 · 相关:0004 · Node.js / npm / pnpm · 2026-10-01
CI 与 CD:自动化跑到哪一步,最后一下谁按
你能做到:听到「等 CI 绿了再合并」「CD 还没配」,能立刻说出它停在哪一层;
再被问「你们算持续交付还是持续部署」,你能指出这两个词只差一件事 —— 上线前有没有人按一下。
1 | 定义
持续集成(Continuous Integration,CI):
每个人把改动频繁合进同一条主线,每一次合并都由自动化在一台干净机器上跑一遍构建与测试,结果立刻反馈给提交的人。
每做完一道菜先尝一口:咸了淡了当场就知道,不用等整桌菜上齐,才发现有一道没法吃。
持续交付(Continuous Delivery,CD):
在持续集成之上再往前一步:检查通过后自动把这一版打包成随时可发布的状态,真正送上生产那一下由人决定。
菜装好盘、盖好盖,随时都能端上桌;至于端不端、什么时候端,你说了算。
持续部署(Continuous Deployment):
检查通过后不再有人工确认,自动化直接把新版本送上生产环境,用户当场用到它。
做好了直接上桌,中间没有人再问一句「现在上吗」。
三个词共用同一条流水线,只在两个地方分岔:自动化停在哪一步、最后一下谁按。
2 | 它们解决什么麻烦
三个词面对的是同一件事:改动越来越多、越来越碎,而把它们合到一起、送上线上这一步仍然靠人。
- ① 改动攒着不合,最后一合就炸。各改各的,谁也不早知道别人的改动会不会把自己弄崩;攒到发布那天才把几周的分支合到一起,冲突和故障一起爆出来。
- ② 人肉发布每次手法都不一样。手工打包、手工填参数、手工传服务器,漏一步、抄错一个值就出事故,而且没法复现上一次是怎么发成功的。
- ③ 出了问题太晚才知道。等用户先发现,回滚、定位、解释都要花时间;能提前到提交后几分钟发现的,代价差着一个量级。
- ④ 发布窗口本身也在花人的时间。攒批发布、挑低峰上线、上线后盯着大盘守半小时 —— 都是在用人的时间换「少出事」。
3 | 特征矩阵
三行之间真正变的只有两列:自动化跑到哪一步、最后一下谁按;其余几列问的是同一件事被放到了什么位置。
| 名词 | 什么时候跑 | 谁按最后一下 | 自动化到哪一步 | 出问题谁先知道 | 需要什么前提 |
| 持续集成(CI) | 每次提交、每个合并请求 | 没人按 —— 它不碰生产 | 构建 + 测试 + 各类检查 | 提交的人,几分钟内 | 测试本身可信、跑得够快 |
| 持续交付 | 同上,一路跑到「可发布」 | 人:上线前确认一次 | 到「随时可发布」,外加一键发布 | 提交的人 + 发布负责人 | 上面全要,还要能一键回滚 |
| 持续部署 | 同上,一直跑到生产 | 没人按 | 到「自动进生产」为止 | 监控与告警,而不是人 | 回滚、监控、开关都得先到位 |
往上走一层不是换一套工具,而是把上一步的前提再加一层:CI 只要求测试可信;到持续交付得有回滚;到持续部署,回滚、监控、开关、数据迁移缺一条都不行。
4 | 各自怎么做
不管做到哪一层,跑的都是同一条流水线(pipeline),顺序固定:
触发推送到主线、开合并请求、打标签、定时
->
构建干净机器上装依赖、编译、打包
->
测试单元测试、集成测试、静态检查
->
产物带版本号、能整块搬走的那一份东西
->
发布人按一下,或者直接上生产
- ① 触发:什么时候跑。推送到主线、开一个合并请求、打一个标签、或者按点定时,任一发生就自动起一趟;这一条写在平台配置文件里(如 GitHub Actions 的
on:、GitLab CI 的 rules:)。
- ② 构建:在一台干净机器上从零装好、编出能跑的东西。拉代码、按锁文件装依赖(包管理器如 npm)、再交给构建工具排队执行,「编译」那一步就是编译器在干;机器是临时起的,跑完就销毁,所以「在我机器上是好的」在这里不成立。
- ③ 测试:把平时手动跑的那套交给机器,每次合并都跑。单元测试、集成测试、静态检查都在这一步;需要造数据的地方用测试夹具,让每次跑起来的前置条件都一样。
- ④ 产物:把构建结果固定下来,后面拿它去部署。压缩包、容器镜像、安装包都算,存进制品库并带上版本号;下一趟部署直接取这个产物、不再重新构建,才能保证「测过的就是上线的那个」。
- ⑤ 发布:把产物送到线上。产物是一堆静态文件时,构建完直接交给静态托管发出去,这份构建就是 SSG 那一类做法;是常驻服务时,则推给服务器换一个版本。
- ⑥ 回滚(rollback)与灰度(canary):发得出去,还要收得回来。新版本先给一小部分流量试,对外那份接口还照常由老版本供着,指标正常再加量;不对劲就把流量切回上一个版本 —— 一键回滚是持续部署的第一件护具。
- ⑦ 特性开关(feature flag):把「上线」和「打开」拆成两件事。代码先上生产但功能不开,确认没问题再打开;出事时把开关关掉,比回滚一整版更快。
- ⑧ 缓存让这一趟跑得快。依赖和构建中间结果缓存起来,下一趟省掉大部分重复动作;缓存命中率一低,流水线就慢,反馈也跟着慢。
- ⑨ 判红绿看退出码。一条命令跑完回一个数字:0 是过,非 0 是不过,前一步非 0 后面就停 —— 流水线里跑的每一步,说到底都是一串命令行界面(CLI)指令,靠它回话;一致性检查那类工具也是同一个规矩(见 0006 · 巡检器)。
三个词的差别只落在最后一段:持续交付在「发布」前面挂一个「必须人工批准」,不挂,它就成了持续部署。平台可选 GitHub Actions、GitLab CI、Jenkins,配置写法不同,流水线这几段是一样的。
5 | 各自的代价
- ① CI 慢,反馈就慢。一趟跑二十分钟,提交的人早去干别的了,红了他也过半天才回来改;检查项只加不减,最后没人愿意等 —— 慢的检查会被绕过。
- ② 不可信的 CI 比没有更糟。测试时红时绿(偶发失败),大家就学会「重跑一遍就好」,真问题也一起被重跑掉;那时候那行绿灯不再说明任何事。
- ③ 持续交付多一步人工,就多一次「谁来按」。发布责任要落到人头上,审批、窗口期、值班都得排;说好的「随时能发」,常常因为等批准变成了定期发。
- ④ 持续部署把出错半径放大到所有人。测试过了就上线,一道坏提交几分钟内就到用户面前;回滚、监控、开关、数据迁移缺一条,自动上线就只是自动出事。
- ⑤ 流水线自己也要人养。依赖升级、临时机器镜像过期、平台配置改动、跑得越来越慢,都得有人看;它是一份要长期维护的配置,不是配一次就完事的开关。
6 | 区分使用场景
先看现在能做到哪一层,再看值不值得往下走:
- ① 几个人、没有专职运维 → 先只做 CI。每次提交自动构建与测试,已经能挡掉大部分「合进去才发现坏了」;这一层成本最小,见效最快。
- ② 面向用户的站点、上线要跟运营打招呼 → 做持续交付。自动化跑到「随时可发布」,上不上线那一下留给人,好配合活动时间与公告。
- ③ 内部服务、能灰度、能一键回滚 → 可以做持续部署。没有发布窗口要守,改动小步快跑,出问题靠监控与回滚兜住。
- ④ 受合规、审批或窗口期约束 → 只做持续交付。那一次人工确认不是效率问题,是流程要求;自动化停在「准备好」正合适。
- ⑤ 测试本身不稳、回滚从没练过 → 先停在 CI。往下走的每一步都踩在「上一步的前提已备好」上,前提没到位,越自动越危险。
一句话:自动化到哪一层,由你能不能接住它的出错决定,而不是由工具决定。
7 | 常见误解
- ① 「CI 就是自动部署。」CI 只管到检查这一步,不碰生产环境;把代码送上生产是另一层的事。看到「流水线绿了」,只说明这次合并没把主线弄坏。
- ② 「只有大公司才需要。」门槛已经低到一个人也能用:仓库里放一份配置,推送后云端机器跑一遍构建与测试。人越少,越没人替你人工看一遍 —— 收益反而更直接。
- ③ 「有流水线就不会出错。」流水线只证明它配置里写的那几项过了;没写的它一概不管,写错了它也不会告诉你;真上线之后出问题,还得靠监控与回滚。
- ④ 「持续交付和持续部署是一回事。」两者只差一次人工确认:留着是人按,去掉是机器按。前面那一段(构建、测试、打包)完全一样,所以从交付走到部署,通常只是删掉一条「需要批准」。
8 | 练习
三个场景,每题只落在四个答案之一;选完立刻看到它停在哪一步。
1. 每次推送到主线,云端机器自动重跑构建与测试,结果发回给提交的人;这一趟跑完,没有任何动作碰生产环境。
对。自动化停在「检查」这一步、不碰生产环境,就是持续集成;它换来的是每次合并当场知道坏没坏,而不是发布那天一起爆。也别忘了它还有另一半:大家得真的频繁合进同一条主线。
2. 检查通过后自动打好包、放到待发布的位置,随时都能上;真正上线由发布负责人点一下确认。
对。自动化跑到「随时可发布」、最后那一下留给人,就是持续交付;它比 CI 多出来的前提是能一键回滚 —— 发得出去,也要收得回来。
3. 检查通过几分钟后,线上自己换成了新版本,全程没有人点过按钮;出没出问题由监控告警说话。
对。人工确认那一步也被去掉、自动化一直跑到生产,就是持续部署;它的前提是回滚、监控、特性开关都到位 —— 缺一条,自动上线就变成自动出事。