Administrator
发布于 2024-03-26 / 16496 阅读
386

从 Jenkins 到 GitLab CI 的流水线迁移

我们团队原来的 CI 是 Jenkins,一台老Ubuntu 服务器,Job 用网页点出来的,配置存在它肚子里,谁也说不清有哪些步骤。新人想加一条发布流水线,得先找老员工"口述"。这种不可见的配置,迟早要还债。借着一次 GitLab 迁移,我把流水线整体搬到了 GitLab CI。

不是嫌 Jenkins 不好

Jenkins 没问题,问题是我们的用法:自由风格 Job、手工配节点、脚本散落在各处。构建结果不跟代码走,分支一多就乱。GitLab CI 的卖点是"流水线即代码"——.gitlab-ci.yml 跟仓库在一起,Review 和回滚都走 MR,这正中痛点。

语法对比:从 Stage 到 Job

Jenkinsfile 的声明式写法是 pipeline { stages { stage('build') { steps { ... } } } },GitLab CI 更扁平,直接列 Job,用 stage 关键字分组:

stages:
  - build
  - test
  - deploy

build-job:
  stage: build
  script:
    - ./mvnw -q clean package -DskipTests
  artifacts:
    paths:
      - target/*.jar
    expire_in: 1 hour

最大的差异是产物传递:Jenkins 靠工作空间共享,GitLab CI 靠 artifacts 显式声明。一开始我漏了 artifacts,test 阶段找不到 jar 包,白白重跑 build。这个"显式传递"反而逼出更清晰的依赖关系。

Runner 配置:别用共享 Runner 跑生产

GitLab.com 的共享 Runner 免费但慢、且不可控。我们自建了 Runner,装在 K8s 里,用 gitlab-runner register 挂到项目:

[[runners]]
  url = "https://gitlab.com/"
  token = "xxxx"
  executor = "kubernetes"
  [runners.kubernetes]
    namespace = "gitlab-ci"
    [runners.kubernetes.pod_spec] # 限制资源,避免一个 Job 吃满节点

关键配置是给 Runner 加标签(tag),生产部署的 Job 只允许带 prod 标签的 Runner 跑,普通构建用默认的。权限隔离比图省事重要。

缓存优化:把 Maven 拉包时间砍掉

没缓存时,每次构建都重新拉依赖,光 mvn package 的下载就要 3 分 40 秒。加了缓存后:

cache:
  key: maven-$CI_COMMIT_REF_SLUG
  paths:
    - .m2/repository

构建时间从 4 分 10 秒降到 1 分 05 秒,提速约 75%。但缓存有坑:key 用分支名时,冷分支第一次还是全拉;我们后来改成 key: maven-main 全分支共享一份,命中率更高,代价是偶尔拉到别人分支的依赖——对内部库要注意 SNAPSHOT 污染,主仓用 release 版本规避。

迁移中踩的坑

  • secrets 管理:Jenkins 的凭据直接挪到 GitLab CI Variables,但注意 protected 变量只在受保护分支暴露,我在 feature 分支跑部署 Job 调不到 token,排查了半小时;
  • 并发数:默认 Runner 并发是 1,排队严重,调到 concurrent = 8 才顺畅;
  • Docker in Docker:构建镜像需要 docker build,Runner 用 docker 挂载而非 dind,速度快一半且少一个容器层级。

留个问题

关于《从 Jenkins 到 GitLab CI 的流水线迁移》里这个坑,你当时是怎么处理的?欢迎在评论区聊聊你踩过的类似情况。

参考