CI/CD 流水线基础
说实话,我在给团队搭流水线之前,总会先问一句:「你们到底想要持续集成,还是持续部署?」这两个词经常被混着用,但背后的流程和风险完全不一样。先把这个搞清楚,后面集成 KMS 才不会跑偏。
从持续集成说起
持续集成(CI)的核心就一句话:频繁地把代码合并到主干,并且每次合并都触发自动构建和测试。
我自己经历过一个项目,团队每周才合并一次代码,结果合并那天所有人都坐在会议室里盯着冲突发呆。后来改成每天至少合并三次,每次合并都跑一遍自动化测试——冲突少了,问题也能在半小时内暴露。
为什么 CI 这么重要?因为反馈越快,修复成本越低。你想想看,代码提交后 10 分钟就能看到测试结果,和隔天才知道测试挂了,完全是两个世界。
持续交付 vs 持续部署
这两个概念经常被混为一谈,我在这里把它们掰开说清楚。
| 维度 | 持续交付(CD – Continuous Delivery) | 持续部署(CD – Continuous Deployment) |
|---|---|---|
| 最终产物 | 可随时部署的发布包 | 自动上线的新版本 |
| 人工介入 | 需要人工点击“发布”按钮 | 全自动化,无需人工确认 |
| 适用场景 | 金融、医疗等需要审批的环境 | 互联网、SaaS 等高频发布场景 |
| 风险控制 | 有手动卡点,降低生产风险 | 依赖强大的自动化测试和灰度策略 |
在我带过的团队里,90% 的新人都会把“持续交付”和“持续部署”统称为“CD”,但后来在配置生产环境发布策略时吃了亏——没有审批就直接推上生产,结果依赖的密钥没更新,整个服务挂了。所以我的建议是:明确你的 CD 指的是哪种,并在流水线设计里体现出来。
流水线的核心阶段
一条典型的 CI/CD 流水线,无论你用 Jenkins、GitLab CI 还是 GitHub Actions,基本都会包含以下几个阶段。我习惯把它分成“CI 左半段”和“CD 右半段”:
- 代码检出 —— 从仓库拉取最新代码和密钥引用。
- 依赖安装 —— 这里经常踩坑:如果依赖里包含私有包,注意不要硬编码凭证。
- 代码检查 —— 静态分析、格式校验,顺便扫一遍有没有密钥泄露。
- 构建 —— 编译、打包、生成制品。
- 测试 —— 单元测试、集成测试、安全扫描。
- 制品存储 —— 将经过验证的产物推送到制品仓库。
- 部署 —— 按环境推送(开发→测试→预发布→生产)。
- 验证与监控 —— 确认服务健康,回滚失败版本。
下面这张图我用最常用的流程来画,你可以对照着理解每个阶段的位置。
常见流水线工具对比
选工具就像选搭档,合适比流行更重要。我用过 Jenkins、GitLab CI 和 GitHub Actions,简单对比一下它们的差异:
| 特性 | Jenkins | GitLab CI | GitHub Actions |
|---|---|---|---|
| 部署方式 | 自托管为主 | 自托管 + SaaS | SaaS + 自托管 runner |
| 流水线定义 | Jenkinsfile(Groovy) | .gitlab-ci.yml(YAML) | .github/workflows(YAML) |
| 密钥管理 | 凭据插件 + 环境变量 | CI/CD Variables(可分组) | Secrets(环境级) |
| 与 KMS 集成 | 需要安装插件或写脚本 | 通过 CI 变量或 OIDC | 通过 OIDC 或 Actions(自建) |
| 我的偏好 | 适合复杂定制的企业 | GitOps 流派最爱 | 开源项目 + 小型团队 |
我个人更倾向用 GitLab CI 来做 KMS 集成,因为它的 CI/CD Variables 支持按环境分组,还能直接引用外部密钥服务。但如果你团队用 GitHub,配合 OIDC 也是不错的选择。
密钥管理在流水线中的位置
你现在可能会想:密钥管理到底应该在流水线的哪个环节出现?我按经验总结三个必须介入的点:
- 代码检出后、构建前:从 KMS 拉取当前版本需要的密钥,注入到构建环境。
- 测试阶段:确保测试环境使用的密钥是独立的,不要和生产环境混用。
- 部署前:验证目标环境是否有权访问对应的密钥版本,避免部署后无法解密。