害你加班的bug就是我寫的,記一次升級Jenkins外掛引發的加班
阿新 • • 發佈:2020-05-27
## 主旨
本文主要記錄了下Jenkins升級外掛過程中出現的場景,一次加班經歷,事發時沒有截圖,有興趣可以看看。
## 起因
### 需求
最近有個需求:在Jenkins流水線中完成下載Git上的檔案簡單修改並提交的功能
起初找到了相關的外掛用法,即使用 `SSH Agent Plugin` 來完成這個功能
### 外掛不生效
經測試無法完成效果,分別懷疑了以下幾點:
- 憑據配置有誤
- 寫錯了指令碼
- 當前未安裝此外掛
- 當前外掛版本過低
- 當前外掛由於某種原因未生效
### 排查不生效原因
經排查,發現的確沒有生效,原因是之前運維同事做遷移時做的一系列騷操作搞的:
- 用最新的Jenkins war包部署 + 老版本Jenkins家目錄
- 由於新版本需要使用新版本的外掛才能生效,升級了所有外掛
- 升級完重啟,啟動不起來了……
- 回退老版本war包,繼續使用當前升級過外掛的Jenkins家目錄
- 在外掛管理處,按提示降級了部分外掛
### 預感
等我看到 `Manage Jenkins` 那一片紅的時候,就有預感這次要不簡單,當時也沒多想,去檢查了下 `SSH Agent Plugin` 的版本
### 升級外掛
發現提示Warn 需要升級此外掛到某版本及以後,外掛方能生效,沒多想,升級就是了
沒想此舉為我昨晚的加班,打開了潘多拉魔盒…… **升級完重啟,啟動不起來了!**
### Jenkins掛機
啟動報錯如下:(昨晚沒心情截圖,直接搜的錯誤)
```bash
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.(Jenkins.java:904)
at hudson.model.Hudson.(Hudson.java:85)
at hudson.model.Hudson.(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 的相關問題解決辦法](https://stackoverflow.com/questions/55898685/after-updating-plugin-role-strategy-plugin-jenkins-is-not-working)
說是因為升級了 `Role-based Authorization Strategy` 外掛會導致這個問題,What?? 我沒升級它啊,這怎麼回事!先看看外國老哥的解法:
![](https://img2020.cnblogs.com/blog/1149398/202005/1149398-20200527110534081-238922932.png)
簡述解法:
1. 備份下 Jenkins 家目錄下的 config.xml
2. 修改原 config.xml,註釋掉 `authorizationStrategy` 塊,修改 `useSecurity` 為 true
3. 重啟服務,訪問成功再關閉服務
4. 恢復 config.xml 備份 替換 config.xml
5. 重啟服務
按這一套操作後,的確服務能起來了
### 工程蒸發,引發的思考
接下來發現了另一個問題 ———— **所有工程都沒了!!**
先顧不上工程蒸發了的問題,手動建立了個測試流水線工程來測下 `SSH Agent Plugin` 是否生效,發現依舊無效
工程沒了問題其實不大,因為`使用者還在`、`許可權還在`、`構建工程的流水線指令碼在 GitLab 上`,大不了再配置一下就行了
我想了下,就算配置好工程後,`使 SSH Agent Plugin 外掛生效` 還沒完成啊,外掛版本還是亂成了一鍋粥,這不是定時炸彈麼
簡單瞭解了下,Jenkins 的外掛升級後,降級的版本是有一個預設值的,但這個值不一定是當前 Jenkins 版本預設或可用的值,最好的辦法是向上升級
思及此節,決定去升級下 Jenkins 及外掛,另闢了一處`實驗場`開搞
### 備份Jenkins家目錄
Jenkins 家目錄裡最大的部分是 workspace 這個目錄,就是每個構建工程執行時的家目錄的父級,這個目錄裡的資料無需備份
將 Jenkins 家目錄備走後,手動建立 workspace 目錄,以防新工程無法構建
### 下載新war包,部署Tomcat
在中科大的靜像站下載了2.222.3的war包
部署到Tomcat的ROOT目錄下
修改Tomcat conf/server.xml,修改 Tomcat 編碼為UTF-8
![](https://img2020.cnblogs.com/blog/1149398/202005/1149398-20200527114101093-354532564.png)
修改 conf/context.xml,修改靜態資源快取最大值,需新增一行 ` `
![](https://img2020.cnblogs.com/blog/1149398/202005/1149398-20200527114324765-1672399616.png)
啟動Tomcat
### 訪問測試Jenkins服務,檢視外掛錯誤警告
訪問服務後,發現服務還可以登入,進來看到工程都還在!點開 `Manage Jenkins` 處,發現仍是大面積報紅,檢查發現是 `Pipeline` 依賴的元件不正確,按錯誤提示去 pluginManager updates處找到被依賴的外掛,按提示升級,升級完重啟(大部分外掛需要重啟以啟用)
重啟後,Pipeline相關的錯誤不在了,再去看其他的,直到所有的都解決了,外掛也都正常了
除了之前外掛上的報紅,還有幾處安全提示,我們的Jenkins不連外網,就一併關掉了
![](https://img2020.cnblogs.com/blog/1149398/202005/1149398-20200527115810952-1236600245.png)
最後 `Manage Jenkins` 就變成了這樣
![](https://img2020.cnblogs.com/blog/1149398/202005/1149398-20200527115900799-1143298115.png)
### 備份,恢復服務
備份原服務家目錄,將新版本部署到原 Tomcat,還原新版本家目錄,重啟服務
> 在恢復過程中,有提示某些資料 Unreadable,這些可以通過點選提示,管理這些舊資料,我這邊因為主要的東西都在,就選了清除不可讀資料了
### 後續工程修復,測試外掛
所有失而復得的工程,其實只記錄了內部的一些引數,但 SCM 如Git,這些流水線指令碼資訊都沒記錄,可能是因為 Git 外掛升級所致
苦逼的一個一個加回來,好在工程不多,也就10來個,等所有工程修復好後,我測試了下之前失效的外掛,外掛可用了 :happy:
## 結尾
寫這段文字主要記錄一下這件挺坑的事,警示自己或大家,**不要在沒備份的情況下,去做一些不可逆的操作**,比如升級 Jenkins,備份的作用同樣適用於其他場景