什么是 CI/CD?持续集成、持续交付、持续部署有什么区别?流水线怎么设计?
简化版
**CI/CD 是一套「让代码从提交到上线自动化、频繁、可靠」的工程实践,包含三个层层递进的概念:① CI(Continuous Integration,持续集成)——开发者频繁地(每天多次)把代码合并到主干,每次合并都自动触发「构建 + 测试」,尽早发现集成问题;② CD(Continuous Delivery,持续交付)——在 CI 基础上,自动把通过测试的代码打包成「可随时部署的制品」,让它「随时能一键上线」(但上生产由人工点一下确认);③ CD(Continuous Deployment,持续部署)——比持续交付更进一步,通过测试后「全自动部署到生产」,无需人工干预。**三者关系:持续集成(自动构建测试)⊂ 持续交付(+ 自动到「可部署」,上线人工确认)⊂ 持续部署(+ 全自动上生产);区别就在「最后一步上生产是人工点还是全自动」。流水线(Pipeline)设计:把整个过程拆成一串自动执行的「阶段(stage)」,典型:拉代码 → 编译构建 → 单元测试 → 代码扫描(质量/安全)→ 打包制品 → 部署到测试环境 → 集成/验收测试 → 部署到生产,任一阶段失败就中断、通知。核心记忆:CI 频繁集成自动构建测试、持续交付到「随时可部署」(上线人工确认)、持续部署全自动上生产;流水线是一串自动阶段(构建→测试→扫描→打包→部署),失败即停。
详细版
CI/CD 三个概念:
| 概念 | 英文 | 做什么 | 最后一步 |
|---|---|---|---|
| 持续集成 | Continuous Integration | 频繁合并主干 + 自动构建测试 | 到「测试通过」 |
| 持续交付 | Continuous Delivery | + 自动打成「可部署制品」 | 上生产人工确认 |
| 持续部署 | Continuous Deployment | + 全自动部署到生产 | 全自动上线 |
三者是递进包含关系:CI ⊂ 持续交付 ⊂ 持续部署(区别在「上生产是人工还是自动」)。
# GitHub Actions 流水线示例
name: CI/CD Pipeline
on: [push] # 每次 push 触发
jobs:
build-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4 # ① 拉代码
- uses: actions/setup-java@v4 # 环境
with: { java-version: '17' }
- run: mvn compile # ② 编译
- run: mvn test # ③ 单元测试
- run: mvn verify sonar:sonar # ④ 代码扫描
- run: mvn package # ⑤ 打包
- uses: actions/upload-artifact@v4 # 上传制品
with: { path: target/*.jar }
deploy:
needs: build-test # 依赖上一步成功
steps:
- run: ./deploy.sh test # ⑥ 部署测试环境
# 持续交付:这里等人工确认再上生产
# 持续部署:自动继续 ./deploy.sh prod
⚠️ CI/CD 三个词最容易混,抓住一句话就够:「持续集成」管到『测试通过』、「持续交付」管到『随时能一键上线的制品』(上生产是人点的)、「持续部署」连『上生产』都自动了——区别只在最后一步上生产是人工还是全自动。很多团队说自己做了 CI/CD,其实只做到「持续集成」(自动构建测试)+「持续交付」(自动打包、人工点上线),真正的「持续部署」(提交到生产全自动、无人工)需要非常完善的自动化测试和监控回滚能力才敢做。CI/CD 的核心价值是「小步快跑 + 快速反馈」:每次小改动都自动验证(构建、测试、扫描),问题在提交后几分钟就暴露(而不是攒一个月集成时炸一堆),出问题范围小、好定位;上线频繁而小、风险低、可快速回滚。
完整版教学
一、CI/CD 解决什么问题
先理解 CI/CD 为什么出现:
没有 CI/CD 的痛点:
① 集成地狱(Integration Hell):
各人在自己分支开发几周,最后一起合并
→ 冲突一大堆、集成时炸一堆问题、难定位
② 手动构建部署:
人工编译、跑测试、打包、上传、部署
→ 慢、易出错、不可重复("在我机器上好的")
③ 上线风险大:
攒一大批改动一次上线
→ 出问题范围大、难回滚、难定位是哪个改动
CI/CD 的解决思路——自动化 + 频繁 + 快速反馈:
① 频繁集成(每天多次合主干)→ 小步,冲突小
② 自动化(构建/测试/部署全自动)→ 快、可重复、不出错
③ 快速反馈(每次提交几分钟内知道好坏)→ 早发现早修
核心价值:
小步快跑 + 快速反馈
→ 问题早暴露(提交后几分钟,不是集成时)
→ 出问题范围小、好定位、好回滚
→ 上线频繁而小、风险低
所以 CI/CD 解决集成地狱+手动易错+上线风险,靠自动化+频繁+快速反馈
没有 CI/CD 的痛点:① 集成地狱(各人分支开发几周最后一起合、冲突炸一堆)、② 手动构建部署(慢、易错、不可重复、“在我机器上好的”)、③ 上线风险大(攒一批一次上线、出问题范围大难回滚)。CI/CD 的解决思路——自动化 + 频繁 + 快速反馈:① 频繁集成(每天多次合主干、小步冲突小)、② 自动化(构建/测试/部署全自动、快可重复不出错)、③ 快速反馈(每次提交几分钟知道好坏、早发现早修)。核心价值:小步快跑 + 快速反馈(问题早暴露、范围小好定位、上线频繁而小风险低)。理解「CI/CD 解决:集成地狱(分支久合冲突炸)+手动易错不可重复+上线风险大;思路自动化+频繁+快速反馈;价值小步快跑+快速反馈(问题早暴露、范围小、上线频繁风险低)」,就理解了 CI/CD 解决什么问题。
二、持续集成(CI)
理解持续集成:
持续集成(Continuous Integration,CI):
开发者频繁地(每天多次)把代码合并到主干
每次合并都自动触发"构建 + 测试"
→ 尽早发现集成问题(不攒着)
CI 的关键实践:
① 频繁提交/合并主干(每天多次,别憋大分支)
② 每次提交自动触发流水线(构建 + 测试)
③ 保持主干"始终可构建、测试通过"(绿色)
→ 构建挂了立即修(别让主干红着)
④ 快速反馈(几分钟出结果)
CI 自动做的事(典型):
拉最新代码 → 编译 → 跑单元测试 → 代码扫描
→ 任一步失败:中断 + 通知(谁提交的谁修)
为什么"频繁"是关键:
改动小 → 冲突小、问题好定位(就是这次改动引入的)
攒大了 → 一堆改动混一起、炸一堆、难定位
CI 的产出:
"这次提交的代码能构建、测试通过"的确认
→ 主干始终处于可工作状态
所以 CI=频繁合主干+每次自动构建测试,尽早发现集成问题(保持主干绿)
持续集成(CI):开发者频繁地(每天多次)把代码合并到主干、每次合并自动触发「构建 + 测试」,尽早发现集成问题。关键实践:① 频繁提交/合主干(别憋大分支)、② 每次提交自动触发流水线、③ 保持主干始终可构建测试通过(绿色、构建挂立即修)、④ 快速反馈(几分钟出结果)。CI 自动做:拉代码→编译→单元测试→代码扫描,任一步失败中断+通知。为什么频繁是关键:改动小冲突小问题好定位、攒大了炸一堆难定位。理解「CI=频繁合主干(每天多次)+每次自动构建测试,尽早发现集成问题;实践频繁提交+自动触发+保持主干绿+快速反馈;自动做拉代码→编译→单元测试→扫描失败即停;频繁关键因改动小好定位」,就掌握了持续集成。
三、持续交付与持续部署
理解持续交付和持续部署——区别在最后一步:
持续交付(Continuous Delivery):
在 CI 基础上,自动把通过测试的代码
→ 打包成"可随时部署的制品"、部署到类生产环境
→ 让它"随时能一键上线"
但:上生产由人工点一下确认(人决定何时上)
产出:一个"随时可上线"的制品 + 一键部署能力
最后一步:人工点击"上生产"
持续部署(Continuous Deployment):
比持续交付更进一步:
通过测试后"全自动部署到生产"(无需人工干预)
→ 代码提交 → 自动构建测试 → 自动上生产
最后一步:全自动上生产(没有人工确认)
区别(就在最后一步):
持续交付:自动到"可部署",上生产人工点(人决定)
持续部署:连上生产都自动(全自动)
三者递进关系:
持续集成(自动构建测试,到"测试通过")
⊂ 持续交付(+自动到"可部署制品",上线人工确认)
⊂ 持续部署(+全自动上生产)
→ 一层比一层自动化程度高
为什么持续部署需要更高要求:
全自动上生产 → 必须有非常完善的:
自动化测试(覆盖全,敢信)+ 监控 + 快速回滚
→ 否则自动上线出问题没人拦
所以持续交付(到可部署,上线人工)、持续部署(全自动上生产),区别最后一步
持续交付(Continuous Delivery):CI 基础上自动把通过测试的代码打包成「可随时部署的制品」、部署到类生产环境、随时能一键上线,但上生产由人工点确认(人决定何时上);最后一步人工点击上生产。持续部署(Continuous Deployment):更进一步,通过测试后全自动部署到生产(无人工干预);最后一步全自动。区别就在最后一步:持续交付上生产人工点、持续部署全自动。三者递进:持续集成(到测试通过)⊂ 持续交付(+可部署制品、上线人工)⊂ 持续部署(+全自动上生产)。持续部署需更高要求:完善的自动化测试 + 监控 + 快速回滚(否则自动上线出问题没人拦)。理解「持续交付(自动到可部署制品、随时能一键上线,但上生产人工点)、持续部署(通过测试全自动上生产);区别最后一步人工 vs 自动;递进 CI⊂交付⊂部署;持续部署需完善测试+监控+回滚」,就掌握了持续交付与持续部署。
四、流水线设计
理解流水线(Pipeline)怎么设计:
流水线(Pipeline):把整个过程拆成一串自动执行的"阶段(stage)"
代码提交 → 触发流水线 → 阶段依次执行 → 任一失败即停+通知
典型阶段(从提交到上线):
① 拉代码(checkout):拉最新代码
② 编译构建(build):mvn compile
③ 单元测试(test):mvn test(快,先跑)
④ 代码扫描(scan):
- 静态分析/质量(SonarQube)
- 安全扫描(依赖漏洞,如 OWASP dependency-check)
- 覆盖率检查(JaCoCo,不达标则失败)
⑤ 打包制品(package):mvn package → jar/镜像
→ 制品存仓库(Nexus / 镜像仓库)
⑥ 部署测试环境(deploy test):部署到测试/预发
⑦ 集成/验收测试(integration test):
真环境跑集成测试、验收测试(慢,后跑)
⑧ 部署生产(deploy prod):
持续交付:人工确认后部署
持续部署:自动部署
设计原则:
① 快的先跑(单元测试)、慢的后跑(集成测试)
→ 快速失败(fail fast),早暴露问题省时间
② 每阶段失败即停 + 通知(别带病往下走)
③ 制品只构建一次(build once),后续各环境用同一个制品
→ 保证测试的和上线的是同一份(可重现)
④ 环境逐级推进(测试→预发→生产)
失败快速反馈:
单元测试(几分钟)失败 → 立即停,不用等后面慢的
→ fail fast,省时间、早通知
所以流水线=一串自动阶段(构建→测试→扫描→打包→部署),快先跑、失败即停
流水线(Pipeline) 把整个过程拆成一串自动执行的「阶段(stage)」,代码提交触发、阶段依次执行、任一失败即停+通知。典型阶段:① 拉代码 → ② 编译构建 → ③ 单元测试(快、先跑)→ ④ 代码扫描(质量 SonarQube/安全漏洞/覆盖率)→ ⑤ 打包制品(jar/镜像、存仓库)→ ⑥ 部署测试环境 → ⑦ 集成/验收测试(慢、后跑)→ ⑧ 部署生产(交付人工确认/部署自动)。设计原则:① 快的先跑慢的后跑(fail fast 快速失败)、② 每阶段失败即停+通知、③ 制品只构建一次(build once、各环境用同一个、保证测试和上线是同一份)、④ 环境逐级推进(测试→预发→生产)。理解「流水线=一串自动阶段(拉代码→编译→单元测试→扫描→打包→部署测试→集成测试→部署生产),任一失败即停+通知;原则快先跑慢后跑(fail fast)+失败即停+制品只构建一次(各环境同一份)+环境逐级推进」,就掌握了流水线设计。
五、常用工具与制品
理解 CI/CD 的常用工具和制品:
常用 CI/CD 工具:
① Jenkins:老牌、插件丰富、可自建(Pipeline as Code)
② GitHub Actions:GitHub 内置、YAML 配置、生态好
③ GitLab CI:GitLab 内置(.gitlab-ci.yml)
④ 其他:CircleCI、Travis CI、Argo CD(K8s GitOps)
配置即代码(Pipeline as Code):
流水线定义写成文件放代码库(Jenkinsfile、
.github/workflows/*.yml、.gitlab-ci.yml)
→ 版本化、可评审、跟代码一起管理
制品(Artifact):
流水线产出的可部署产物:
① jar/war:Java 应用包(发到 Nexus)
② 容器镜像(Docker image):现代主流(发到镜像仓库)
→ 一次构建镜像,各环境跑同一个镜像(一致)
制品原则:build once(构建一次)、多环境复用同一制品
现代实践(容器化 + K8s):
代码 → 构建镜像 → 推镜像仓库
→ 部署到 K8s(改镜像 tag,滚动更新)
→ GitOps(Argo CD):声明式部署,Git 是唯一真相源
部署策略(配合 CD):
滚动更新、蓝绿部署、金丝雀发布(见相关题)
→ 降低上线风险、支持快速回滚
所以工具 Jenkins/GitHub Actions/GitLab CI,配置即代码,制品 build once
常用 CI/CD 工具:① Jenkins(老牌、插件丰富、可自建)、② GitHub Actions(GitHub 内置、YAML)、③ GitLab CI(.gitlab-ci.yml)、④ 其他(CircleCI、Argo CD K8s GitOps)。配置即代码(Pipeline as Code):流水线定义写成文件放代码库(Jenkinsfile/workflows yml),版本化、可评审。制品(Artifact):jar/war(发 Nexus)、容器镜像(现代主流、发镜像仓库、各环境跑同一镜像),原则 build once(构建一次多环境复用)。现代实践:容器化 + K8s(构建镜像→推仓库→部署 K8s 滚动更新)、GitOps(Argo CD 声明式、Git 唯一真相源)。部署策略:滚动更新/蓝绿/金丝雀(降低风险、快速回滚)。理解「工具 Jenkins/GitHub Actions/GitLab CI/Argo CD;配置即代码(Jenkinsfile/yml 放代码库版本化);制品 jar 或容器镜像(build once 各环境同一份);现代容器化+K8s+GitOps;部署策略滚动/蓝绿/金丝雀」,就掌握了常用工具与制品。
六、实践与总结
总结 CI/CD 的实践:
CI/CD 实践建议:
① CI:频繁合主干、每次自动构建测试、保持主干绿
② 流水线阶段:构建→单元测试→扫描→打包→部署→集成测试→上线
③ 快速失败:快的测试先跑,失败即停+通知
④ 制品 build once:构建一次,各环境用同一制品/镜像
⑤ 配置即代码:流水线定义放代码库(版本化、可评审)
⑥ 自动化测试是基石:测试不全不敢自动上线
⑦ 部署策略+监控+回滚:降低上线风险
三个概念别混(面试高频):
持续集成:频繁集成+自动构建测试(到"测试通过")
持续交付:+自动到"可部署制品"(上生产人工点)
持续部署:+全自动上生产(无人工)
→ 区别在最后一步上生产是人工还是自动
核心总结:
CI/CD=让代码从提交到上线自动化、频繁、可靠
持续集成⊂持续交付⊂持续部署(自动化程度递进)
流水线=一串自动阶段(构建→测试→扫描→打包→部署),失败即停
价值:小步快跑+快速反馈(问题早暴露、上线频繁风险低)
CI/CD 实践建议:① CI 频繁合主干+自动构建测试+保持主干绿、② 流水线阶段(构建→测试→扫描→打包→部署→集成测试→上线)、③ 快速失败(快的先跑、失败即停)、④ 制品 build once(各环境同一份)、⑤ 配置即代码、⑥ 自动化测试是基石、⑦ 部署策略+监控+回滚。三个概念别混:持续集成(到测试通过)、持续交付(到可部署、上线人工)、持续部署(全自动上生产),区别最后一步。理解「实践:CI 频繁合主干+流水线阶段+快速失败+制品 build once+配置即代码+测试是基石+部署策略监控回滚;三概念持续集成/交付/部署区别最后一步;CI/CD 让代码提交到上线自动化频繁可靠、流水线一串自动阶段、价值小步快跑快速反馈」,就掌握了实践与总结。
记忆钩子:「CI/CD=让代码从提交到上线自动化、频繁、可靠,三个层层递进概念:①CI(持续集成 Continuous Integration)开发者频繁(每天多次)合主干+每次自动构建测试,尽早发现集成问题(保持主干绿),到’测试通过’②持续交付(Continuous Delivery)+自动打成’可随时部署的制品’、随时能一键上线,但上生产人工点确认③持续部署(Continuous Deployment)+通过测试全自动上生产(无人工);★三者关系持续集成⊂持续交付⊂持续部署,区别就在最后一步上生产是人工点还是全自动;流水线(Pipeline)=一串自动阶段:拉代码→编译→单元测试(快先跑)→代码扫描(质量/安全/覆盖率)→打包制品→部署测试环境→集成/验收测试(慢后跑)→部署生产,任一失败即停+通知;原则:快先跑慢后跑(fail fast)、制品 build once(各环境同一份可重现)、配置即代码;价值小步快跑+快速反馈(问题早暴露、上线频繁风险低);工具 Jenkins/GitHub Actions/GitLab CI」。
七、常见误区与追问
- 误区:持续交付和持续部署是一回事。 区别在最后一步「上生产」是人工还是自动:持续交付(Continuous Delivery)自动把代码打成「随时可部署的制品」、让它随时能一键上线,但上生产由人工点击确认(人决定何时上);持续部署(Continuous Deployment)连上生产都自动化了,通过测试后全自动部署到生产、无需人工干预;持续部署要求更高(需要非常完善的自动化测试、监控、快速回滚才敢做)。
- 误区:CI 就是用了 Jenkins/GitHub Actions 这类工具。 工具只是手段——CI(持续集成)的核心是「频繁地把代码合并到主干(每天多次)+ 每次合并自动构建和测试 + 保持主干始终可工作(绿色)」这套实践;如果还是各人在长期分支上开发、很久才合一次,就算用了 Jenkins 也不算真正的持续集成;关键是「频繁集成 + 快速反馈」的实践,不是装个工具。
- 误区:流水线里制品每个环境各构建一次。 应该「build once」——制品(jar 或容器镜像)只构建一次,之后测试环境、预发环境、生产环境都部署同一个制品;如果每个环境各自重新构建,就无法保证「测试通过的那份」和「上线的那份」是同一个(可能因依赖版本、构建环境差异产生不同结果),破坏可重现性;构建一次、多环境复用同一制品是关键原则。
- 误区:有了 CI/CD 就能全自动上生产。 真正的持续部署(全自动上生产)需要非常完善的前提:自动化测试覆盖充分(敢信任测试结果)、完善的监控(上线后能立即发现异常)、快速回滚能力(出问题能秒回滚)、以及成熟的部署策略(金丝雀、蓝绿);大多数团队实际做到的是持续集成 + 持续交付(自动到可部署、人工点上线),因为直接全自动上生产风险太大。
- 追问:CI、持续交付、持续部署三者的区别是什么? 三者是层层递进、自动化程度依次提高的关系:持续集成(Continuous Integration)——开发者频繁合并主干、每次自动构建+测试,做到「代码集成后测试通过」;持续交付(Continuous Delivery)——在 CI 基础上,自动把通过测试的代码打包成「随时可部署的制品」并部署到类生产环境,做到「随时能一键上线」,但上生产由人工确认;持续部署(Continuous Deployment)——比持续交付更进一步,通过测试后全自动部署到生产、无人工干预;区别的核心就在「最后一步上生产」是人工点击还是全自动。
- 追问:一条典型的 CI/CD 流水线有哪些阶段? 从代码提交到上线:① 拉代码(checkout 最新代码);② 编译构建(mvn compile);③ 单元测试(mvn test,快、先跑);④ 代码扫描(静态质量分析如 SonarQube、依赖安全漏洞扫描、覆盖率检查如 JaCoCo);⑤ 打包制品(mvn package 生成 jar 或构建容器镜像,存到 Nexus/镜像仓库);⑥ 部署到测试环境;⑦ 集成/验收测试(真环境跑,慢、后跑);⑧ 部署到生产(持续交付人工确认后部署、持续部署自动部署);任一阶段失败就中断并通知,遵循「快的先跑、失败即停(fail fast)、制品只构建一次」的原则。
- 追问:CI/CD 的核心价值是什么? 核心价值是「小步快跑 + 快速反馈」:每次小改动都频繁集成、自动验证(构建、测试、扫描),问题在提交后几分钟就暴露,而不是攒一大批改动到集成时才炸一堆、难定位;因为每次改动小,出问题时范围小、好定位、好回滚;上线也变得频繁而小、风险低、可快速回滚;自动化还消除了手动构建部署的低效和易错(“在我机器上是好的”),保证构建可重现;整体上让软件交付更快、更可靠、更可控。
八、加强记忆
CI/CD 是让代码从提交到上线「自动化、频繁、可靠」的工程实践,包含三个层层递进的概念:① CI(持续集成,Continuous Integration)——开发者频繁地(每天多次)把代码合并到主干,每次合并自动触发「构建 + 测试」,尽早发现集成问题(保持主干绿),做到「测试通过」;② 持续交付(Continuous Delivery)——在 CI 基础上,自动把通过测试的代码打成「随时可部署的制品」、随时能一键上线,但上生产由人工点击确认;③ 持续部署(Continuous Deployment)——通过测试后全自动部署到生产,无需人工干预。三者关系:持续集成 ⊂ 持续交付 ⊂ 持续部署,区别就在最后一步上生产是人工点还是全自动。流水线(Pipeline)= 一串自动执行的阶段:拉代码 → 编译构建 → 单元测试(快、先跑)→ 代码扫描(质量/安全/覆盖率)→ 打包制品 → 部署测试环境 → 集成/验收测试(慢、后跑)→ 部署生产,任一阶段失败即停+通知;原则「快先跑慢后跑(fail fast)、制品 build once(各环境用同一份、可重现)、配置即代码」。核心价值:小步快跑 + 快速反馈(问题早暴露、范围小好定位、上线频繁而小风险低);工具 Jenkins/GitHub Actions/GitLab CI。一句话「CI/CD 让代码提交到上线自动化频繁可靠;持续集成(频繁合主干+自动构建测试,到测试通过)⊂持续交付(+可部署制品,上线人工点)⊂持续部署(+全自动上生产),区别最后一步;流水线一串自动阶段(构建→测试→扫描→打包→部署)失败即停,快先跑+build once;价值小步快跑+快速反馈」。