害你加班的bug就是我写的,记一次升级Jenkins插件引发的加班
主旨
本文主要记录了下Jenkins升级插件过程中出现的场景,一次加班经历,事发时没有截图,有兴趣可以看看。
起因
需求
最近有个需求:在Jenkins流水线中完成下载Git上的文件简单修改并提交的功能
起初找到了相关的插件用法,即使用 SSH Agent Plugin
来完成这个功能
插件不生效
经测试无法完成效果,分别怀疑了以下几点:
- 凭据配置有误
- 写错了脚本
- 当前未安装此插件
- 当前插件版本过低
- 当前插件由于某种原因未生效
排查不生效原因
经排查,发现的确没有生效,原因是之前运维同事做迁移时做的一系列骚操作搞的:
- 用最新的Jenkins war包部署 + 老版本Jenkins家目录
- 由于新版本需要使用新版本的插件才能生效,升级了所有插件
- 升级完重启,启动不起来了……
- 回退老版本war包,继续使用当前升级过插件的Jenkins家目录
- 在插件管理处,按提示降级了部分插件
预感
等我看到 Manage Jenkins
那一片红的时候,就有预感这次要不简单,当时也没多想,去检查了下 SSH Agent Plugin
的版本
升级插件
发现提示Warn 需要升级此插件到某版本及以后,插件方能生效,没多想,升级就是了
没想此举为我昨晚的加班,打开了潘多拉魔盒…… 升级完重启,启动不起来了!
Jenkins挂机
启动报错如下:(昨晚没心情截图,直接搜的错误)
com.thoughtworks.xstream.mapper.CannotResolveClassException: com.michelin.cio.hudson.plugins.rolestrategy.RoleBasedAuthorizationStrategyat com.thoughtworks.xstream.mapper.DefaultMapper.realClass(DefaultMapper.java:79)atcom.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.DynamicProxyMapper.realClass(DynamicProxyMapper.java:55)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.PackageAliasingMapper.realClass(PackageAliasingMapper.java:88)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.ClassAliasingMapper.realClass(ClassAliasingMapper.java:79)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.ArrayMapper.realClass(ArrayMapper.java:74)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.SecurityMapper.realClass(SecurityMapper.java:71)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at hudson.util.XStream2$CompatibilityMapper.realClass(XStream2.java:379)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at org.jenkinsci.jruby.JRubyMapper.realClass(JRubyMapper.java:34)
at hudson.util.xstream.MapperDelegate.realClass(MapperDelegate.java:43)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.CachingMapper.realClass(CachingMapper.java:48)
at hudson.util.RobustReflectionConverter.determineType(RobustReflectionConverter.java:461)
at hudson.util.RobustReflectionConverter.doUnmarshal(RobustReflectionConverter.java:327)
Caused: jenkins.util.xstream.CriticalXStreamException: com.michelin.cio.hudson.plugins.rolestrategy.RoleBasedAuthorizationStrategy : com.michelin.cio.hudson.plugins.rolestrategy.RoleBasedAuthorizationStrategy
---- Debugging information ----
message : com.michelin.cio.hudson.plugins.rolestrategy.RoleBasedAuthorizationStrategy
cause-exception : com.thoughtworks.xstream.mapper.CannotResolveClassException
cause-message : com.michelin.cio.hudson.plugins.rolestrategy.RoleBasedAuthorizationStrategy
class : hudson.model.Hudson
required-type : hudson.model.Hudson
converter-type : hudson.util.RobustReflectionConverter
path : /hudson/authorizationStrategy
line number : 11
version : not available
-------------------------------
at hudson.util.RobustReflectionConverter.doUnmarshal(RobustReflectionConverter.java:356)
at hudson.util.RobustReflectionConverter.unmarshal(RobustReflectionConverter.java:270)
at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72)
at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:65)
at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66)
at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:50)
at com.thoughtworks.xstream.core.TreeUnmarshaller.start(TreeUnmarshaller.java:134)
at com.thoughtworks.xstream.core.AbstractTreeMarshallingStrategy.unmarshal(AbstractTreeMarshallingStrategy.java:32)
at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:1189)
at hudson.util.XStream2.unmarshal(XStream2.java:161)
at hudson.util.XStream2.unmarshal(XStream2.java:132)
at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:1173)
at hudson.XmlFile.unmarshal(XmlFile.java:178)
Caused: java.io.IOException: Unable to read /var/lib/jenkins/config.xml
at hudson.XmlFile.unmarshal(XmlFile.java:181)
at hudson.XmlFile.unmarshal(XmlFile.java:161)
at jenkins.model.Jenkins.loadConfig(Jenkins.java:3005)
at jenkins.model.Jenkins.access$1300(Jenkins.java:304)
at jenkins.model.Jenkins$13.run(Jenkins.java:3104)
at org.jvnet.hudson.reactor.TaskGraphBuilder$TaskImpl.run(TaskGraphBuilder.java:169)
at org.jvnet.hudson.reactor.Reactor.runTask(Reactor.java:296)
at jenkins.model.Jenkins$5.runTask(Jenkins.java:1066)
at org.jvnet.hudson.reactor.Reactor$2.run(Reactor.java:214)
at org.jvnet.hudson.reactor.Reactor$Node.run(Reactor.java:117)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused: org.jvnet.hudson.reactor.ReactorException
at org.jvnet.hudson.reactor.Reactor.execute(Reactor.java:282)
at jenkins.InitReactorRunner.run(InitReactorRunner.java:48)
at jenkins.model.Jenkins.executeReactor(Jenkins.java:1100)
at jenkins.model.Jenkins.<init>(Jenkins.java:904)
at hudson.model.Hudson.<init>(Hudson.java:85)
at hudson.model.Hudson.<init>(Hudson.java:81)
at hudson.WebAppMain$3.run(WebAppMain.java:233)
Caused: hudson.util.HudsonFailedToLoad
at hudson.WebAppMain$3.run(WebAppMain.java:250)
经过
按错误信息排解问题
发现问题不可怕,一顿 Google Bing 发现了 StackOverFlow 的相关问题解决办法
说是因为升级了 Role-based Authorization Strategy
插件会导致这个问题,What?? 我没升级它啊,这怎么回事!先看看外国老哥的解法:
简述解法:
- 备份下 Jenkins 家目录下的 config.xml
- 修改原 config.xml,注释掉
authorizationStrategy
块,修改useSecurity
为 true - 重启服务,访问成功再关闭服务
- 恢复 config.xml 备份 替换 config.xml
- 重启服务
按这一套操作后,的确服务能起来了
工程蒸发,引发的思考
接下来发现了另一个问题 ———— 所有工程都没了!!
先顾不上工程蒸发了的问题,手动创建了个测试流水线工程来测下 SSH Agent Plugin
是否生效,发现依旧无效
工程没了问题其实不大,因为用户还在
、权限还在
、构建工程的流水线脚本在 GitLab 上
,大不了再配置一下就行了
我想了下,就算配置好工程后,使 SSH Agent Plugin 插件生效
还没完成啊,插件版本还是乱成了一锅粥,这不是定时炸弹么
简单了解了下,Jenkins 的插件升级后,降级的版本是有一个默认值的,但这个值不一定是当前 Jenkins 版本默认或可用的值,最好的办法是向上升级
思及此节,决定去升级下 Jenkins 及插件,另辟了一处实验场
开搞
备份Jenkins家目录
Jenkins 家目录里最大的部分是 workspace 这个目录,就是每个构建工程运行时的家目录的父级,这个目录里的数据无需备份
将 Jenkins 家目录备走后,手动创建 workspace 目录,以防新工程无法构建
下载新war包,部署Tomcat
在中科大的静像站下载了2.222.3的war包 https://mirrors.ustc.edu.cn/jenkins/war-stable/2.222.3/
部署到Tomcat的ROOT目录下
修改Tomcat conf/server.xml,修改 Tomcat 编码为UTF-8
修改 conf/context.xml,修改静态资源缓存最大值,需添加一行 <Resources cachingAllowed="true" cacheMaxSize="100000" />
启动Tomcat
访问测试Jenkins服务,查看插件错误警告
访问服务后,发现服务还可以登录,进来看到工程都还在!点开 Manage Jenkins
处,发现仍是大面积报红,检查发现是 Pipeline
依赖的组件不正确,按错误提示去 pluginManager updates处找到被依赖的插件,按提示升级,升级完重启(大部分插件需要重启以激活)
重启后,Pipeline相关的错误不在了,再去看其他的,直到所有的都解决了,插件也都正常了
除了之前插件上的报红,还有几处安全提示,我们的Jenkins不连外网,就一并关掉了
最后 Manage Jenkins
就变成了这样
备份,恢复服务
备份原服务家目录,将新版本部署到原 Tomcat,还原新版本家目录,重启服务
在恢复过程中,有提示某些数据 Unreadable,这些可以通过点击提示,管理这些旧数据,我这边因为主要的东西都在,就选了清除不可读数据了
后续工程修复,测试插件
所有失而复得的工程,其实只记录了内部的一些参数,但 SCM 如Git,这些流水线脚本信息都没记录,可能是因为 Git 插件升级所致
苦逼的一个一个加回来,好在工程不多,也就10来个,等所有工程修复好后,我测试了下之前失效的插件,插件可用了 :happy:
结尾
写这段文字主要记录一下这件挺坑的事,警示自己或大家,不要在没备份的情况下,去做一些不可逆的操作,比如升级 Jenkins,备份的作用同样适用于其他场景