Jenkins 是 CI/CD 界的"老大哥"——2004 年从 Hudson 分支出来后,已经走了 20 年。2024 年 9 月它发布了基于 JDK21 的 LTS(2.504.x 系列),而 2024-09-24 正是 Jenkins 官方对 JDK11 镜像停止安全更新的日期。这篇文章不是"Jenkins 是什么"的科普文,而是把零散的实战笔记整理成"从镜像拉取到一条完整流水线"的路径:拉哪个镜像、Agent 怎么挂、钉钉/企微通知怎么接、Kubernetes 上的动态 Agent 怎么配、流水线部署 Java/Golang/Vue 项目分别怎么写。
阅读对象:需要从零搭一套 Jenkins CI/CD,或正在做 JDK8→JDK11→JDK21 升级的开发者、运维
覆盖范围:官方 LTS 镜像选择、Agent 节点(JNLP)、钉钉/企业微信 webhook 通知、Active Choices 级联参数、Generic Webhook Trigger 触发、SSH/Credentials 凭据、Kubernetes 动态 Agent(jnlp-slave)、自定义 sshpass/rsync Agent、流水线部署 Java/Golang/Vue 模板、常见排错
一、Jenkins 镜像选择:JDK8 / JDK11 / JDK21 LTS
Jenkins 官方镜像 jenkins/jenkins 有几个常用 tag,先把它们的关系理清楚:
| Tag | 含义 | 备注 |
|---|---|---|
2.346.3-lts-jdk8 | JDK8 + Jenkins 2.346.3 LTS | 2022 年主流选择,但 JDK8 已停止安全更新 |
2.440.3-lts-jdk11 | JDK11 + Jenkins 2.440.3 LTS | 2024 年过渡选择,2024-09-24 停止安全更新 |
2.504.2-lts-jdk21 | JDK21 + Jenkins 2.504.2 LTS | 当前推荐(LTS 路线) |
When to use:JDK21 LTS(
2.504.x系列)已是新装 Jenkins 的默认推荐。JDK11 LTS 在 2024-09-24 之后不再收安全补丁——还在跑 JDK11 的同学需要规划升级。
1.1 最小启动:JDK8 老镜像
| |
坑 1:第一个启动慢是因为它要执行
init.groovy.d下的初始化脚本,并下载默认插件。耐心等几分钟,初始密码可以通过docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword拿到。
1.2 JDK11 升级路径(已被 JDK21 取代)
如果已经在线上跑着 JDK8 或 JDK11,可以保留数据卷 jenkins_home,直接换镜像 tag 升级。
| |
升级完后第一次启动会提示"java11 将在 2024-09-24 结束支持"——这是 Jenkins 内置的提示,不是 bug。
坑 2:挂
docker.sock是为了在 Jenkins 容器内构建镜像(docker build)。但这等同于把宿主机的 docker 权限交给 Jenkins,多用户场景需要谨慎。
1.3 JDK21 升级路径(当前推荐)
| |
把启动脚本里的镜像 tag 换成 2.504.2-lts-jdk21 即可,数据卷 jenkins_home 完全兼容——Jenkins 2.504.x 会自动迁移配置。
坑 3:容器时区是对的,但 Jenkins 日志时间格式仍是 UTC。解决:在 系统管理 → 脚本命令行 执行
System.setProperty('org.apache.commons.jelly.tags.fmt.timeZone', 'Asia/Shanghai'),或启动时加-e JAVA_OPTS=-Duser.timezone=Asia/Shanghai。新版本还支持在 用户列表 → admin → 设置 → 用户自定义时区 里改 UI 时区,但日志里那行仍是 UTC。
二、必备插件清单
Jenkins 的 90% 价值在插件。一份覆盖 90% 场景的最小集合:
| 插件 | 作用 |
|---|---|
git / gitlab | Git 源码拉取、GitLab 集成 |
SSH plugin | SSH 远程执行命令 |
Publish Over SSH | 把构建产物 SCP 到远端并执行命令 |
SSH Pipeline Steps (ssh-steps) | 流水线里用 sshCommand / sshPut |
Maven Integration | 构建 Maven 项目 |
NodeJS | 构建 Node 项目 |
Go | 构建 Golang 项目 |
git-parameter | 构建时选择 Git 分支 |
Active Choices (uno-choice) | 多级参数级联 |
Generic Webhook Trigger | 接收 Git 服务的 webhook |
Qy Wechat Notification | 构建后发企业微信 |
DingTalk | 构建后发钉钉 |
Naginator | 构建失败后自动重试 |
Environment Injector | 注入运行时环境变量 |
Pipeline / Workflow Aggregator | 流水线基础 |
Kubernetes | 在 K8s 上跑动态 Agent |
JDK Parameter | 多 JDK 项目里选择 jdk 版本 |
Config File Provider | 集中管理 settings.xml / npmrc 等配置文件 |
坑 4:插件安装慢?Jenkins 4.x 之后插件源会从
updates.jenkins-ci.org拉。国内网络下经常卡死,建议:
- 用
*.hpi文件手动下载:https://updates.jenkins-ci.org/download/plugins/- 或在 系统管理 → 插件管理 → 高级 里把
升级站点换成国内镜像(如https://mirror.tuna.tsinghua.edu.cn/jenkins/updates/)
三、钉钉 / 企业微信通知:3 行就能接
3.1 钉钉机器人
- 群设置 → 智能群助手 → 添加机器人 → 自定义
- 安全设置选"自定义关键词"或"加签"
- 拿到 webhook(形如
https://oapi.dingtalk.com/robot/send?access_token=xxxx) - Jenkins 安装
DingTalk插件,在 Job 配置里填 webhook
curl 直接测试:
| |
3.2 企业微信机器人
- 群右键 → 群机器人 → 添加 → 选"群机器人"
- 拿到 webhook(形如
https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxx) - Jenkins 安装
Qy Wechat Notification插件
| |
3.3 在 Pipeline 里推 commit 信息
| |
坑 5:把 webhook 凭据硬编码在脚本里?不要这样做。把 webhook 放进 Jenkins 凭据(Credentials)→ Secret text 里,再通过
withCredentials([string(credentialsId: 'wechat-webhook', variable: 'WEBHOOK')])引用。
四、Agent 集群:JNLP 节点 + K8s 动态 Agent
4.1 JNLP Agent(传统固定节点)
适合:物理机 / 虚拟机 / 容器化的固定 Agent。
前置:在 Agent 机器上装好 java、maven、git。
启动方式 A:java web 启动代理
| |
启动方式 B:Kubernetes 上的 JNLP 静态 Agent
| |
4.2 Kubernetes 动态 Agent(推荐)
Jenkins 装 Kubernetes 插件,每次 Job 触发时在 K8s 里拉一个临时 Pod,构建完销毁。
| |
前置:
- 制作 Jenkins 连接 K8s 的证书(K8s
~/.kube/config的certificate-authority-data/client-certificate-data/client-key-data三个字段,base64 解码后保存) - 把
kube-ca.crt+kube-cert.pfx配到 Jenkins 凭据里 - 创建一个
jnlp-slavePod Template(基础镜像jenkins/inbound-agent:latest-jdk21)
K8s 集群配置:
| |
坑 6:Pod 启动失败?用
kubectl logs -f --tail=10查看 Jenkins 动态创建的 Pod。80% 的情况是jnlp-slavePod Template 里的镜像拉不到(私有仓库没配 imagePullSecrets)或 Jenkins 容器内没装 rsync。
4.3 自定义 Agent 镜像(装 rsync + sshpass)
jenkins/inbound-agent 基础镜像不带 rsync 和 sshpass,但流水线里经常要用。两种方式:
方式 A:临时容器安装 + commit
| |
方式 B:Dockerfile(推荐,可追溯)
| |
| |
五、流水线:声明式 vs 脚本式
5.1 声明式(推荐)
| |
5.2 脚本式(灵活但难维护)
| |
坑 7:声明式是 2017 年之后的官方推荐。新项目用声明式;老项目如果是脚本式,不要一次性重写,逐步迁移。
六、Active Choices:多级参数级联
真实场景:先选 节点(master/dev/联创),再选 项目(不同节点不同项目),再选 主机(不同节点不同主机),再选 分支(不同项目不同分支)。
步骤:
- Job 选"参数化构建"
- 加
Active Choices Parameter,name=agent,Choice Type=Single - Script:
| |
- 加
Active Choices Reactive Parameter,name=project,Referenced parameters=agent
| |
- 同样做 host(referenced=agent)、branch(referenced=project)
坑 8:低版本 Jenkins(2.346.x)装
Active Choices时提示依赖缺失,要先装script-security1.x 版本,再装uno-choice。
七、流水线部署三类项目:Java / Golang / Vue
7.1 部署 Java 项目
参考第五章 5.1 的完整 pipeline。核心点:
mvn clean package -P <profile>打 jarsshPublisher把 jar 传到目标机器- 远端
docker rm -f <container>+docker run -d重启
钉钉/企微通知 + commit 信息:
| |
7.2 部署 Golang 项目
Golang 项目的特殊点:Go 安装路径、GOPATH 设置、交叉编译。
| |
坑 9:Jenkins 装 Go 插件后,Go 路径会被装到
$JENKINS_HOME/tools/org.jenkinsci.plugins.golang.GolangInstallation/go/<version>/。如果手动tar -C解压到/home/docker/jenkins/data/go/,路径对不上会找不到——解决方法是用tar -C时直接建go1.21.5子目录,让最终路径是/home/docker/jenkins/data/go/go1.21.5/。
7.3 部署 Vue 项目
Vue 项目用 npm 构建,产物在 dist/:
| |
坑 10:
docker-compose restart frontend只重启容器,不会重新读docker-compose.yaml的端口/环境变量。改了 compose 文件必须docker-compose up -d。
八、定时构建 + 自动合并代码
轮询 SCM(在 Job 的"构建触发器"里勾选"轮询 SCM"):
| |
坑 11:5 个星分别是"分 时 日 月 周",别写反。
H/5比*/5好——Jenkins 会在集群内做 hash 分散,多个 Job 不会同时触发。
自动合并代码(在 SCM 的 Additional Behaviours 加):
Clean before checkout(构建前清空工作区)Prune stale remote-tracking branches(同步远程分支)Merge before build(构建前 merge 目标分支)
坑 12:Name of repository 一定要写
origin,否则Merge before build报Could not find remote ref。
九、常见排错
9.1 “Waiting for Jenkins to finish collecting data” 等待时间长
Jenkins 通过 Maven 构建 Java 项目后,会做 指纹验证——给每个 jar 算一个 SHA-1,写入数据库。Java 项目越大、依赖越多,等待时间越长。
解决:关掉指纹验证 → Job 配置 → 构建环境 → 勾选 “Disable deferred wipeout and improve performance”。
9.2 中文乱码
启动加:
| |
9.3 IllegalArgumentException: No enum constant io.jenkins.plugins.localization_zh_cn.UserCommunityProperty.ShowConditions
中文插件版本不兼容。解决:删除中文插件 → 重装匹配 Jenkins 版本的 localization-zh-cn 插件 → 重启。
9.4 Publish Over SSH 连接超时
检查:
~/.ssh/known_hosts里有没有目标机器的公钥(StrictHostKeyChecking=no可绕过)- 远端
sshd_config是否允许PasswordAuthentication yes - 网络是否可达(
telnet <INTERNAL_HOST> 22)
9.5 流水线里 Git 拉取失败
| |
9.6 Kubernetes 插件连接集群失败
| |
80% 是这几个原因:
- 证书过期(K8s 证书默认 1 年)
- 镜像拉取失败(私有仓库没配 imagePullSecrets)
jnlp-slavePod Template 里command/args写错
十、写在最后
Jenkins 的"全"是把双刃剑——插件生态丰富意味着学习曲线陡。从 2004 年走到 2024 年,Jenkins 仍是大量企业 CI/CD 的"事实标准"(不是"应该",是"事实上")。如果你正在做新项目选型,可以看看 GitHub Actions(云原生、YAML 优先)或 Drone(容器化、声明式),但对存量 Jenkins 集群,升级到 JDK21 LTS、关闭指纹验证、清理无用插件,就能让 80% 的项目跑得更稳。
下一步建议:
- Jenkins on K8s 的完整部署:Jenkins Master 也跑在 K8s 里 + dynamic Agent
- Jenkins Configuration as Code (JCasC):用
jenkins.yaml管理所有插件、凭据、节点 - Pipeline as Code:把 Jenkinsfile 放进 Git 仓库,Job 通过
Multibranch Pipeline自动发现
2024+ 视角补充
本文写于 2024-09,2025-2026 期间 Jenkins 关键演进:
- Jenkins 2.516.x LTS(2025-04 起):JDK 17 / 21 双轨 LTS,JDK 11 LTS 已于 2024-09-24 停止安全补丁——本文内容完全契合
- Jenkins Evergreen 持续完善:CD-as-a-Service 模式,与 Kubernetes Operator 深度集成
- Jenkins on K8s Operator(jenkinsci/kubernetes-operator):Jenkins Master 本身也跑在 K8s 上,生产级高可用 + 自动备份
- Pipeline as Code 主导:Jenkinsfile + Multibranch Pipeline 成为 2025+ 事实标准,老的 FreeStyle Job 模式逐步淘汰
- AI 辅助插件(2025+):Jenkins 接入 LLM 做"日志摘要 + 失败原因诊断",但仅作为辅助——核心编排仍是声明式流水线
实战建议(2025-2026 视角):Jenkins 仍是 Java 后端 CI/CD 事实标准;GitHub Actions / GitLab CI 在新项目是强力竞争者,但存量 Jenkins 集群升级到 JDK 21 LTS + 跑在 K8s 上仍是 2025+ 主路线。
参考资料
- Jenkins 官方文档:https://www.jenkins.io/zh/doc/
- Jenkins 官方镜像:https://hub.docker.com/r/jenkins/jenkins
- Jenkins K8s Operator:https://github.com/jenkinsci/kubernetes-operator
- Kubernetes 插件:https://plugins.jenkins.io/kubernetes
- Active Choices 插件:https://plugins.jenkins.io/uno-choice
- Generic Webhook Trigger:https://plugins.jenkins.io/generic-webhook-trigger
- 钉钉自定义机器人:https://open.dingtalk.com/document/orgapp/custom-robot-access
- 企业微信群机器人:https://developer.work.weixin.qq.com/document/path/91770
