深入理解持续集成工具

Shell脚本侠
2025-06-27 21:33
阅读 352

从 Jenkins 到 GitLab CI/CD:我的持续集成工具进阶之路

从 Jenkins 到 GitLab CI/CD:我的持续集成工具进阶之路

在我刚入行那会儿,公司的项目还是靠手动部署的。每次上线都像打仗一样紧张,谁也不敢轻易改代码,生怕一个不小心就搞出个线上故障。后来公司开始引入持续集成(CI)的概念,我也有机会一步步接触到各种 CI 工具。这篇文章想和你聊聊这几年我对 CI 工具的理解、踩过的坑,以及从 Jenkins 转向 GitLab CI/CD 的真实经历。

项目背景:业务发展推动 CI 演进

我们是一个 ToB 的 SaaS 公司,产品包括一个 Web 后台系统和多个 SDK 组件。起初团队规模不大,项目结构也简单,用的是一套基于 Jenkins 的 CI 流程:开发者本地提交代码到 GitLab,触发 Jenkins 自动拉取代码、构建 Docker 镜像并推送到镜像仓库。那时候,Jenkins 是“唯一选择”,一切运行得还算顺利。

但随着业务发展,我们的痛点逐渐暴露出来:

  • 配置复杂:Jenkinsfile 写得越来越臃肿,多分支逻辑混乱。
  • 环境不一致:不同项目的依赖版本管理难统一。
  • 维护成本高:插件更新频繁,有时候升级一个插件就能让整个流水线跑不起来。
  • 协作困难:非 DevOps 成员想要修改 CI 配置必须去 Jenkins 系统操作,不够透明。

这些问题最终促使我们重新思考 CI 工具的选择。

技术选型:为什么是 GitLab CI/README?

当时市面上流行的工具有 Jenkins、GitLab CI/CD、CircleCI、GitHub Actions。我们做了个简单的对比:

工具 优势 劣势
Jenkins 插件丰富,生态庞大 安装配置复杂,可维护性差
GitLab CI/CD 与 GitLab 深度集成,易上手 对非 GitLab 用户支持较弱
GitHub Actions 社区活跃,集成方便 私有化部署成本高
CircleCI 性能不错,界面简洁 价格较高,自定义程度一般

我们最终选择了 GitLab CI/CD,原因主要有两个:

  1. 我们已经在使用 GitLab 进行代码管理,无需额外切换平台;
  2. GitLab Runner 支持私有部署,便于我们在内部集群跑任务。

此外,YAML 形式的 .gitlab-ci.yml 让流程更透明、版本可控,也更容易做 Code Review。这对我们这种需要多人协作的团队来说非常重要。

实践过程:一次完整的迁移案例

在某个老项目中,我们决定先做一个试点迁移。原 Jenkins 流水线大概流程如下:

pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                sh 'make build'
            }
        }
        stage('Test') {
            steps {
                sh 'make test'
            }
        }
        stage('Push Image') {
            steps {
                sh 'docker login registry -u user -p pass'
                sh 'docker build -t myapp:latest .'
                sh 'docker push myapp:latest'
            }
        }
    }
}

转换成 GitLab CI 很直观:

image: docker:24.0

services:
  - docker:dind

stages:
  - build
  - test
  - deploy

build:
  script:
    - make build

test:
  script:
    - make test

deploy:
  script:
    - docker login registry -u $REGISTRY_USER -p $REGISTRY_PASS
    - docker build -t myapp:latest .
    - docker push myapp:latest

这里有几个小细节需要注意:

  • docker:dind 服务用于在 GitLab Runner 中运行 Docker 命令;
  • 使用了内置的变量机制 $REGISTRY_USER$REGISTRY_PASS,避免敏感信息硬编码;
  • 所有配置直接写在代码仓库中,可以随代码一起进行版本控制。

一开始我们也遇到一些问题:

问题1:权限错误导致 Docker 构建失败

刚开始执行 docker build 总是提示权限被拒绝。查了一圈发现是因为 GitLab Runner 默认运行在 gitlab-runner 用户下,对 /var/run/docker.sock 没有访问权限。

解决方式:

  1. gitlab-runner 用户添加到 docker 用户组:
    sudo usermod -aG docker gitlab-runner
    
  2. 重启 GitLab Runner 服务以应用新权限。

这个看似基础的问题其实耽误了不少时间,也提醒我们不要忽视环境搭建的基础检查。

问题2:缓存命中率低

我们在构建前端项目时发现,每次 CI 都要重新安装 npm 包,非常慢。后来尝试引入缓存:

cache:
  key: "$CI_COMMIT_REF_SLUG-node_modules"
  paths:
    - node_modules/

这一项改进直接把构建时间从平均 5 分钟缩短到 90 秒以内。

效果与收益

迁移完成后,整个项目的 CI 体验有了明显提升:

  • 流水线更清晰:每个阶段都在 .gitlab-ci.yml 中一目了然;
  • 易于维护:任何开发人员都可以通过 Pull Request 修改 CI 配置;
  • 提升构建效率:通过合理缓存和并发控制,整体构建时间下降约 40%;
  • 更好的安全控制:凭据集中管理,减少了硬编码泄露风险;
  • 更少的运维负担:不用再频繁处理 Jenkins 插件冲突或性能瓶颈。

最让我感到惊喜的一点是:团队成员开始主动优化自己的 CI 步骤。以前他们只管写代码,现在会去看自己提交的变更对构建耗时有什么影响,甚至有人提出用 Linter 在 PR 阶段拦截格式问题。

几点经验分享

如果你也在考虑 CI 工具的选型,或者准备做迁移,我可以结合自己的经历给出几点建议:

1. 先从小范围试点开始

CI 工具一旦上线就会影响所有人的工作流,所以别上来就在全公司推广。我们是从一个小项目做起,验证可行性、收集反馈、逐步完善模板后再铺开。

2. 尽量保持流程透明、可读性强

GitLab CI 的一大优势就是把 CI 配置放到代码仓库里,这样不仅可以走 Review,还可以做版本回溯。这一点比 Jenkins 只保存在服务器磁盘里好太多了。

3. 重视缓存机制

构建效率直接影响开发体验。合理设置缓存目录和 Key,能大大减少重复下载和构建时间。

4. 安全问题不能忽视

  • CI 中不要明文写密码,用环境变量;
  • 权限最小化原则,例如 Runner 不要用 root 身份运行;
  • 如果涉及敏感步骤(比如生产发布),可以考虑加上人工审批环节。

5. 多阶段 + 并行执行是个好习惯

将测试、打包、构建分开阶段,并尽可能利用并行 job,不仅提高执行效率,也方便排查问题。

写在最后

CI 工具不是万能的,但它确实能让我们的开发流程变得更高效、更规范。从 Jenkins 到 GitLab CI/CD,对我而言不只是技术栈的转变,更是对开发协作流程理解的加深。

中间也走了不少弯路,但正是这些“踩坑”让我对 CI 有了更深的认识。现在的我,看到一个新的项目,第一件事就是去检查有没有 .gitlab-ci.yml 或对应的 CI 文件 —— 因为我知道,它不仅是一个自动化脚本,更是一个项目能否快速迭代、稳定交付的基础设施。

希望这篇文章对你有所帮助。如果你正在面临类似的 CI 工具选型问题,欢迎留言交流,我很乐意听听你的故事!

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝