喝杯咖啡,一鍵部署完成!
背景
新項(xiàng)目沒(méi)有完善的部署流程,只能自己先搭一套來(lái)頂一頂了。
服務(wù)器資源如下:
原理圖如下所示:
Jenkins 打包部署原理圖
- Jenkins 部署在一臺(tái)服務(wù)器上,然后安裝了很多必備的 Jenkins 插件。比如拉取 Gitlab 倉(cāng)庫(kù)代碼的插件、遠(yuǎn)程執(zhí)行命令和拷貝文件的插件。
- Jenkins 開(kāi)始運(yùn)行一個(gè)任務(wù)時(shí),通過(guò) Git 插件從 Gitlab 倉(cāng)庫(kù)拉取代碼到本地目錄。
- Jenkins 通過(guò) JDK 和 Maven 工具對(duì) Java 代碼進(jìn)行打包部署。
- Jenkins 通過(guò) SSH 插件執(zhí)行遠(yuǎn)程命令,將包進(jìn)行備份、清理操作。
- Jenkins 將 JAR 包拷貝到遠(yuǎn)程服務(wù)器的固定目錄下。
- Jenkins 執(zhí)行遠(yuǎn)程命令,更新服務(wù)。
Jenkins 簡(jiǎn)易安裝教程
Jenkins 官方網(wǎng)站對(duì) Jenkins 如何安裝已經(jīng)講解得非常清晰了,所以這里不再贅述,貼一下官方網(wǎng)站,自行去看吧。
Jenkins 下載地址:
https://www.jenkins.io/download/
Jenkins 安裝步驟:
https://www.jenkins.io/doc/book/installing/
安裝完成后,我們需要配置 Jenkins。
配置 Jenkins
因?yàn)槲覀円虬渴鸬捻?xiàng)目是 Java 項(xiàng)目,所以需要將 Java JDK 所在的目錄和 Maven 所在目錄配置到 Jenkins 中,這樣 Jenkins 打包時(shí)就能利用這兩個(gè)工具進(jìn)行打包。
配置全局工具:Maven
配置如下:
Jenkins配置入口
Jenkins Global Tool Configuration
配置環(huán)境變量:
- Java JDK
- Maven
全局屬性配置
上面的配置完成后,我們就可以測(cè)試下是否可以將代碼倉(cāng)庫(kù)中的某個(gè)分支的代碼拉取下來(lái)進(jìn)行打包。
通過(guò) Jenkins 一鍵部署
在使用 Jenkins 時(shí),我們必須創(chuàng)建一個(gè)任務(wù)才行,然后這個(gè)任務(wù)里面可以配置要執(zhí)行的各種操作。
Jenkins中自動(dòng)構(gòu)建項(xiàng)目的類型有很多,常用的有以下三種:
- 自由風(fēng)格軟件項(xiàng)目(FreeStyle Project)
- Maven項(xiàng)目(Maven Project)
- 流水線項(xiàng)目(Pipeline Project)
每種類型的構(gòu)建其實(shí)都可以完成一樣的構(gòu)建過(guò)程與結(jié)果,只是在操作方式、靈活度等方面有所區(qū)別,在
實(shí)際開(kāi)發(fā)中可以根據(jù)自己的需求和習(xí)慣來(lái)選擇。
下面演示創(chuàng)建一個(gè)簡(jiǎn)單的自由風(fēng)格項(xiàng)目來(lái)完成項(xiàng)目的集成過(guò)程:
拉取代碼->編譯 Java 項(xiàng)目->備份服務(wù)器 JAR 包->刪除服務(wù)器 JAR 包->拷貝 JAR 包到服務(wù)器->更新服務(wù)。
創(chuàng)建一個(gè)項(xiàng)目
創(chuàng)建一個(gè)項(xiàng)目
創(chuàng)建成功后就會(huì)出現(xiàn)一條記錄:
Dashboard 界面
為了測(cè)試我們的 Jenkins 是否能正常拉取代碼并打包,我們需要配置 Gitlab 代碼倉(cāng)庫(kù)的地址、用戶名、密碼。
配置拉取的代碼倉(cāng)庫(kù)
- 倉(cāng)庫(kù) URL
- 用戶名和密碼
配置拉取的代碼倉(cāng)庫(kù)地址和認(rèn)證方式
配置打包
配置 Maven 打包
echo "開(kāi)始打包"
mvn clean package
echo "打包完成"
配置到這一步后,我們可以先驗(yàn)證下這些配置是否生效。
運(yùn)行項(xiàng)目
在 Dashboard 可以看到配置完成的任務(wù),點(diǎn)擊 Build Now 按鈕即可開(kāi)始拉取代碼、打包項(xiàng)目。
我們還可以從控制臺(tái)輸出看到打包記錄。
Jenkins 會(huì)從 Gitlab 倉(cāng)庫(kù)拉取指定分支的代碼,然后運(yùn)行 mvn clean package 命令,進(jìn)行打包。
打印 Jenkins 運(yùn)行項(xiàng)目的結(jié)果
輸出記錄中打印出了以下關(guān)鍵信息:代碼拉取后存放在哪,打的 jar 包在哪。
代碼和生成的 jar 包在到這個(gè)根目錄找到:
C:\ProgramData\Jenkins.jenkins\workspace\passjava-dev
還可以從打印日志的最后看到這次打包用時(shí) 2 min 33 秒,任務(wù)的執(zhí)行狀態(tài)為 Finished Success。
接下來(lái)就是將這些 JAR 包拷貝到遠(yuǎn)程服務(wù)器地址。
拷貝安裝包
安裝插件
拷貝安裝包需要用到一個(gè)插件:Publish Over SSH。
Dashboard>Manage Jenkins->插件管理->Avaliable plugins。
下圖是已經(jīng)安裝好了這款插件的截圖。
Jenkins 插件管理
配置這個(gè)插件的全局配置:
- SSH Server Name:遠(yuǎn)程服務(wù)器的名字,后面在配置拷貝包的時(shí)候可以根據(jù)名字選擇拷貝到哪臺(tái)服務(wù)器。
- Hostname:SSH Server 的 Hostname。
- Username:SSH Server 登錄名和密碼或密鑰。
- Remote Directory:指定將文件拷貝到哪個(gè)目錄。
配置遠(yuǎn)程服務(wù)器地址
備份服務(wù)器 JAR 包
在上傳打包好的 JAR 包之前,需要將應(yīng)用服務(wù)器上的 JAR 備份。
備份的步驟如下:
- 在遠(yuǎn)程服務(wù)器創(chuàng)建一個(gè)備份目錄 bak。
- 在備份目錄bak上創(chuàng)建一個(gè)以當(dāng)前時(shí)間作為目錄名的目錄。
- 將遠(yuǎn)程服務(wù)器的上 JAR 重命名為原文件名+時(shí)間戳的名字。
備份服務(wù)器 JAR 包
拷貝 JAR 包到遠(yuǎn)程服務(wù)器
需要配置以下內(nèi)容:
- SSH Server:指定要將文件拷貝到哪個(gè)服務(wù)器,格式為 <用戶名>@<ip 地址>。
- Transfer Set Source files:jenkins 編譯后的 JAR 地址。通過(guò)之前的編譯信息我們知道,JAR 包地址在如下路徑:
C:\ProgramData\Jenkins.jenkins\workspace<Jenkins 任務(wù)名><編譯目錄>
- Remove prefix:要移除的文件路徑前綴。
- Remte directory:拷貝到哪個(gè)路徑下,如果之前已經(jīng)配置過(guò)全局的文件夾,則拷貝的文件會(huì)放到 <全局文件夾>/之下,如果全局文件夾之下沒(méi)有這個(gè) Remote directory 目錄,則創(chuàng)建一個(gè)。這里我們不需要配置,全局配置已經(jīng)可以滿足條件了。
- 如果還有其他 JAR 包也需要拷貝則需要再添加一項(xiàng)。
拷貝多個(gè) JAR 包到遠(yuǎn)程服務(wù)器
滾動(dòng)更新服務(wù)
項(xiàng)目采用的 Docker Swarm 方式來(lái)管理集群中的微服務(wù)。
Jenkins 通過(guò) 插件 發(fā)送命令到應(yīng)用服務(wù)器上執(zhí)行指定的腳本
配置遠(yuǎn)程執(zhí)行腳本的命令
echo "部署 jar 包"
cd /nfs-data/wukong/
nohup sudo sh restart.sh
exit
這個(gè)命令使用 nohup 和 sudo 權(quán)限來(lái)執(zhí)行名為 restart.sh 的腳本。nohup 命令用于將腳本在后臺(tái)運(yùn)行,即使終端會(huì)話結(jié)束,腳本仍然繼續(xù)運(yùn)行。
遠(yuǎn)程服務(wù)器上創(chuàng)建腳本
如果想要 jenkins 執(zhí)行遠(yuǎn)程服務(wù)器上的腳本,則需要先在遠(yuǎn)程服務(wù)器上創(chuàng)建一個(gè)可執(zhí)行的腳本。
這里我們需要重啟服務(wù)器的容器服務(wù),所以在這個(gè)目錄 /nfs-data/wukong/ 編寫(xiě)一個(gè) restart.sh 腳本。
echo "部署 passjava 服務(wù)"
nohup sudo docker service update accountservice --force > /nfs-data/wukong/jenkins/account.txt
nohup sudo docker service update gatewayservice --force > /nfs-data/wukong/jenkins/gateway.txt
nohup sudo docker service update qmsservice --force > /nfs-data/wukong/jenkins/qms.txt
這個(gè)命令使用--force選項(xiàng)來(lái)更新名為"accountservice、gatewayservice、qmsservice"的 Docker 服務(wù)。命令的輸出被重定向到文件/nfs-data/wukong/jenkins/xxx.txt中。
部署
再次測(cè)試是否能正確編譯代碼,上傳 jar 包,部署微服務(wù)。
部署結(jié)果如下:Finished: SUCESS
部署結(jié)果
遇到的問(wèn)題
問(wèn)題 1、添加 Git 倉(cāng)庫(kù)時(shí),無(wú)法訪問(wèn)
SSL certificate problem: unable to get local issuer certificate
解決方案:
git config --system http.sslVerify false
git config --global http.sslVerify false
參考鏈接:https://stackoverflow.com/questions/39746535/jenkins-git-ssl-certificate-error
問(wèn)題 2
stderr: fatal: unable to access 'url of my git/': SSL certificate problem: self signed certificate in certificate chain
解決方案:
git config --system http.sslVerify false
git config --global http.sslVerify false
參考鏈接:https://stackoverflow.com/questions/39746535/jenkins-git-ssl-certificate-error
問(wèn)題 3
Exception when publishing, exception message
問(wèn)題 3 的記錄
解決方案
遠(yuǎn)程機(jī)器上需要用 sudo 命令執(zhí)行 docker 命令,這個(gè)時(shí)候需要輸入密碼,通過(guò)配置賬號(hào) xx 執(zhí)行 sudo 命令不需要輸入密碼。
解決思路
問(wèn)題 3 的解決思路
問(wèn)題 4:could not identify password for [xxx]
問(wèn)題 4 解決思路
問(wèn)題 5:ssh 超時(shí)配置
ERROR: Exception when publishing, exception message [Exec timed out or was interrupted after 120,011 ms]
問(wèn)題 5 的記錄
解決方案:修改超時(shí)時(shí)間設(shè)置
問(wèn)題 5 的解決方案
關(guān)于我
InfoQ 簽約作者、藍(lán)橋簽約作者、阿里云專家博主、51CTO 紅人。