ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Jenkins从安装到自动化部署:踩坑实录与实战指南

Jenkins从安装到自动化部署:踩坑实录与实战指南 写这篇东西之前我先把话放这Jenkins的安装使用网上教程一搜一大把但多数都是“点到为止”——装完就没了插件装不上、Webhook不触发、构建产物传不到服务器上这些问题没人告诉你。我这些年从零搭了不知道多少套Jenkins环境从单机到几十个节点的集群都折腾过踩坑踩到怀疑人生。这篇文章我不打算写成官方文档的复读机就按实际动手的顺序把从下载Jenkins到跑通自动化部署的完整链路写一遍顺带把我遇到过的问题和排查思路全部交代清楚。适合谁看准备在公司内部搭CI流程的运维同学、被临时抓壮丁搭环境的后端开发以及想彻底搞明白Jenkins自动部署原理的测试和前端工程师。不管你是第一次听到Jenkins这个名字还是已经建过几个Job但经常被各种诡异报错卡住这篇应该都能帮到你。1. 安装前的准备版本选型和目录规划1.1 JDK版本不对后面全白搭先说一个很多人还没走到安装就开始翻车的事情JDK版本。Jenkins本身是一个Java应用机器上没有JDK它压根跑不起来。但问题不在“有没有”而在“版本对不对”。从Jenkins 2.357版本开始官方要求必须跑在Java 11或Java 17上如果你机器上还是JDK8下载最新的war包或者用官方源安装启动的时候要么直接给你报一个unsupported class version错误要么起来之后一堆插件加载异常日志里全是一眼看不明白的NoClassDefFoundError。我现在的习惯是直接上OpenJDK 17。Jenkins的LTS版本对Java 17支持已经很成熟而且这两年新版本的插件也在往JDK17靠。装完以后务必检查一下环境变量别省这一步java -version echo $JAVA_HOME如果JAVA_HOME没输出在/etc/profile里加上export JAVA_HOME/usr/lib/jvm/java-17-openjdk-amd64 export PATH$PATH:$JAVA_HOME/bin执行source /etc/profile让配置生效。补充一个高频场景公司老项目还是JDK8的但Jenkins必须用JDK17跑这两者其实不冲突。Jenkins支持在“Manage Jenkins - Tools - JDK”里配置多个JDK安装然后在每个Job里单独指定用哪个JDK去构建。前提是你机器上装了多个版本并且能用which java找到对应的路径。这个配置项很多人不知道导致了“为了Jenkins不敢升级JDK”的误会。1.2 war包、rpm包、Docker三种方式怎么选安装方式上我的建议非常直白先想清楚你准备把这台服务器当成什么。如果只是临时测试或者公司已经有Tomcat在跑想顺手挂一个Jenkins上去那用war包最省事。下载jenkins.war丢到Tomcat的webapps下启动Tomcat就完事了。更直接一点不用Tomcat也行Jenkins本身可以独立运行java -jar jenkins.war --httpPort8080如果这是一台专职CI服务器我更推荐用官方提供的rpm或者deb包。它会帮你把Jenkins注册成systemd服务开机自启、日志管理、重启服务都方便。CentOS系大致是这么装sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key sudo yum install jenkins -y sudo systemctl start jenkins sudo systemctl enable jenkinsDocker方式我也用过不少但它有一个必须正视的问题Jenkins的配置、插件、构建记录全部都在文件系统里容器一删就全没了。除非你把/var/jenkins_home挂载成持久化卷否则千万别在生产环境用裸容器跑Jenkins。Docker更适合的场景是Kubernetes里跑动态构建节点这个后面有机会单独写一篇。这里还得强调一个路径概念rpm方式安装后Jenkins的默认目录结构长这样/var/lib/jenkinsJenkins主目录所有配置、插件、构建记录都在这备份就备份它/var/log/jenkins日志目录/etc/sysconfig/jenkins启动参数文件改内存、改端口都在这搞清楚这三个位置后面所有排查工作都不抓瞎。1.3 内网环境怎么离线安装很多公司CI服务器是内网隔离的装不了外网包这是很现实的需求。离线安装的核心就两个war包能拷进去插件也能装进去。war包没什么好说的移动硬盘也好、内网共享目录也好拷进去就能跑。离线装插件有两个路子。第一个路子在能联网的电脑上从Jenkins插件更新中心把需要的.hpi文件一个个下载下来拷贝到/var/lib/jenkins/plugins目录下注意目录权限然后重启Jenkins。这个方法看起来简单实际上有个大坑插件之间是有依赖关系的。你装A插件结果它依赖B和CB又依赖D手动下很容易漏。我前几年吃过这个亏之后换了一个更聪明的做法先在一台能联网的机器上正常装一遍Jenkins把需要的插件都装好然后把整个/var/lib/jenkins/plugins目录打包拷到内网机器解压。这个做法虽然土但能一次性解决依赖问题内网机器重启Jenkins后插件全部就位。唯一要注意的是插件版本要和Jenkins主版本匹配不然启动时控制台会一片红。2. 初始化配置解锁管理员、换国内插件源2.1 第一次启动必须处理的三件事服务起来之后浏览器访问http://你的IP:8080会看到一个解锁页面。初始管理员密码在文件里直接读cat /var/lib/jenkins/secrets/initialAdminPassword把密码复制进去进入下一步。这里要特别注意到了“Customize Jenkins”这一步一定选“Select plugins to install”不要选“Install suggested plugins”。推荐插件列表里塞了一堆你可能根本用不到的东西安装时间极长而且在国内网络环境下大概率装到一半就失败。选“Select plugins to install”进去以后先不勾选任何插件直接点右上角的保存进去之后再按需安装。这个操作能帮你省掉大量等待时间。然后创建管理员账号。这里我不厌其烦地提醒一句账号密码一定记好这个账号就是整个Jenkins的超级管理员后面开账号、配权限都靠它。密码强度不要太弱Jenkins面板暴露在办公网的话弱口令被扫到就是一场灾难。2.2 插件源换成国内源的正确姿势这是新手卡住重灾区。Jenkins默认的插件更新中心地址是updates.jenkins.io国内访问这个地址速度极其不稳定装插件经常失败。解决办法是把更新中心换成国内镜像。图形化路径“Manage Jenkins - Plugins - Advanced settings”把Update Site里的URL改成清华源https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json或者华为云源https://mirrors.huaweicloud.com/jenkins/updates/update-center.json但是这里有个超级隐蔽的坑我估计80%的人都被坑过只修改Update Site的URL是不够的。Jenkins会把这个update-center.json下载到本地并解析解析出来的每个插件的下载地址仍然指向官方国外的服务器。你看到的现象是插件列表刷出来了但安装时依然慢如蜗牛最后超时失败。正确的做法是改完后还要处理本地解析出来的配置文件。具体来说修改/var/lib/jenkins/hudson.model.UpdateCenter.xml把URL换成国内镜像地址。然后重启Jenkins等它重新拉取更新中心数据。接着编辑/var/lib/jenkins/updates/default.json把这个文件里所有包含官方下载地址的地方批量替换成国内镜像地址。这个文件很大用sed一把梭sed -i s#https://updates.jenkins.io/download#https://mirrors.tuna.tsinghua.edu.cn/jenkins#g /var/lib/jenkins/updates/default.json sed -i s#http://updates.jenkins.io/download#https://mirrors.tuna.tsinghua.edu.cn/jenkins#g /var/lib/jenkins/updates/default.json替换完重启Jenkins再去装插件效果立竿见影。注意如果镜像源上的插件版本和当前Jenkins版本不兼容安装时会出现红色警告。这种时候优先升级Jenkins主版本别强行装不然运行期各种诡异报错会让你怀疑人生。2.3 插件我一向只装这些插件本身不该贪多装多了全是负担。但有几类插件属于基础建设几乎每个团队都躲不开。我列一下我的基础清单Git源码管理必备没有它Job里连仓库地址都填不了Pipeline流水线任务支持写Jenkinsfile就靠它Publish Over SSH远程传文件和执行命令部署必备Allure测试报告插件DingTalk钉钉通知Credentials Binding在Pipeline里安全使用凭据这些插件在“Manage Jenkins - Plugins - Available plugins”里搜索安装就行。换完国内源之后安装过程通常一两分钟就结束。3. 第一个自动化任务从自由风格任务到流水线3.1 新建一个能跑的Freestyle任务插件就绪我们正式建第一个自动化构建任务。我故意先讲自由风格任务因为它操作直观适合把“源码管理、构建触发器、构建步骤”这三个核心概念讲清楚。在Jenkins主页点“新建任务”输入名称选择“Freestyle project”。进入配置页面后核心配置有这几项源码管理选GitRepository URL填仓库地址。如果仓库是私有的需要添加凭据。点“Add”选“Username with password”或者“SSH key”。SSH key方式要注意把Jenkins服务器的公钥添加到GitLab的部署密钥列表里。构建触发器这里没有Webhook之前可以先选“Poll SCM”填一个轮询表达式H/2 * * * *意思是每两分钟检查一次仓库有没有新提交有变化就触发。这种方式实时性不如Webhook但起步阶段好排查什么东西都能从日志里看到。构建步骤里选“执行shell”写实际命令。Java项目可以写mvn clean package -DskipTestsNode项目npm ci npm run build保存之后点“立即构建”然后点击构建号查看控制台输出。第一次构建跑通的感觉还是挺有成就感的。从这一刻起你的Jenkins才算是真正“用起来”了。3.2 环境变量和参数化构建构建脚本里如果全写死路径和名称过两个月你自己都会看着那一堆硬编码头疼。Jenkins内置了环境变量帮你在脚本里动态获取Job名、构建号、工作目录等信息。我用过最频繁的变量先列几个变量名含义示例值JOB_NAME任务名my-jobBUILD_NUMBER构建号42WORKSPACE工作目录/var/lib/jenkins/workspace/my-jobBUILD_URL本次构建完整URLhttp://jenkins:8080/job/my-job/42/GIT_COMMIT当前代码提交号a1b2c3d...GIT_BRANCH当前分支origin/main在“执行shell”里直接echo这些变量就能看到值。想看看还有哪些变量可用加一行env命令把整个环境变量表打印出来然后删掉就行。参数化构建是我强烈建议掌握的功能。在Job配置里勾选“参数化构建过程”添加一个String Parameter名字比如叫ENV默认值填dev。保存后构建时选择“Build with Parameters”可以自由修改参数在构建脚本里直接能用$ENV取到。这套机制在做多环境发布时是救命级的一个Job配合不同参数就能部署到测试、预发、生产不用复制三套任务出来。3.3 从自由风格迁移到流水线自由风格任务用多了你很快会遇到问题构建步骤散落在网页配置区每次改动都得登录Jenkins去点没法做代码审查也没法放进Git里做历史追溯。这时候就应该上流水线了。流水线有两种语法声明式和脚本式。新手直接学声明式结构清晰可读性好。一个最基础的声明式流水线长这样pipeline { agent any parameters { string(name: ENV, defaultValue: dev, description: 部署环境) } stages { stage(拉取代码) { steps { git url: http://gitlab.example.com/group/demo-api.git, branch: main, credentialsId: gitlab-ssh-key } } stage(代码构建) { steps { sh mvn clean package -DskipTests } } stage(输出产物) { steps { sh ls -lh target/*.jar } } } }写完之后新建任务时选“Pipeline”把脚本粘贴到Pipeline script里保存构建即可。但更专业的做法是把这段脚本保存为仓库根目录的Jenkinsfile文件然后任务配置里选“Pipeline script from SCM”指向存放Jenkinsfile的仓库。这样一来构建流程成了代码每人改都有记录出问题能回退。团队协作层面这比在网页上改配置靠谱一个量级。注意声明式流水线里stage名用中文没问题但agent、steps这些关键字必须是英文。如果脚本里要使用凭据推荐用withCredentials块不要把账号密码明文写在脚本里。4. 进阶实践GitLab自动触发、部署包上传、Allure报告和钉钉通知4.1 对接GitLab提交代码后自动构建轮询SCM说到底还是被动检查实时性差对GitLab服务器也是种负担。标准做法是用Webhook代码一提交GitLab主动通知Jenkins触发构建。先安装GitLab插件。装完后在“Manage Jenkins - Configure System”里找到GitLab配置区域填两件事Connection name自己起一个比如gitlab-connGitLab API Token这个Token要去GitLab个人设置里生成权限勾上api和read_repository。然后在Job配置的“构建触发器”里勾选“Build when a change is pushed to GitLab”页面下方会显示一个Webhook URLhttp://你的Jenkins地址/project/my-job复制这个URL去GitLab仓库设置里的Webhooks页面添加同时勾选Push events。保存后提交一次代码试试Webhook有没有生效。这里有个我反复踩的坑新版Jenkins默认开启CSRF防护GitLab推过来的请求校验不通过的话Webhook会返回403。解决办法是在Job触发器的Webhook URL下方有一个“Secret token”生成按钮点一下自动生成Token复制到GitLab Webhook配置里的Secret Token字段。两边配好后403基本不再出现。还有个容易忽略的点Jenkins填写的URL必须是GitLab能访问到的地址。如果Jenkins装在开发机用localhost配置Webhook那GitLab自然是访问不了的。这个错误很低级但每次出问题都有人犯。4.2 构建产物怎么传上目标服务器构建机把包打出来接下来就要面对我们真正关心的问题——部署。最常用的插件是Publish Over SSH。先在“Manage Jenkins - Configure System”里的“Publish over SSH”区域添加一个SSH Server。需要填主机名、端口、用户名、私钥。私钥建议用Jenkins服务器生成的专用密钥对把公钥追加到目标服务器对应用户的authorized_keys文件里。填完后点“Test Configuration”返回success才算通过。然后在Job的“构建后操作”里选择“Send build artifacts over SSH”配置传输规则。Source files填相对于工作目录的路径比如target/demo.jarRemote directory填目标服务器上的目录Exec command填传输完成后执行的命令比如systemctl restart demo-api这套流程非常直接而且传输结果和命令执行结果都会回传到Jenkins控制台排查问题方便。确实也有不用插件的做法直接在shell里scpscp target/demo.jar deploy192.168.1.10:/opt/app/demo/ ssh deploy192.168.1.10 systemctl restart demo-api这种方式的好处是不依赖插件坏处是得提前配好SSH免密而且报错信息没有Publish Over SSH那么清晰。我还是推荐插件方案尤其是团队里有人对Linux命令不熟的时候。4.3 集成Allure测试报告自动生成测试跑完之后一堆XML原始结果几乎没人看大家想要的是带趋势、带失败分类、能一眼定位问题的HTML报告这就是Allure的价值。系统层面需要先装Allure命令行工具装完确认allure命令能执行。Jenkins里装Allure插件。然后在流水线脚本里加一个Stagestage(测试报告) { steps { allure includeProperties: false, jdk: default, report: target/allure-report, results: [[path: target/allure-results]] } }这里有一个必须注意的前提results路径下必须真实存在allure-results目录否则插件直接报错。我习惯在测试阶段先执行mvn test生成原始结果再跑Allure聚合。构建完成后Job页面左侧会出现Allure Report入口点开就是清晰的HTML报告。补充一个细节Allure报告默认会保留每次构建的数据时间长了会积累大量文件。需要在流水线里定期清理旧的报告目录或者找时间手动清一下不然磁盘容易被悄悄占满。4.4 钉钉通知构建结果主动找上门构建失败不能只挂在Jenkins页面里等着有人来看得主动通知到人。钉钉机器人是团队协作里最常见的接收端。先去钉钉群里添加自定义机器人。安全设置选“自定义关键词”或“加签”都可以选加签的话会得到一个密钥后续请求需要用签名。创建成功后拿到Webhook地址填到Jenkins的DingTalk插件配置里。在流水线里发通知很简单post { success { dingtalk(robot: my-bot, notifyEveryone: true, message: 构建成功可以发布) } failure { dingtalk(robot: my-bot, notifyEveryone: true, message: 构建失败${env.BUILD_URL}) } }如果插件默认的消息格式满足不了需求更灵活的方式是用curl直接调钉钉机器人接口。钉钉的机器人消息支持markdown格式拼一个自定义消息发出去curl -X POST $WEBHOOK_URL \ -H Content-Type: application/json \ -d {msgtype:markdown,markdown:{title:构建通知,text:### 构建失败\n 分支: main\n 构建号: 42\n [查看日志]($BUILD_URL)},at:{isAtAll:false}}这种方式的好处是消息内容可以完全自定义塞入提交人、代码变更、测试通过率等任何你关心的信息。我这边生产上的通知脚本早期就是从这条curl命令长出来的。5. 常见问题与排查技巧实录5.1 内存不足导致构建卡死Jenkins本身是Java应用默认堆内存往往只有512MB并发一上来就卡。修改/etc/sysconfig/jenkins里的JENKINS_JAVA_OPTIONS把堆内存调大JENKINS_JAVA_OPTIONS-Djava.awt.headlesstrue -Xmx2048m -Xms512m改完重启。如果服务器内存本身就不大建议把并发执行器数量调小。在“Manage Nodes”里把内置节点的Number of executors从默认的2改成1。要不然多个构建同时跑CPU和内存瞬间被打满构建互相拖累看起来就像卡死。5.2 插件装不上或者列表都刷不出来插件安装失败九成是更新源的问题。按前面2.2节的步骤把更新中心和插件下载地址全部换成国内源再配合sed命令把本地解析出的JSON文件里的地址也一并替换。如果还是失败去日志文件/var/log/jenkins/jenkins.log看具体报错常见的原因有两个一是插件与Jenkins版本不兼容二是插件之间冲突。前者去插件管理页面换个兼容版本后者只能逐个排查卸载最近安装的插件试试。5.3 定时任务不执行或者时间差8小时Jenkins的定时表达式是基于服务器本地时区的。很多服务器默认是UTC时间于是你配的定时任务会比预期晚8小时执行。解决方案在“Manage Jenkins - Configure System”里找“User Defined Time Zone”填Asia/Shanghai保存后重启。另外提醒一个容易误解的地方Jenkins的cron和Linux crontab虽然很像但它支持一个H字母表示“为一个哈希运算出的随机值”。比如H/30 * * * *并不是固定每小时的00分、30分执行而是每30分钟执行一次具体几分由Jenkins自己算。如果业务上必须精确在00分和30分就写成0,30 * * * *。5.4 Webhook不触发或者一直403Webhook是高频踩坑点。403大概率是CSRF没过按4.1节配置Secret Token。不触发的排查路径我理一下第一在GitLab的Webhook设置页面点击Test看发送结果是200还是其他状态码第二确认Jenkins地址是GitLab能访问的别填localhost第三确认Job里勾选了构建触发器对应选项别只保存忘了勾。5.5 聊聊Jenkins与AI的新生态最近AI编程工具火得一塌糊涂里面有个词也传到了CI/CD圈子MCP全称Model Context Protocol。它是用来让AI助手调用外部工具的一套协议。社区里已经有人做了Jenkins的MCP服务端把查询构建状态、触发构建、获取日志这些操作封装成标准工具。配合支持MCP的AI客户端你可以直接说“帮我触发某某任务并看看结果”AI自己完成调用。这个生态还比较年轻但方向很明显未来CI/CD平台的日常操作会越来越轻AI充当操作员人来负责判断和兜底。不过我的建议始终是先把Jenkins本身的基础体系玩明白再去接这些新工具底子不稳的话AI只会帮你制造更多错误。6. 最后再分享几条实在的经验Jenkins用久了你会发现它本质上就是一个“把重复事情自动化”的调度中心真正的难度从来不在装上这个服务而在于把构建、测试、部署流程梳理清楚用流水线固化下来。我踩过无数坑之后的三个体会这里毫无保留地分享一下。第一Jenkinsfile一定要纳入Git版本管理。任何人对流水线的改动都留痕出了问题能明确知道是谁改的、改了什么回退也方便。把构建流程当成代码来管收益远超想象。第二从第一天就把权限控制好。管理员账号不要到处共享普通开发给Job级别的权限就够别的一律不给。等团队扩到几十人再回来收拾权限摊子会非常痛苦。第三定期备份/var/lib/jenkins目录。配置、插件、构建记录全在这一个目录里服务器挂了直接恢复。我见过太多人重装系统之后对着空白的Jenkins发呆那种绝望没必要经历。最后分享一个压箱底的小技巧在构建脚本开头加一行set -ex。作用很简单——shell每执行一条命令先把命令本身打印出来一旦任何一条命令失败立即终止整个构建。排查“构建失败但不知道卡在哪一步”的时候这个参数比任何调试工具都好用。Jenkins的坑是踩不完的但每解决一个整套流程就会顺滑一点。希望这篇能帮你少走几条弯路尽早把自动化流水线跑起来。
返回列表