运维知识
悠悠
2026年7月23日

我们团队踩了2年坑,才总结出这套企业级Jenkins CI/CD搭建方案(建议收藏)

200多个微服务同时构建失败,线上发版卡死,开发堵在办公室门口骂娘。
我盯着Jenkins那台破服务器,磁盘100%,内存飘红,连后台都进不去。

那一刻我才真正明白:Jenkins不是装上就能用的,企业级的CI/CD,是一套体系,不是一个工具。装上Jenkins到用好Jenkins,中间隔着一百个坑

今天把这两年的踩坑经验全掏出来,从架构到Pipeline,从插件选型到高可用,从权限管控到性能调优,掰开了讲。看完你直接能落地,少走半年弯路。

从一次深夜故障说起

事情是这样的。那天搞活动,所有业务线都在赶发版。我们的Jenkins集群突然就崩了,Master机器CPU直接100%,整个构建系统卡死。

排查过程堪称教科书式的狼狈。先看top,发现Java进程吃满了CPU。再看Jenkins的thread dump,发现大量线程卡在Git操作上。查构建队列,积压了400多个任务,整个Master被拖到喘不过气。

根因查出来让人哭笑不得:有个老项目没做Git LFS,把一堆二进制文件全塞进Git仓库了,单次拉取要20多分钟。每次构建全量拉取,整个Master被拖垮。

怎么解决的

第一步,立刻扩容Master机器到8核16G临时顶住,让发版能继续走。第二步,强制清理那个20多G的仓库,二进制文件迁移到Nexus。第三步,加了Git仓库大小监控,超过500M的报警。第四步,重要Agent节点限流,配置合理的并发数。

这个案例让我彻底明白一个道理:CI/CD系统的稳定性,取决于最弱的那个环节。你Jenkins装得再高端,架构设计得再完美,一个失控的Git仓库就能搞死你。

先搞清楚Jenkins到底是个啥

很多人对Jenkins的认知停留在"装上就能用的工具",但企业用起来,会发现完全不是那么回事。

Jenkins本质上是个事件驱动的执行引擎。它监听代码变更、定时任务、webhook这些事件,然后调度Master和Agent去干活。Master负责调度和界面展示,Agent负责实际构建。这套Master/Agent架构听起来简单,但企业用起来,全是坑。

它和GitLab CI、GitHub Actions最大的区别在于插件生态。Jenkins有1500多个官方插件,几乎能集成所有你能想到的工具。这种开放性是双刃剑,好处是扩展性强,坏处是插件质量参差不齐,装多了容易出兼容性问题。

而Jenkins Pipeline,是它区别于传统CI工具的核心特性。它是一组插件,让你可以用Groovy DSL把整个构建流程写成代码,然后签入到Git仓库里管理。这就是所谓的"Pipeline as Code"——把构建流水线当成代码一样去版本控制、审查、迭代。

说实话,我见过太多团队还在用Freestyle Job建项目,建了几百个Job,改个参数要改到手断。企业级必须上Pipeline,这是血泪教训

架构选型:别一上来就堆K8s

我们第一版架构就吃了亏:上来就搞Jenkins on K8s,动态Agent拉满,觉得这就是最佳实践。结果网络问题、PV挂载问题、调度问题全冒出来,团队天天救火。

后来才悟出来:架构要匹配团队规模,不要为了用新技术而用新技术

10人以下的团队,单Master就够,搞那么多花活纯属给自己挖坑。装个Jenkins,配几个Agent,先把流程跑通再说。

50人左右的团队,Master+静态Agent够用。搭个Nginx反向代理做高可用,Agent按语言分组管理,这套架构能扛住绝大部分中型公司的构建压力。

200人以上的大团队,才需要考虑K8s动态Agent。K8s的好处是弹性伸缩,构建高峰期自动扩容,低谷期自动释放。但运维成本也上去了,需要有专门的SRE团队维护。

我们现在的架构跑了两年,稳得很:2台Master做主备,用Nginx+Keepalived漂移VIP,构建Agent按语言分组(Java一组、Python一组、前端一组),构建产物推Nexus,镜像推Harbor。这套扛了日均2000+次构建,稳定性99.9%以上。

环境准备:这些坑提前避开

Jenkins的安装本身不复杂,但环境准备阶段有几个坑,新手必踩。

第一个坑:运行用户。Jenkins千万别用root启动,但目录权限一定要给足。我们当时chown改权限,改完一堆任务报错,查了半天才发现是.ssh目录和known_hosts的问题。jenkins用户的SSH密钥、known_hosts文件都要正确配置,不然Agent通信会出问题。

第二个坑:JDK版本。Jenkins 2.346以后的版本必须JDK11,我们当时还在用JDK8,启动直接报错。升级JDK又牵扯到一堆老插件兼容性,又是半天折腾。所以选Jenkins版本前,先查清楚对应的JDK要求。

第三个坑:磁盘空间。Jenkins的workspace会越积越多,构建历史、构建产物、日志文件,全吃空间。我们后来挂了块单独的SSD专做workspace,IO瓶颈直接消失。JENKINS_HOME目录建议放在独立分区,最好是SSD。

第四个坑:基础工具。Maven、Git、Docker这些基础工具必须预装到Agent上。别指望Jenkins自己装,它装不靠谱。Agent的镜像要做标准化,新Agent拉起来就能用。

第五个坑:时区和时间同步。Jenkins的定时任务、构建日志、构建历史全靠时间戳。Agent时区不对,构建历史会乱套;时间不同步,分布式构建会出各种诡异问题。所有机器必须配置NTP时间同步。

Pipeline才是企业级的核心

前面说过,Freestyle Job是玩具,Pipeline才是企业级。但Pipeline写起来也有讲究。

声明式Pipeline vs 脚本式Pipeline。新手推荐用声明式(Declarative Pipeline),语法更严格,写法更规范,不容易出岔子。老手可以用脚本式(Scripted Pipeline),更灵活,能写复杂逻辑。我们团队规范是能用声明式就用声明式,复杂场景才用脚本式。

标准的声明式Pipeline长这样:

pipeline {
    agent any
  
    options {
        timestamps()                           // 日志加时间戳
        timeout(time: 30, unit: 'MINUTES')    // 构建超时
        disableConcurrentBuilds()              // 禁止并发构建
        buildDiscarder(logRotator(numToKeepStr: '30'))  // 保留30次构建
    }
  
    parameters {
        string(name: 'BRANCH', defaultValue: 'main', description: '构建分支')
        choice(name: 'ENV', choices: ['dev', 'staging', 'prod'], description: '部署环境')
    }
  
    stages {
        stage('Checkout') {
            steps {
                checkout scm
            }
        }
        stage('Build') {
            steps {
                sh 'mvn clean package -DskipTests'
            }
        }
        stage('Unit Test') {
            steps {
                sh 'mvn test'
                junit '**/target/surefire-reports/*.xml'
            }
        }
        stage('Deploy') {
            when {
                branch 'main'
            }
            steps {
                sh "./deploy.sh ${params.ENV}"
            }
        }
    }
  
    post {
        always {
            cleanWs()  // 清理workspace
        }
        success {
            echo '构建成功'
        }
        failure {
            emailext to: 'team@company.com',
                     subject: "构建失败: ${env.JOB_NAME} #${env.BUILD_NUMBER}",
                     body: "构建日志: ${env.BUILD_URL}"
        }
    }
}

这套模板能解决80%的构建场景。剩下的复杂场景,用参数化构建、多分支Pipeline、并行执行这些特性扩展。

这里有个细节很多人忽略:Jenkinsfile要放在项目根目录。这样每个项目自带Jenkinsfile,谁提交的代码谁负责维护Pipeline,权责清晰。我们团队有条规定:PR里改了Jenkinsfile,必须有高级工程师Review。

插件选型:别装太多,挑重点

Jenkins插件是它的灵魂,也是它最容易崩的地方。我们之前图新鲜装了一百多个插件,升级的时候一半不兼容,Jenkins直接起不来,折腾了一整天。

企业级必装的插件就这些

Pipeline流水线核心,必装。Git/GitHub/GitLab根据代码仓库选一个。Maven Integration做Java构建必备。Docker Pipeline构建镜像必备。SSH Agent远程执行脚本。Role-based Authorization Strategy权限管理,这个没装会出大事。Timestamper日志加时间戳,排查问题必备。Workspace Cleanup清理workspace。Localization中文支持,新手友好。

这些插件谨慎装

第三方小众插件,维护可能跟不上。老旧插件长期不更新,容易出安全漏洞。功能重复的插件装一个就行,装多了冲突。

插件管理要做白名单制度。新插件上线前必须在测试环境跑一遍,确认兼容性再上生产。我们吃过亏,某次升级装了个小众插件,结果和Pipeline插件冲突,整个Master起不来。

另外,Jenkins升级和插件升级要分开做。Jenkins核心版本升级前,一定先在测试环境验证。插件升级也要错开,别一次性全升。

权限管控:出事才知道重要

我们出过这么个事:一个新来的实习生权限没控制好,把生产环境的Job配置改了,导致全公司发版中断了2小时。权限这东西,事前不设防,事后火葬场

基于角色的权限管理是必须的。Role-based Authorization Strategy这个插件一定要装。

我们的角色设计参考:

管理员有所有权限,能改全局配置。开发只能看和触发自己项目的Job,不能改配置。测试可以触发但不能改配置,能看所有项目的构建日志。运维可以改所有Job配置,但管理权限要单独申请。访客只读,连触发构建都不行。

每个项目组成员加到对应角色,Job级别也要分配。千万别图省事给所有人admin权限。出事的时候追责都追不到人。

权限配置还有个坑:不要在Job配置里写死用户信息。用Jenkins的Credentials管理敏感信息(SSH密钥、Kubernetes Token、Docker Registry密码等),Job里只引用Credentials ID。这样人员变动的时候不用改Job配置。

高可用怎么做

Master高可用我们有套标准方案,跑了两年没出过问题。

两台Master机器,配置完全一致(CPU、内存、磁盘、JDK版本、插件版本都要一致)。JENKINS_HOME挂NFS共享存储,所有配置、插件、构建历史全在共享目录。Nginx做反向代理,upstream配置两台后端。Keepalived做VIP漂绑,一台Master挂了另一台自动接管。

Agent节点按业务分组,每组至少2台机器。一台挂了另一台能顶上。关键业务的Agent一定要做冗余,不能只有一台。

构建产物要分离。Jenkins只负责调度,产物存到Nexus(Java包)或S3(通用文件)。Jenkins本身不存大的构建包,磁盘压力会小很多。镜像统一推Harbor,Jenkins不做镜像存储。

JENKINS_HOME的NFS一定要用高可用的存储方案。普通NFS单点故障,Master切换了NFS没切过来就完蛋。我们用的是NFS+DRBD双主方案,后来上了CephFS,更稳了。

监控告警不能少

没有监控的Jenkins就是在裸奔,故障定位全靠猜。

Jenkins本身有Prometheus插件,暴露metrics接口。我们接了Prometheus+Grafana,重点监控这些指标:

队列积压任务数,这个是核心指标。积压超过50就要警惕,说明Agent不够用或者有慢任务。Master JVM内存,Jenkins是Java应用,内存泄漏是常见问题。内存持续增长不释放就要排查。Agent在线状态,Agent掉线是常有的事,特别是K8s动态Agent。构建成功率,按项目分组统计,能看出哪些项目代码质量差。平均构建时长,突然变长说明有问题,可能是依赖变更或者环境问题。

告警规则要分级

紧急告警(电话):Master宕机、队列积压超过200、构建失败率超过30%。重要告警(IM):Agent离线超过5分钟、内存超过80%、单个项目连续失败3次。一般告警(邮件):构建时长超过基线2倍、磁盘使用率超过70%。

构建时长基线这个概念很重要。每个项目第一次构建成功后记录时长,作为基线。后续构建超过基线2倍就告警,能提前发现很多问题——依赖下载变慢、测试用例变多、镜像拉取问题,全能反映在构建时长上。

性能调优实战

Jenkins用久了总会变慢,这里面有几个调优的硬核技巧。

JVM调优是基础。Jenkins的JVM参数要调整,默认配置太保守。我们生产环境的配置是:堆内存设为机器内存的50%-70%,新生代用G1垃圾回收器,MaxGCPauseMillis设为200ms。具体配置在JENKINS_JAVA_OPTIONS环境变量里设置。

export JENKINS_JAVA_OPTIONS="-Xms4g -Xmx4g -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/jenkins/"

Master和Agent分工要明确。Master只做调度,不做实际构建。所有的Maven、Docker、Shell执行都放Agent。千万别在Master上跑构建任务,Master一旦卡住整个集群就完蛋。

并发数控制是关键。Master的并发执行数(# of executors)建议设为0,让Master只做调度。Agent的并发数按机器配置来,4核8G的机器建议设2-3个executor,别贪多。

workspace管理容易被忽略。构建完成后及时清理workspace,不然磁盘会爆。我们用Workspace Cleanup插件,在post阶段的always里调用cleanWs()。重要构建产物在构建中就归档到Nexus,不留在workspace。

构建缓存能大幅提升速度。Maven的本地仓库挂载到独立目录,Agent之间共享。npm、pip这些也有类似的缓存机制。Docker构建用BuildKit的缓存,挂载到持久化存储。

插件精简前面说过,但还要强调一下。每多装一个插件,Jenkins启动时间就多一秒。我们的Master启动时间从1分钟优化到15秒,就是靠砍掉30多个不用的插件。

避坑清单:这些坑千万别踩

不要直接在生产改配置。所有配置变更先在测试环境验证,配置变更要走变更流程,重要变更要双人复核。我们出过生产环境JVM参数改错,Master直接OOM的事故。

不要无监控上线。新Job上线前必须配监控和告警,不然故障发生了都不知道。不要只看CPU不看load、上下文切换。有时候CPU不高但load很高,原因是IO阻塞或者线程争抢。不要省略复盘。每次故障都要复盘,写清楚现象、原因、解决、预防。不复盘的故障一定会再发生。

不要把Jenkins当部署工具。Jenkins的核心是构建和调度,部署应该用专业的工具(Ansible、Argo CD、Spinnaker)。Jenkins可以调用这些工具,但不要自己造轮子。

不要在Jenkins里存敏感信息。密码、Token、密钥这些必须用Credentials管理,不要明文写在脚本里。定期轮换Credentials,特别是有人员变动的时候。

不要忽视构建历史清理。构建历史会一直保留,时间长了Jenkins会越来越慢。配置logRotator,定期清理旧的构建历史。

写在最后

Jenkins这东西,说简单也简单,装上就能跑。说难也难,企业级的稳定性、性能、权限、安全,处处是坑。

我见过太多团队上来就照着博客搭一套,三个月后又推翻重来。企业级CI/CD不是一蹴而就的,是踩着坑迭代出来的。希望我今天总结的这些经验,能让你少踩几个坑。

这套方案我们在生产环境跑了2年,扛住了日均2000+次构建,没出过大的稳定性问题。核心就三点:架构匹配规模、Pipeline as Code、监控全覆盖

如果觉得这篇内容对你有帮助,点赞、在看、转发三连支持一下,这是对我最大的鼓励。也可以关注我的公众号耕云躬行录,回复"CI"领取这份企业级CI/CD搭建的完整方案文档、Jenkinsfile模板合集、以及Jenkins调优配置脚本。

下期我会讲讲Jenkins与Kubernetes深度集成实战,包括动态Agent、PV挂载那些让人头大的问题怎么解。关注我,别错过。

有问题欢迎评论区留言,看到必回。

—— 来自一个被Jenkins折磨过无数次的运维老兵

公众号:耕云躬行录
个人博客:躬行笔记
关注回复「CI」获取完整方案资料

文章目录

博主介绍

热爱技术的云计算运维工程师,Python全栈工程师,分享开发经验与生活感悟。
欢迎关注我的微信公众号@运维躬行录,领取海量学习资料

微信二维码