CI/CD 基础回顾:持续集成与持续部署
做灰度回滚,说白了就是跟 CI/CD 打交道。如果你连持续集成和持续部署的底子都没打牢,后面谈分层支持那就是空中楼阁。我带团队这么多年,见过太多人把 CI 和 CD 混为一谈,结果回滚的时候手忙脚乱。
持续集成 (CI) 到底在干什么?
持续集成,就是让代码在合并到主干之前,能自动编译、测试、打包。我习惯用一个比喻:你写文章,写完一段就让别人帮你读一遍,发现问题马上改。而不是写了十页再通读,那样改起来成本太高。
CI 的核心价值就两点:
- 尽早发现问题 — 代码一提交就触发构建和测试,bug 半小时内就能暴露。
- 保证主干稳定 — 通过门禁机制,不合格的代码压根进不了主干。
关键指标:CI 的成熟度常用“提交到反馈时长”来衡量。我个人追求的是 < 5 分钟。如果你的团队还在等半小时,那就是该优化的时候了。
持续部署 (CD) 不只是“自动发布”
持续部署分两种:Continuous Delivery 和 Continuous Deployment。前者是“随时可以发布到生产”,需要人工按个按钮;后者是“自动发布到生产”,代码一过门禁,直接上线。
说实话,我在金融项目里很少用全自动 CD,风险太高。但我们做灰度发布时,CI 层面先做分层,CD 层面再做分批推送——这套组合拳非常有效。
# 一个简化的 CD Pipeline 配置示例(Jenkinsfile)
pipeline {
agent any
stages {
stage('Build & Unit Test') {
steps {
sh 'make build'
sh 'make test'
}
}
stage('Containerize') {
steps {
sh 'docker build -t myapp:${BUILD_TAG} .'
}
}
stage('Deploy to Staging') {
steps {
sh 'kubectl apply -f k8s/staging.yaml'
}
}
stage('Smoke Test') {
steps {
sh 'curl -f http://staging.myapp.com/health'
}
}
stage('Deploy to Canary') {
when { branch 'main' }
steps {
// 灰度部署逻辑
sh 'kubectl apply -f k8s/canary.yaml'
}
}
stage('Deploy to Production') {
when { branch 'main' }
input '确认发布到生产?'
steps {
sh 'kubectl apply -f k8s/prod.yaml'
}
}
}
}
我的习惯是:在 CD 流程里至少保留两处人工卡点——一次是灰度验证通过后,一次是生产全量发布前。宁可慢半拍,不要出大事。
Pipeline 核心要素
Pipeline 就是 CI/CD 的骨架。不管用哪个工具,核心要素都跑不出下面这五样:
| 要素 | 说明 | 常见坑 |
|---|---|---|
| 触发条件 | Push、PR、定时、手动 | 忘记配置分支过滤,导致所有分支都跑全量构建 |
| 阶段 (Stage) | 构建→测试→打包→部署 | 阶段间没有依赖关系,并行跑出冲突 |
| 步骤 (Step) | 具体执行的命令或操作 | 步骤内写死凭证,安全隐患 |
| 制品 (Artifact) | 构建产物(镜像、jar、zip) | 制品管理混乱,回滚时找不到旧版本 |
| 环境 | Dev→Staging→Canary→Prod | 环境配置不统一,灰度验证失效 |
有一次我接手一个项目,Pipeline 里十几个阶段全写在一个文件里,没有分层。灰度回滚时想只回滚某个微服务,结果整个流水线都重跑了一遍,耗时两小时。后来我把它拆成了三层:基础构建层、灰度验证层、生产部署层。每个层独立触发,互不阻塞。
常用 CI 工具对比
市面上的工具多得眼花缭乱,其实挑对了能用好多年。我简单列一下用过的几个主流工具:
| 工具 | 部署方式 | 适合团队 | 灰度支持 |
|---|---|---|---|
| Jenkins | 自建 | 大型团队 / 高度定制需求 | 强(Pipeline as Code,灵活) |
| GitLab CI | 云端 / 自建 | 中大型 / 已用 GitLab 的团队 | 中等(环境变量 + 手动触发) |
| GitHub Actions | 云端 | 中小型 / 开源项目 | 中等(Matrix + 环境) |
| CircleCI | 云端 | 中型 / 追求速度 | 一般(Orbs 扩展) |
| Argo Workflows | Kubernetes 原生 | 云原生 / K8s 重度用户 | 强(DAG + 参数化) |
我曾经犯过一个错误:在一个中小型项目里强行上了自建 Jenkins,结果维护成本比开发成本还高。后来全量迁移到 GitLab CI,一个月就稳定了。选工具一定要看团队规模,别为了技术炫酷给自己挖坑。
你想想看,灰度回滚这件事,如果没有分层清晰的 CI 支持,回滚就成了“全量回滚”或者“手动回滚”。CI 在灰度场景下的角色,就是提供可复现的构建、可追溯的制品、可控制的部署。这三样缺一不可。
把这个图记在脑子里:等你后面学灰度回滚的 CI 分层支持时,就会发现其实就是把 CI 这条分支拆成了“基础层”、“灰度层”、“回滚层”,而 CD 分支则负责按层执行不同的部署策略。