聊聊持续集成工具:从“能跑就行”到“高效交付”的实战经验分享

黄勇·
2025-06-17 17:42
阅读 733

我是在一家中型互联网公司做 DevOps 工具链开发的,主要负责内部 CI/CD 平台的设计与实现。说白了,就是让开发同学提交代码后,自动构建、测试、部署,减少人为操作带来的低效和错误。

在加入团队之前,公司的 CI 环境非常原始: Jenkins 是唯一的选择,job 用得杂乱无章,没有统一的流程规范,甚至有些项目是直接在服务器上手动执行脚本打包的。整个研发流程像是靠惯性往前推,谁也不敢动那几台老旧的 Jenkins 服务器,生怕一重启就崩盘。

这篇文章我想借这个机会,讲讲我们在推动持续集成平台升级过程中踩过的坑、用过的工具、遇到的问题以及最后的收益。如果你正在为自己的团队挑选 CI 工具或者正准备搭建一套更高效的构建流程,希望我这些亲身经历能给你一些启发。


引言:为什么我们开始重新审视 CI 工具?

引言:为什么我们开始重新审视 CI 工具?

2021 年底,随着公司业务快速扩张,我们迎来了几个新问题:

  • 项目数量暴增:原本不到 30 个服务,一下子涨到了 80 多个。
  • 构建任务排队严重:Jenkins 的 agent 数量跟不上需求,经常一个 job 得等十几分钟才排上队。
  • 失败率高但定位难:很多构建失败是因为环境不一致或者脚本写法混乱,排查一次要花上半天。
  • 新人上手成本高:每个项目都有一套自定义的 jenkinsfile,没人敢轻易改,文档也几乎等于没有。

这时候我们就意识到,CI 工具不能再当“后台小透明”了,它必须成为一个可维护、可扩展、可配置的基础能力,支撑起整个研发流程的稳定性与效率。

于是我们启动了一个叫“Phoenix(凤凰)计划”的项目——目标是重构 CI 系统,提升整体交付效率,同时降低使用门槛。


遇到的挑战:不只是换工具那么简单

自动化部署流程-1

遇到的挑战:不只是换工具那么简单

刚开始我们以为就是换个更新的 CI 工具而已,比如 GitLab CI 或者 GitHub Actions,但实际上远没有想象中简单。

挑战一:工具选型困难重重

我们先后评估了 Jenkins、GitLab CI、GitHub Actions、CircleCI、Drone、Tekton 几种主流方案。

工具 优点 缺点
Jenkins 插件生态丰富,社区强大 架构陈旧,维护复杂
GitLab CI 原生集成 GitLab,易上手 如果不使用 GitLab,就没啥优势
GitHub Actions 和 GitHub 集成好,免费额度大 自托管 runner 成本高
CircleCI UI 友好,支持并行执行 国内访问慢,费用较高
Drone 轻量级,容易部署 插件少,社区活跃度一般
Tekton CNCF 孵化项目,适合云原生场景 上手难度高,学习曲线陡峭

项目管理工具-2

最后我们选择了 Jenkins + Tekton 的混合方案 —— 把 Tekton 当作底层构建引擎来调度任务,而 Jenkins 做调度器和 UI 层,相当于做了个中间层抽象,这样既能保留已有的历史 job,又可以为未来迁移到纯 Tekton 打基础。

听起来很完美吧?其实后面坑更多……


我们的解决方案:打造灵活可控的 CI 平台

我们的解决方案:打造灵活可控的 CI 平台

我们的核心设计思路是 “上层统一配置,下层灵活扩展”,具体包括以下几个部分:

1. 统一配置管理

我们基于 YAML 定义了一套构建模板:

pipeline:
  name: "my-service"
  triggers:
    - type: git_push
      branch: develop
  stages:
    - name: checkout
      action: git-checkout
    - name: install
      action: npm-install
    - name: build
      action: webpack-build
    - name: test
      action: jest-test

然后通过中间服务将这个模板翻译成 Tekton 的 TaskRun 或 PipelineRun,大大减少了每个项目的重复工作。

2. 自研轻量 Runner Pool

Tekton 默认需要每个任务都新建一个 Pod,但我们发现对于轻量任务(比如 lint、test),这种开销太大了,影响构建效率。

所以我们自己做了一个共享式的 Runner Pool,在 Kubernetes 中预启动一组空闲容器,并根据任务类型动态注入脚本。这样避免了每次都要拉镜像、启动容器的时间浪费,实测平均构建时间下降了 40%。

3. 构建缓存优化

我们知道构建过程中的依赖下载是非常耗时的,特别是在 Node.js 和 Go 项目中。于是我们为每个项目加了一个“缓存 key”机制:

# 示例:缓存 node_modules 目录
cache_key=node_modules-${GIT_COMMIT}

结合 S3 兼容的对象存储,我们将这些缓存文件上传保存。后续相同 commit 的构建就可以直接复用缓存,极大提升了构建速度。


踩坑记录:那些年我们一起掉进去的陷阱

工具换了,问题也不少。下面是一些印象深刻的“血泪教训”。

🐞 Jenkins 插件兼容性问题

我们一开始想用 Jenkins 的 Tekton 插件来做集成,结果发现插件版本不匹配,导致部分 API 无法调用,调试起来极其痛苦。后来果断放弃插件,直接在 Jenkins 写 Groovy 脚本去调 Tekton API。

def response = sh(script: """
curl -X POST http://tekton-pipeline:8080/apis tekton.dev/v1beta1/namespaces/default/pipelineruns \
-H 'Content-Type: application/json' \
-d @tekton_run.json
""", returnStdout: true).trim()

虽然不够优雅,但至少稳定可用。

🔁 动态参数传递太难搞

初期我们尝试在 Jenkins 流水线中动态注入一些参数(比如分支名、commit hash),结果因为 Jenkins 的变量作用域和 shell 解析顺序搞错,各种莫名其妙的错误层出不穷。

最终解决方案是采用 JSON 配置文件 + sed 替换的方式:

sed -e "s/\${BRANCH}/${env.BRANCH}/" \
    -e "s/\${COMMIT}/${env.GIT_COMMIT}/" \
    template.yaml > generated.yaml

虽然原始,但胜在清晰明了,出问题也好查。

🧱 构建镜像拉取慢得离谱

最头疼的是在不同环境之间拉取 Docker 镜像速度太慢,尤其是在北京机房部署的节点拉上海机房仓库的镜像,简直像蜗牛爬。我们后来引入了 Harbor 的镜像代理,并且本地加了个镜像缓存加速器(类似 cnrm),效果立竿见影。


实施后的效果:不是简单的提速,而是彻底改变协作方式

经过半年多的努力,Phoenix 计划终于上线,带来了显著的变化:

指标 改造前 改造后 提升幅度
平均构建时间 6min 3.5min 42%
构建成功率 78% 92% ↑14%
新人上手所需文档时间 半天以上 30 分钟左右 ↓60%
同时并发任务数 最多 10 个 支持 50+ ↑500%

更重要的是,我们现在可以把 CI 配置统一管理,配合权限系统实现“谁提交谁负责”,真正做到了自动化闭环。


一些经验总结 & 建议

如果你也在规划或者重构你们的 CI 系统,这里有一些我真心建议你考虑的事情:

✅ 不要一开始就追求“一步到位”

CI 平台是个长期演进的系统,别想着一次性全部重写。最好是分阶段迭代,先从最痛的部分下手。

比如你可以:

  1. 先解决构建慢的问题 → 增加缓存 + 调整并发策略
  2. 再解决配置混乱的问题 → 推广标准化流水线模板
  3. 最后再考虑底层架构升级 → 引入 Tekton 或 Argo Workflows

每一步都落地后再推进下一步,不然很容易陷入“理想很丰满,现实很骨感”的泥潭。

✅ 不要过度依赖 UI 配置

虽然可视化界面看起来很方便,但它会带来一个问题:逻辑分散难以维护。我们曾经有个 Jenkins job 界面里嵌了好几个 Shell Script Block,根本没人敢动一行代码。

现在我们坚决要求所有构建流程都由代码定义(Infrastructure as Code),用 Git 来管理变更历史,这样不仅可追溯,也能方便做 diff 检查。

✅ 小心“工具万能主义”

不要觉得换一个工具就能解决所有问题。我们曾天真地以为只要换成 GitHub Actions 就万事大吉,结果发现一旦涉及私有网络、企业级权限控制,还是有很多定制开发要做。

所以一定要明确自己的需求边界。你是想要更好的开源体验?还是更看重平台成熟度?还是要跟已有系统做深度集成?这些问题想清楚,才能做出合适的决策。


最后的一点感悟

这几年折腾下来,我越来越觉得,持续集成不是一项技术活儿,更像是一种“软件工程文化”的体现。

它背后反映的其实是:

  • 我们是否重视可重复的流程?
  • 是否愿意为自动化投资时间和资源?
  • 是否能把构建失败当作生产事故来看待?

有时候,一个好的 CI 工具可能不如一个认真的工程师重要。工具只是手段,真正的变化来源于组织对质量意识的提升。

所以如果你问我:“我现在应该用 Jenkins 还是 Tekton?”我的回答一定是:“先看看你团队能不能写出一个结构清晰的 pipeline.yml。”

毕竟,工具有尽头,而工程化的思维才是真正的生产力。


如果你喜欢这样的实战分享,欢迎留言交流你的 CI 实践经验。如果有想了解的具体技术细节,我也很乐意继续深入展开~

评论 0

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