CI/CD 流水线设计(Github Actions / Jenkins)
什么是 CI/CD?
- CI(Continuous Integration,持续集成):开发人员频繁(如每天多次)将代码合并到主干分支,每次合并后自动触发构建和测试,尽早发现集成错误。
- CD(Continuous Delivery / Deployment,持续交付/部署):
- 持续交付:代码在通过所有测试后,随时可手动部署到生产环境。
- 持续部署:代码在通过所有测试后,自动部署到生产环境(无需人工干预)。
流水线(Pipeline)是什么?
流水线是自动化执行的一系列步骤,通常包括:
flowchart LR
A[代码拉取] --> B[依赖安装] --> C[编译构建] --> D[单元测试] --> E[集成测试] --> F[打包] --> G[部署] --> H[通知]
工具对比:Github Actions vs Jenkins
| 特性 | Github Actions | Jenkins |
|---|---|---|
| 部署方式 | 云原生,与 GitHub 深度集成 | 自托管,需自行维护服务器 |
| 配置文件 | .github/workflows/*.yml | Jenkinsfile(Groovy 语法) |
| 易用性 | 上手简单,适合中小项目 | 功能强大,插件丰富,适合复杂企业场景 |
| 扩展性 | 依赖 GitHub 生态,扩展有限 | 插件生态庞大,高度可定制 |
| 成本 | 免费额度充足,私有仓库也免费 | 免费开源,但需自备服务器和维护成本 |
| 触发机制 | Push、PR、定时、手动等 | 同上,支持 Webhook、定时、远程触发等 |
推荐选择:
- 实际工作中,我们会选择混合使用:
Actions管理代码/DEV 环境 +Jenkins负责生产环境管理复杂流水线。
示例:Github Actions 简单流水线
| |
自动化测试
为什么需要自动化测试?
- 保证每次代码变更不影响已有功能(回归测试)
- 快速反馈,缩短修复周期
- 为持续部署提供质量门禁(Quality Gate)
- 减少人工测试成本
常见测试类型(按阶段)
| 类型 | 描述 | 执行阶段 |
|---|---|---|
| 单元测试 | 测试单个函数/类,Mock 依赖 | CI 构建阶段 |
| 集成测试 | 测试模块间交互,如 API、数据库 | CI 构建阶段 |
| 端到端测试 | 模拟用户操作整个系统(如 Selenium) | 部署后测试环境 |
| 性能测试 | 压力、负载、并发测试 | 预发布阶段 |
| 安全测试 | 扫描漏洞(如 OWASP ZAP、Snyk) | 构建或部署阶段 |
如何集成到 CI/CD?
在流水线中添加测试步骤
测试失败 → 流水线中断,通知开发者
测试覆盖率报告(如使用
coverage)最佳实践:
测试用例要覆盖核心路径和边界条件
使用测试框架(如 Pytest、GoConvey )
并行执行测试加速流程
失败时提供清晰日志和截图(E2E 测试)
灰度发布(Gray Release / Canary Release)
什么是灰度发布?
灰度发布是一种渐进式发布策略,先让一小部分用户或服务器使用新版本,观察运行情况(如性能、错误率、用户体验),再逐步扩大范围,最终全量上线。
为什么需要灰度发布?
- 降低新版本上线风险
- 快速发现问题并回滚,影响范围小
- 支持 A/B 测试、功能开关、用户分群
实现方式
方式一:基于流量比例(最常见)
- 使用网关/负载均衡(如 traefik、Istio、Spring Cloud Gateway)控制流量比例
- 例如:5% 用户 → v2.0,95% → v1.0
方式二:基于用户特征
- 根据用户 ID、地域、设备、VIP 等路由到不同版本
- 适合定向测试或内测
方式三:基于服务器分组
- 部署新版本到部分服务器,逐步替换旧服务器
示例: traefik 灰度配置
Traefik 初始配置
| |
动态配置文件
| |
灰度发布脚本
| |
执行灰度发布
第一步 (90/10):./canary-api-deploy.sh 90 10
第二步 (50/50):./canary-api-deploy.sh 50 50
完成 (0/100):./canary-api-deploy.sh 0 100
最佳实践:
- 配合监控系统(Prometheus + Grafana)观察指标
- 设置自动熔断:错误率 > 5% 自动回滚
- 灰度周期建议 1~3 天,逐步放量
回滚机制(Rollback Mechanism)
什么是回滚?
当新版本上线后出现严重问题(如崩溃、数据错误、性能下降),快速恢复到上一个稳定版本的操作。
为什么需要自动回滚?
- 人工回滚慢,影响用户体验和业务收入
- 自动化可减少 MTTR(平均修复时间)
- 与监控告警联动,实现“无人值守”发布
回滚策略
基于版本的回滚
- 保留历史版本镜像/包(Docker Image、Jar、War)
- 部署系统支持一键切换版本(如 Helm、K8s Deployment)
基于 Git 的回滚
- 回滚到上一个 Git Commit / Tag
- 重新触发 CI/CD 流水线部署旧版本
自动回滚(推荐)
- 监控关键指标(错误率、延迟、CPU)
- 超过阈值 → 自动触发回滚脚本
示例:Kubernetes 回滚
| |
示例:自动回滚脚本(伪代码)
| |
最佳实践:
- 回滚操作必须幂等、快速、可审计
- 回滚后保留日志,便于事后分析
- 定期演练回滚流程(如 Chaos Engineering)
- 数据库变更需特别小心(一般不自动回滚 DDL)
总结:四者如何协同工作?
一个完整的现代 DevOps 发布流程如下:
flowchart TD
A[开发者提交代码] --> B[触发 CI 流水线
Github Actions/Jenkins] B --> C[运行自动化测试
单元/集成/E2E] C --> D{测试是否通过?} D -->|是| E[打包构建 → 推送镜像/包] D -->|否| F[通知失败并停止] E --> G[CD 阶段: 部署到预发布环境
→ 自动化验收测试] G --> H[灰度发布到生产
5% → 20% → 50% → 100%] H --> I[监控系统实时采集指标
错误率、延迟、资源] I --> J{指标是否异常?} J -->|是| k[自动回滚至上一版本] J -->|否| L[发布成功] L --> M[通知团队 + 生成报告]
Github Actions/Jenkins] B --> C[运行自动化测试
单元/集成/E2E] C --> D{测试是否通过?} D -->|是| E[打包构建 → 推送镜像/包] D -->|否| F[通知失败并停止] E --> G[CD 阶段: 部署到预发布环境
→ 自动化验收测试] G --> H[灰度发布到生产
5% → 20% → 50% → 100%] H --> I[监控系统实时采集指标
错误率、延迟、资源] I --> J{指标是否异常?} J -->|是| k[自动回滚至上一版本] J -->|否| L[发布成功] L --> M[通知团队 + 生成报告]
最佳实践建议
- 基础设施即代码(IaC):用 Terraform、Ansible 管理环境
- 不可变基础设施:每次部署新建实例,避免配置漂移
- 蓝绿部署 / 金丝雀发布:结合灰度策略
- 日志 + 监控 + 告警三位一体:ELK + Prometheus + AlertManager
- 流水线可视化:让团队随时看到构建/部署状态
- 权限与审批:生产环境部署需人工审批(尤其金融、医疗行业)