ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Jenkins 安装实战:从环境准备到常见坑位排查全指南

Jenkins 安装实战:从环境准备到常见坑位排查全指南

如果你准备搭一套自动化构建环境,Jenkins 这个名字大概率绕不开。作为目前使用范围最广的持续集成(CI)工具,它解决的问题很直接:把代码拉取、编译、测试、打包、部署这一连串重复动作从人肉点击变成自动执行。我帮几个团队搭过构建环境,几乎每次都是从安装 Jenkins 开始,而安装这一步看起来简单,实际踩坑的人并不少。这篇就围绕“Jenkins 安装”把该想清楚的事、该准备的环境、该避开的坑一次说明白,适合第一次接触持续集成的新手,也适合装过但没系统整理过安装细节的人。

安装是所有后续工作的地基,地基没打好,后面调插件、写流水线、配节点都会跟着难受。所以我不打算只是给一段“java -jar 跑起来就行”的命令,而是把方案选择、环境依赖、目录规划、常见报错这些平时容易忽略的细节一并展开,让看完的人能真正理解每一步为什么这么做。

1. 装之前先想清楚:三种安装方式怎么选

1.1 三种方式实际用起来差别在哪

Jenkins 官方提供的安装方式主要有三类,实际工作中也会有人混着用,但每种的适用场景差别很大。

第一种是 WAR 包方式。下载一个 jenkins.war,通过 Java 直接启动,可以嵌在已有 Web 容器里,也可以独立跑。这种方式对服务器环境要求最简单,只要有一台能装 Java 的机器就行。

第二种是系统原生安装包,比如 Debian/Ubuntu 下的 .deb、CentOS/RedHat 下的 .rpm。这种方式好处是包管理器帮你搞定服务注册、开机自启、日志轮转,对不熟悉 systemd 的人更友好。但缺点也明显:安装目录比较分散,配置路径不像 WAR 包那样可控,换版本时依赖包管理器的仓库状态。

第三种是 Docker 容器方式。一句 docker run 就能起一个实例,适合临时环境、本地实验、或者团队已经全面容器化的情况。但它引入了一个新问题:容器内的文件系统是临时的,必须把 JENKINS_HOME 挂载出来,否则容器一删,所有配置和任务全没了。另外容器内跑构建任务时,如果任务本身需要访问 Docker 守护进程,还要额外处理挂载和权限,复杂度并不低。

1.2 为什么我优先建议 WAR 包

我的个人习惯是:生产环境的 Jenkins 一律用 WAR 包跑,不依赖系统包管理器版本,不依赖容器平台。原因很简单,升级方便、回滚干净、日志可控。

用 WAR 包升级,基本上就是停服务、备份数据、替换 war 文件、再启服务。出问题想回滚,把旧 war 放回去就行。用系统安装包升级,可能拖着依赖一起变;用 Docker 升级,可能因为镜像体积和网络问题折腾半天,而且插件文件在容器内层还是数据卷里,出了问题排查成本高。WAR 包是 Jenkins 官方迭代最频繁支持的形态,遇到问题去社区提问时,别人给的定位思路也基本基于这种部署方式。

当然这不是说系统安装包和 Docker 不能用。团队已有成熟的运维体系、要求全链路可编排,Docker 反而是更合适的选择;如果只是想在本机快速起一个环境做验证,docker run 那一条命令确实快。关键是在选型前想清楚:谁维护、怎么升级、数据放哪、出问题能不能快速回滚。

1.3 版本选择:长期支持版优先

安装前还有一个容易忽略的问题:选版本。

我见过不少人直接下载“最新版”,结果插件生态还没跟上,或者团队用的构建工具版本和新版 Jenkins 不兼容,最后被迫降级。稳妥的做法是选择长期支持版,也就是 LTS 版本。LTS 版本每隔一段时间发布一个维护版,插件兼容性和稳定性都更好,社区支持周期也长,适合生产环境长期运行。

这里还有一个关键点:新版本 Jenkins 对 Java 版本有硬性要求。较新的 LTS 版本已经以 Java 11 或 Java 17 为基准,早期版本才支持 Java 8。这就意味着装新版 Jenkins 前,得先把 JDK 准备好,而不是随便拿个旧环境凑合跑。很多人安装失败,不怪 Jenkins,而是 JDK 版本不匹配,启动时直接抛出不支持类的错误。关于 JDK 的事,下一节细说。

2. 环境准备:JDK 版本、内存与目录规划

2.1 JDK 一定要先对口

安装 Jenkins 之前,先确认机器上的 Java 版本。命令行执行一句:

java -version

看到类似openjdk version "17.0.x"或者openjdk version "11.0.x"就没问题。如果系统里同时装了好几个 JDK,推荐用update-alternatives(Linux 上通用的切换工具)把默认版本切到目标版本,然后再检查一次。

sudo update-alternatives --config java java -version

为什么这么强调 JDK?因为 Jenkins 本身是 Java 写的,它启动和运行都依赖 JDK,插件框架、任务执行也要有 Java 环境。我遇到过最典型的报错是启动时抛UnsupportedClassVersionError,一看就是 JDK 版本比 Jenkins 要求的低。这类问题在安装阶段最容易排查,别等启动失败了才到处找原因。

没有按照 JDK 的可以一条命令装上,Debian/Ubuntu 用:

sudo apt update sudo apt install -y openjdk-17-jdk

CentOS/RedHat 用:

sudo yum install -y java-17-openjdk

装完再java -version确认,这一步值得多花两分钟。

2.2 内存、磁盘和专用用户

Jenkins 本身体积不大,但任务并发跑起来,内存需求会快速上涨。如果只是本地实验,512MB 也能勉强跑;生产环境建议至少 2GB 可用内存,4GB 更宽裕。真要拿它跑 Maven、Gradle、前端打包这类重活,并且同时跑多个任务,那就要根据任务量继续加内存。

调 JVM 参数的方式也很直接,在启动命令里加:

java -Xms1g -Xmx2g -jar jenkins.war --httpPort=8080

Xms1g表示初始堆内存 1GB,Xmx2g表示最大堆内存 2GB。这两个值不要拍脑袋填,先看机器真实空闲内存:

free -h

磁盘也一样。构建产物、插件包、构建日志都写在 JENKINS_HOME 里,时间长了很容易涨到几十 GB。安装前用df -h看一眼那个分区有没有足够余量,别等磁盘写满,Jenkins 各种奇怪报错就来了。

还有一个容易忽略但很重要的操作:不要用 root 用户跑 Jenkins。正确做法是创建一个专用系统用户,让 Jenkins 只在自己的权限范围内读写文件。这既是安全习惯,也是为后面避免权限混乱铺路。创建用户和目录的命令大致是这样:

sudo useradd -r -s /bin/bash jenkins sudo mkdir -p /var/lib/jenkins sudo chown -R jenkins:jenkins /var/lib/jenkins

有独立的用户,后面排查日志、备份数据、清理缓存,职责都清晰很多。

2.3 两个核心目录:安装目录和数据目录

装 Jenkins 之前先把目录规划清楚,能省很多后续麻烦。我自己常用的划分是这样:

  • 程序目录:/opt/jenkins,放 jenkins.war 和辅助脚本。
  • 数据目录:/var/lib/jenkins,就是 JENKINS_HOME,所有配置、任务、插件、日志、密钥全在这里。
  • 日志目录:/var/log/jenkins,把运行日志单独拎出来,方便查问题。

关键的是理解 JENKINS_HOME 的意义。很多第一次接触 Jenkins 的人以为装完就完事了,不知道 Jenkins 的所有“记忆”都存在这个目录里。换机器、升级前备份、迁移环境,核心都是搬这个目录。我一度吃过亏,升级前只备份了 war 文件,没备份数据目录,结果任务全没了,只能重新配,那种滋味不好受。

用 WAR 包启动时,如果用户目录下没有特殊设置,Jenkins 默认会把 JENKINS_HOME 放在启动用户的家目录下,比如/root/.jenkins。但生产环境建议显式指定到/var/lib/jenkins,这样路径稳定、备份方便、权限也好控制。显式指定方式在后面启动章节会写到。

3. 实操记录:WAR 包方式把 Jenkins 跑起来

3.1 下载与首次启动

先建程序目录,下载稳定版 WAR 包。因为版本一直更新,我这里不贴死版本号,直接从官方发布页拿长期支持版最新链接即可。

sudo mkdir -p /opt/jenkins cd /opt/jenkins sudo wget <你的稳定版WAR包下载地址> -O jenkins.war

下载完成后,先用前台方式做首次启动验证,这样日志直接打在终端上,能第一时间发现环境问题:

export JENKINS_HOME=/var/lib/jenkins java -Xms512m -Xmx1g -jar /opt/jenkins/jenkins.war --httpPort=8080

看到日志里出现类似“Jenkins is fully up and running”的字样,说明启动成功了。此时打开浏览器访问http://<服务器IP>:8080,应该能看到 Jenkins 的页面。

首次启动时不要急着关掉终端,先确认端口没被占、页面能访问、数据目录能写。如果页面一直转圈或者打不开,切回终端看日志,通常原因就写在最近几行里。

3.2 用 systemd 托管,避免重启就挂

前台启动适合验证,但服务器一重启,进程就断了。生产环境必须把 Jenkins 注册成 systemd 服务。

先停掉刚才的前台进程,然后新建服务文件:

[Unit] Description=Jenkins Service After=network.target [Service] User=jenkins Group=jenkins Environment="JENKINS_HOME=/var/lib/jenkins" Environment="JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64" Environment="JAVA_OPTS=-Xms512m -Xmx1g" ExecStart=/usr/bin/java $JAVA_OPTS -jar /opt/jenkins/jenkins.war --httpPort=8080 Restart=always RestartSec=10 [Install] WantedBy=multi-user.target

注意几个细节。User和Group指定成之前创建的 jenkins 用户,而不是 root。JAVA_HOME的路径要跟机器实际 JDK 安装路径对应,用readlink -f $(which java)可以查到真实路径。Restart=always保证进程意外退出时自动拉起。

文件创建好后依次执行:

sudo systemctl daemon-reload sudo systemctl enable jenkins sudo systemctl start jenkins sudo systemctl status jenkins

看到active (running)就说明服务起来了。之后每次更新 WAR 包,只要替换文件、重启服务就行,不用改动服务配置。这一步做完,安装才算是真正稳定下来。

3.3 解锁与初始化配置

打开http://<服务器IP>:8080,第一次访问会进入解锁页面。Jenkins 在首次启动时生成了一串管理员初始密码,位置在 JENKINS_HOME 下:

sudo cat /var/lib/jenkins/secrets/initialAdminPassword

把终端里显示的字符串复制到页面上,点击继续。这个密码是临时性的,完成管理员账号创建后就用不上了。建议创建管理员时设置一个强密码,并把它放进团队的密码管理工具,不要只存在某个人的备忘录里。

初始化界面会询问安装插件的方式。我的建议是:不要无脑选“安装推荐的插件”。推荐列表里有很多你用不到的插件,安装数量大、耗时长,还会引入不必要的安全面。第一次配置时可以选“自定义选择”,只装当前必需的,比如后面的中文语言包、Git 相关插件。插件是可以后期随时补装的,并不需要一次到位。

首次初始化还应该顺手设置一下 Jenkins 对外访问地址,位置在“系统管理 -> 系统配置 -> Jenkins Location”。如果后面要配 Nginx 反向代理,这里的地址需要填实际对外访问的域名或地址,不填的话 Jenkins 页面重定向和任务里回填的链接可能一直是 8080 端口,带来一堆奇怪问题。

4. 装完立刻要做的:镜像源、反向代理和中文显示

4.1 换镜像源,加速插件安装

Jenkins 的插件默认从官方更新中心下载,在国内网络环境下面经常超时或失败。所以安装完成后,第一件值得做的事就是换软件镜像源。

进入 JENKINS_HOME 目录,编辑更新中心的配置文件:

cd /var/lib/jenkins vim hudson.model.UpdateCenter.xml

默认内容大致是官方更新中心地址,可以改成本地团队可达的开源镜像站地址,或者你所在区域网络访问更快的软件源。常见配置如下:

<?xml version="1.0" encoding="UTF-8"?> <sites> <site> <id>default</id> <url>https://<你的开源镜像站>/jenkins/updates/update-center.json</url> </site> </sites>

改完后重启 Jenkins 服务:

sudo systemctl restart jenkins

需要注意,镜像源不仅要提供 update-center.json,还要处理里面指向各插件文件的下载地址。很多开源镜像站提供了更新脚本,下载后放到对应目录执行一遍,就能把默认地址替换成本地镜像地址。完成后再到“系统管理 -> 插件管理 -> 高级”页面,能看到可用的更新站点地址,点提交检查应该很快能拉到插件列表。这步做完,后面装插件就不再是耐心战了。

4.2 用 Nginx 做反向代理,告别裸奔端口

Jenkins 默认监听 8080 端口,直接把端口暴露给用户既不美观,也容易和其他服务冲突。生产环境通常会在前面放一层 Nginx 做反向代理,对外用 80 端口,内网转发到 8080。

Nginx 配置示例:

server { listen 80; server_name _; client_max_body_size 50m; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }

配置要点有三个。一是Host头要转发,否则 Jenkins 生成重定向地址时容易出错;二是X-Forwarded-Proto要设置,否则外部 HTTPS 请求到 Jenkins 后会被当成 HTTP,页面里有的资源地址会走错协议;三是如果对外走的 HTTPS,还要考虑证书配置。重启 Nginx 后再访问http://<服务器IP>/,看到的就是 Jenkins 页面了,用户可以不用记端口。

我这里提醒一个反代场景的常见问题:Nginx 配好之后,Jenkins 任务构建完生成的控制台地址、分支源地址可能还保留内部端口信息。这需要在“系统管理 -> 系统配置 -> Jenkins Location”里,把 Jenkins URL 改成对外地址,同时在/opt/jenkins下启动时加上明确监听地址。如果团队已经准备整体容器化,反向代理这步也可以由网关层替代,但思路是一样的:外部统一入口,内部服务解耦。

4.3 顺手搞定中文界面

很多团队希望界面显示中文,降低新手理解成本。其实 Jenkins 官方提供了本地化插件,进入“系统管理 -> 插件管理 -> 可选插件”,搜索 Chinese,安装“Localization: Chinese (Simplified)”插件。装完后在系统配置里设置 Locale 为zh_CN,重启服务,界面就会变成中文。

要说明的是,中文插件只是界面翻译,不影响底层逻辑和任务执行。团队成员可能习惯中英文混用,这不重要,关键是让每个人能快速理解系统状态。如果团队整体英文水平没问题,也可以不装这个插件,看个人习惯。不过建议团队协作环境下统一语言,减少沟通歧义。

5. 排错手册:安装期这些坑我基本都踩过

5.1 端口、Java 版本、内存问题

安装阶段遇到最多的问题可以整理成一张速查表,现场排查时对着看,效率高很多。

现象可能原因处理方式
启动报 UnsupportedClassVersionErrorJDK 版本过旧,不满足 Jenkins 版本要求安装对应版本的 OpenJDK,检查 java -version
端口 8080 已被占用其他进程监听同一端口netstat -tlnp | grep 8080,找到进程,换端口或停掉冲突进程
页面一直转圈或 404端口没真正监听,或磁盘空间已满看启动日志、检查 df -h 磁盘余量
任务一多就卡死堆内存配置过小调大 JAVA_OPTS 的 -Xms / -Xmx,重启服务
启动后几秒自动退出systemd 里 User 没有数据目录权限确认 chown -R jenkins:jenkins /var/lib/jenkins

端口排查常用命令是ss -lntp或netstat -tlnp | grep 8080,能直接看到哪个进程占用了端口。如果 Jenkins 需要换端口,把启动参数里的--httpPort改掉就行,Nginx 反代那边的proxy_pass也要同步改。

磁盘满这个问题最隐蔽,现象和网络问题很像。有一次页面要等半天才打开,查了一圈最后发现是根分区满了,因为项目构建历史太多,日志没有做清理。所以建议安装阶段就规划好日志轮转和构建历史清理策略,别等磁盘被打爆再处理。

5.2 插件安装与初始密码问题

插件安装失败是安装后第一个高频问题。主要表现为:插件列表加载不出来、下载到一半报超时、或者提示“No such plugin”。前两种情况基本和源有关,按 4.1 节换镜像源基本能解决。第三种情况更多是插件名打错或者插件本身兼容版本不行,去插件站点确认一下插件支持的 Jenkins 版本,再搜准确的名字。

还有一种情况是“插件装上了但没生效”。通常原因是要重启服务。Jenkins 很多插件在安装后需要重启加载,页面会提示,不要忽略,直接sudo systemctl restart jenkins重启一次。

初始密码是另一个典型的坑。解锁页面用的密码在/var/lib/jenkins/secrets/initialAdminPassword,但很多人在安装引导里创建了管理员后,还会尝试用这个初始密码登录,结果发现密码不对。其实初始化后,这个临时文件就失去了作用,后续登录用的是你自己创建的管理员账号密码。

如果忘记管理员密码,处理思路是:停止 Jenkins 服务,打开JENKINS_HOME/config.xml,找到安全配置区域,把安全认证相关配置临时禁用或改为不启用认证,然后重启服务,重新设置密码,再恢复安全配置。这套操作要小心,改配置文件前先备份,操作完成后记得把安全策略恢复到正常状态,避免服务处于无防护状态。

5.3 数据目录备份与恢复思路

安装完成、正常登录之后,我建议立刻做一次数据目录备份,给这个“初始可用状态”留一个存档。备份很简单:

sudo systemctl stop jenkins sudo tar czf jenkins_home_$(date +%Y%m%d).tar.gz /var/lib/jenkins sudo systemctl start jenkins

停止服务是为了保证文件一致,生产环境也可以先不停,但对新手来说,停服务备份最稳妥。备份文件要放到和 Jenkins 数据目录不同的磁盘或机器上,否则磁盘一起坏掉就没有意义了。

恢复的过程也简单:把备份解压到目标机器的/var/lib/jenkins,确认目录权限归属正确,然后启动服务。

这里有一个我亲自吃过亏的细节:恢复后如果发现插件加载不出来,先不要怀疑恢复流程,大概率是恢复的机器和原来机器 JDK 版本不同,或者插件源配置不一样。所以迁移环境时,除了打包数据目录,最好把 JDK 版本、启动参数也一并记下来。建议把这个信息写成一个简单的部署文档,放在团队 Wiki 里,省得每次换人都要重新问一遍。

安装只是 Jenkins 使用的入口,真正耗时的是后续的插件整理、节点管理、流水线编写。但恰恰是安装阶段决定了很多后续操作的上限,比如目录规划得合理,备份和升级就省心;JDK 版本选对,插件生态的兼容痛苦就少一大半;反代和镜像源配好,团队日常使用体验会顺畅很多。我个人现在无论给哪个团队搭环境,都会坚持这几个原则:独立用户、独立数据目录、WAR 包部署、显式指定 JENKINS_HOME、装完立即备份。这几个习惯帮我躲过了不少坑,也推荐你在自己的环境里直接采纳。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进