3. CI/CD 基础概念:从手工到自动化的认知拐点

说实话,我第一次接触 CI/CD 时,觉得这就是个“编译打包的自动化脚本”。后来被现实狠狠教育了——没有理解这些基础概念,流水线搭得再花哨,也只是一个会报错的玩具。

咱们这门课要跟国密接口打交道,测一次签名验签可能要调七八个工具。如果不先把 CI/CD 的底子打牢,后面你连“为什么我的国密流水线跑了两小时还没完”都分析不出来。

所以这一章,我带你把四个核心概念掰开揉碎:持续集成、持续部署、流水线、制品。


3.1 持续集成:别等周五下午才合并代码

持续集成,英文叫 Continuous Integration,缩写 CI。说白了就是:你每一次提交代码,系统都自动拉下来、编译、跑单元测试、给检查结果。

我在项目中遇到过最典型的反例:团队五个人,各写各的国密接口模块,攒了两周才合并。结果一跑,A 的签名算法依赖跟 B 的消息摘要库版本冲突,修了三天。这就是典型的“集成地狱”。

持续集成的核心目标就是打破它。你想想看——每次提交都验证,冲突早发现,修复成本低到可以忽略。

CI 的核心价值

  • 早发现集成问题,避免“爆炸式冲突”
  • 保证代码库始终处于可发布状态
  • 强制团队养成小步提交习惯

3.2 持续部署:从“我点一下”到“自动上线”

持续部署(Continuous Deployment)是 CI 的下一站。CI 帮你确保代码没问题,CD 则负责把没问题的代码 自动 送到目标环境。

很多人分不清持续交付和持续部署。我习惯这么记:

概念 含义 区别
持续交付 每次 CI 通过后,生成可部署的版本,但需要手动确认才上线 有人拍板
持续部署 CI 通过后,自动推送到生产环境,无人干预 全自动

在国密接口的场景下,我更建议先用持续交付。为什么?国密算法涉及合规审核,有些环节还是得过一次人工。你可以让流水线自动打包、自动部署到测试环境,但上生产前留个“确认按钮”。

避坑提示

我曾经在一个项目里直接上了全自动持续部署。结果一次签名算法的配置项写错,部署后所有接口返回 “ILLEGAL_KEY”。虽然五分钟就回滚了,但监控告警把运维同学半夜喊起来骂了半小时。后来我学乖了——关键接口加个“手动确认”环节,不丢人。

3.3 流水线:你的自动化“传送带”

流水线(Pipeline)就是把 CI 和 CD 做成的一系列自动化步骤。你可以把它想象成一条工厂传送带:代码从一端进去,依次经过编译、测试、打包、部署,最后从另一端出来一个可运行的服务。

每条流水线由 阶段(Stage) 和 任务(Job) 组成。我给你看一个最基础的国密接口流水线结构:

流水线:国密代理签名服务
├── 阶段1:代码检查(lint、代码规范)
├── 阶段2:单元测试(跑全部单测)
├── 阶段3:国密算法验证(SM2/SM3/SM4 功能测试)
├── 阶段4:构建打包(生成 Docker 镜像)
└── 阶段5:部署测试环境(推送到测试 K8s 集群)

为什么叫“流水线”?因为它们是串行的——阶段 2 失败了,阶段 3 根本不会启动。这样你能精确定位到哪一步出了问题。

我个人的习惯

流水线别设计得太长。超过 7 个阶段的流水线,出问题时排查起来非常痛苦。我曾经接手过一个 12 阶段的流水线,每次跑完要 40 分钟,光看日志就要翻十几屏。后来我拆成两条:一条 CI 流水线(代码检查 + 单测 + 国密验证),一条 CD 流水线(镜像构建 + 部署),分开跑,清晰多了。

3.4 制品:你的“交付物”长什么样

制品(Artifact)是流水线产出的“东西”。它可以是:

  • 一个编译好的 .jar 包
  • 一个 Docker 镜像
  • 一个 npm 包
  • 一份国密签名验证报告

理解制品的关键在于:它应当是不可变的、版本化的、可追溯的。你不能覆盖它,也不能修改它。你要的是“某年某月某日,从某次提交构建出的某版本制品”。

我在做国密接口 CI/CD 集成时,制品库用的最多的就是 Nexus 和 Harbor。Nexus 管 jar 包,Harbor 管镜像。国密算法模块编译出来的东西,我都会打上 sm2-v1.2.3 这种清晰标签。

制品管理的三个原则

  1. 不可变:制品发布后禁止修改,只能新建版本
  2. 可追溯:每个制品必须关联 Git commit ID 和构建时间
  3. 可复现:只要保留制品和构建参数,随时能重建出相同环境

3.5 四者的关系:一张图说清楚

这些概念不是孤立的。持续集成驱动流水线,流水线产出制品,制品又被持续部署推到目标环境。我画了张图,你看看就明白了:

CI/CD 核心概念关系图 流水线(Pipeline) 持续集成(CI) 持续部署(CD) 制品(Artifact) CI 驱动流水线 → 流水线产出制品 → 制品由 CD 部署到目标环境

我画这条线的逻辑是:

  • 持续集成 触发你的流水线——没有提交,流水线就不启动
  • 流水线 里跑各种阶段,最后产出一个或多个 制品
  • 持续部署 拿到制品,把它推到测试、预生产或生产环境

你想想看,如果 CI、流水线、制品、CD 四者脱节,你会有多痛苦?CI 跑了但没产出可部署的包,CD 部署了但没人知道用的是哪个版本的制品。嗯,这些坑我都踩过。


3.6 把这些概念串起来:一个最简单的实战场景

假设你在做一个 SM2 签名服务。你需要写一段代码,然后发布到测试环境让前端联调。在没有 CI/CD 的时候,你的步骤是:

  1. 本地写完代码,手动编译
  2. 把 jar 包 scp 到测试服务器
  3. ssh 上去停掉旧进程、启动新进程
  4. 出了问题,排查半天发现是本地编译的版本不对

有了 CI/CD,这套流程变成:

  1. 你提交代码到 Git 仓库
  2. 持续集成自动触发流水线
  3. 流水线跑:代码检查 → 单元测试 → SM2 功能验证 → 构建 Docker 镜像
  4. 流水线产出制品(Docker 镜像,Tag 是 commit SHA)
  5. 持续部署把镜像推送到测试环境的 K8s 集群
  6. 测试通过后,你点击“确认上线”,持续交付把同一份制品部署到生产

整个过程你只做了一件事:提交代码。剩下的全是自动化的。这也就是 CI/CD 最迷人的地方。

注意

国密接口对构建环境有特殊要求。比如 SM2 签名算法需要用 指定版本的 OpenSSL 或 经国家密码管理局认证的密码卡驱动。这些驱动必须提前固化在流水线的构建镜像里,否则跑出来的制品可能连签名都生成不了。一定要在流水线里显式声明这些依赖版本。

3.7 这一章你该带走什么

  • 持续集成 是“频繁合并 + 自动验证”,目标是早发现问题
  • 持续部署 是“自动把验证通过的代码推上线”,持续交付则在中间留个确认步骤
  • 流水线 是自动化的步骤组,它是 CI/CD 的执行载体
  • 制品 是流水线的产出,必须不可变、版本化、可追溯

我个人觉得,这四个概念就像开车:

  • CI 是你的仪表盘——随时告诉你车况
  • 流水线是你的发动机——提供动力
  • 制品是你的汽油——能量载体
  • CD 是你的自动驾驶——把车开到目的地

没有哪个都跑不远。但一旦把它们组合起来,你就从“手工修车工”变成了“自动化车队管理者”。下一站,我们就要上车动手了。