CI管道基础:CI/CD概念与三大工具核心工作流

说实话,干了这么多年DevOps,我见过太多团队把CI/CD当成「玄学」——配置了半天,一提交代码就崩。其实CI/CD没你想的那么复杂。咱们今天就把这三个主流工具掰开了聊,顺带讲讲我踩过的坑。

CI/CD到底在解决什么问题?

我先问你个问题:每次代码合并到主分支,你是不是提心吊胆?生怕一个冲突把线上搞挂了?CI/CD说白了就是帮你自动化这个「提心吊胆」的过程。

  • 持续集成(CI):每次代码提交都自动构建、跑测试。早期发现问题,别拖到上线前。
  • 持续交付(CD):通过CI的代码自动部署到类生产环境。注意,不一定直接上生产。
  • 持续部署(CD):CI通过后直接自动推到生产。嗯,这需要你足够自信,或者测试覆盖率足够高。

我个人习惯:团队还没达到80%单元测试覆盖率之前,别开持续部署。我曾经在一个项目里强行上CD,结果一次测试漏报导致生产宕机两小时……从那以后我学会了「保守一点」。

三大CI/CD工具核心工作流对比

市面上工具很多,但主流就这三个:Jenkins、GitLab CI、GitHub Actions。我分别讲下它们的核心逻辑。

1. Jenkins —— 老牌王者

Jenkins的核心是「主从架构」。主节点负责任务调度,从节点(Agent)负责执行。工作流靠Pipeline DSL描述。

pipeline {
    agent any
    stages {
        stage('Checkout') {
            steps { git 'https://github.com/example/repo.git' }
        }
        stage('Build') {
            steps { sh 'mvn clean package' }
        }
        stage('Test') {
            steps { sh 'mvn test' }
        }
        stage('Deploy') {
            steps { sh 'kubectl apply -f deploy.yaml' }
        }
    }
}

我记得第一次配Jenkins,被它的插件生态吓到了——两千多个插件,但真正常用的就二十来个。别贪多,装多了反而容易版本冲突。

2. GitLab CI —— 一体化体验

GitLab CI把代码托管、CI/CD、容器注册表全揉在一起。工作流靠.gitlab-ci.yml文件控制,每个任务叫Job,任务集合叫Stage。

stages:
  - build
  - test
  - deploy

build-job:
  stage: build
  script:
    - mvn clean package

test-job:
  stage: test
  script:
    - mvn test

deploy-job:
  stage: deploy
  script:
    - kubectl apply -f deploy.yaml
  only:
    - main

这里有个坑:stages必须按拓扑顺序定义,Job之间如果有依赖,你得自己控制。我踩过「test跑完了才开始build」的荒唐事,因为stage写反了。

3. GitHub Actions —— 云原生的新秀

GitHub Actions的核心概念是「Workflow」→「Job」→「Step」。每个Workflow由事件触发(比如push、pull_request),运行在GitHub托管的Runner上。

name: CI Pipeline
on: [push, pull_request]
jobs:
  build-and-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-java@v4
        with:
          java-version: '17'
      - run: mvn clean test
      - run: mvn package

GitHub Actions最大的好处是「开箱即用」,不需要自己维护Runner。但我建议你们公司人多的话还是自建Runner,免费额度跑一个月就没。

要点速览:三个工具本质都是在「事件触发→流水线执行→产物输出」这个循环里转。区别在于:
- Jenkins:灵活,插件多,但搭建维护成本高。
- GitLab CI:一体,天然与GitLab仓库绑定,适合GitLab生态。
- GitHub Actions:轻量,云端,社区Actions库丰富。

核心工作流:一个通用模型

不管用哪个工具,CI管道的核心工作流其实都差不多。我画了个图帮你梳理下——

CI/CD 核心工作流通用模型 代码提交/PR 1. 拉取代码 (Checkout) 2. 构建编译 (Build) 3. 自动测试 (Test) 测试通过? 失败 → 通知开发者 成功 4. 制品打包 (Package/Artifact) 5. 部署/发布 (Deploy) 常见触发方式 • push 到特定分支 • Pull Request 事件 • 定时/手动触发 Mock回放介入点 • Test阶段拦截外部API • 使用录制流量作为Mock • 回放验证接口兼容性 • 对比结果自动检查 整体趋势:左进右出,上测试下发布。Mock回放通常在「测试」阶段注入。 Jenkins / GitLab CI / GitHub Actions 均遵循此模型

避坑指南:我曾经在一个项目里把「测试通过」和「制品打包」放在同一个Stage里,结果测试失败时构建产物已经上传了。正确做法是保证Stage之间的依赖走向是单向的,失败就立即中断,别让后续步骤捡到脏数据。

Pipeline阶段的核心分工

不管用Jenkins的Declarative Pipeline,还是GitLab CI的YAML,亦或是GitHub Actions的Workflow,你都得把下面这几个阶段想清楚。我习惯用这张表来跟团队对齐——

阶段 核心目标 常见工具 Mock回放能做什么?
1. Checkout 获取最新代码 git, svn 无直接关系
2. Build 编译、依赖解析 Maven, Gradle, npm 无直接关系
3. Test 验证代码正确性 JUnit, pytest, Jest 注入Mock数据,回放录制流量
4. Package 打包成可部署制品 Docker, tar, jar 无直接关系
5. Deploy 发布到环境 kubectl, ansible 部署后验证时可回放Mock

关键认知:Mock回放不是替代测试,而是把那些依赖外部服务(第三方API、数据库、云服务)的测试场景「固化」下来。这样你的CI管道就不再受外部环境波动影响了。我曾在电商项目里用Mock回放模拟支付回调,从此再也不用担心测试环境没钱扣。

三种工具在Mock回放场景下的配置差异

虽然核心工作流一样,但三种工具的配置方式各有千秋。我给你列几个实战中常见的配置点——

  • Jenkins:通常用Pipeline插件里直接跑sh 'python mockserver.py',或者用docker run启动Mock容器。注意清理,别让Mock服务占着端口。
  • GitLab CI:可以在services字段声明一个Mock容器作为服务依赖。这招特别好用,因为GitLab CI会自动帮你管理容器生命周期。
  • GitHub Actions:用services类似,但可以配合job.services来实现。另外GitHub生态里有现成的Mock Actions,比如MockServer action。

嗯,这里要特别提醒一下:不管用哪个工具,Mock服务的端口映射一定要和你的被测代码里写的地址一致。我有一次忘了映射端口,Mock回放跑了一小时全失败——因为代码连的是localhost:8080,Mock却跑在8081。

个人建议:先在本地跑通Mock回放脚本,再塞进CI管道。别像我一样,直接在Jenkins里写十行sh,结果排错排了一天。

好了,CI管道的核心概念和三大工具的工作流就先聊到这儿。接下来你就可以拿着这张图去给团队画大饼了——不对,是讲解CI管道的最佳实践。