手把手教你用 Jenkins 自動部署 SpringBoot!
1. 什么是 CI/CD
CI/CD 是一種通過在應(yīng)用開發(fā)階段引入自動化來頻繁向客戶交付應(yīng)用的方法。
CI/CD 的核心概念可以總結(jié)為三點:
- 持續(xù)集成
- 持續(xù)交付
- 持續(xù)部署
CI/CD 主要針對在集成新代碼時所引發(fā)的問題(俗稱"集成地獄")。
為什么會有集成地獄這個“雅稱”呢?大家想想我們一個項目部署的過程,拉取代碼->構(gòu)建->測試->打包->部署,如果我們經(jīng)常需要部署項目,特別是在微服務(wù)時代,服務(wù)特別多的情況下,不停的測試打包部署,那估計得有個人一整天專門做這事了,而這事又是繁瑣的重復(fù)無意義的。
具體而言,CI/CD 可讓持續(xù)自動化和持續(xù)監(jiān)控貫穿于應(yīng)用的整個生命周期(從集成和測試階段,到交付和部署),這些關(guān)聯(lián)的事務(wù)通常被統(tǒng)稱為"CI/CD 管道",由開發(fā)和運維團(tuán)隊以敏捷方式協(xié)同支持。
1.1 CI(Continuous Integration)
CI/CD 中的"CI"始終指持續(xù)集成,它屬于開發(fā)人員的自動化流程。成功的 CI 意味著應(yīng)用代碼的新更改會定期構(gòu)建、測試并合并到代碼倉庫中,該解決方案可以解決在一次開發(fā)中有太多應(yīng)用分支,從而導(dǎo)致相互沖突的問題。
1.2 CD(Continuous Delivery/Continuous Deployment)
CI/CD 中的"CD"指的是持續(xù)交付和/或持續(xù)部署,這些相關(guān)概念有時會交叉使用。兩者都事關(guān)管道后續(xù)階段的自動化,但它們有時也會單獨使用,用于說明自動化程度。
持續(xù)交付(Continuous Delivery)通常是指開發(fā)人員對應(yīng)用的更改會自動進(jìn)行錯誤測試并上傳到代碼倉庫(如 GitHub、GitLab 等),然后由運維團(tuán)隊將其部署到實時生產(chǎn)環(huán)境中。這旨在解決開發(fā)和運維團(tuán)隊之間可見性及溝通較差的問題。因此,持續(xù)交付的目的就是確保盡可能減少部署新代碼時所需的工作量。
持續(xù)部署(Continuous Deployment)指的是自動將開發(fā)人員的更改從代碼倉庫發(fā)布到生產(chǎn)環(huán)境,以供客戶使用。通過一套全自動化的流程,來解決手動測試、編譯、打包等操作。持續(xù)部署以持續(xù)交付的優(yōu)勢為根基,實現(xiàn)了管道后續(xù)階段的自動化。
2. 什么是 Jenkins
前面說的 CI/CD 算是一種思想,思想要落地,就需要對應(yīng)的工具。
Jenkins 是一款開源的 CI/CD 軟件,可以算是 CI/CD 軟件領(lǐng)導(dǎo)者,它提供了超過 1000 個插件來支持構(gòu)建、部署、自動化,基本上能夠滿足任何項目的需要。
整體來說,Jenkins 有如下六大特點:
- 持續(xù)集成和持續(xù)交付
作為一個可擴展的自動化服務(wù)器,Jenkins 可以用作簡單的 CI 服務(wù)器,或者變成任何項目的持續(xù)交付中心。
- 簡易安裝
Jenkins 是一個基于 Java 的獨立程序,可以立即運行,包含 Windows、Mac OS X 和其他類 Unix 操作系統(tǒng)。
- 配置簡單
Jenkins 可以通過其網(wǎng)頁界面輕松設(shè)置和配置,其中包括即時錯誤檢查和內(nèi)置幫助。
- 插件
通過更新中心中的 1000 多個插件,Jenkins 集成了持續(xù)集成和持續(xù)交付工具鏈中幾乎所有的工具。
- 擴展
Jenkins 可以通過其插件架構(gòu)進(jìn)行擴展,從而為 Jenkins 可以做的事提供幾乎無限的可能性。
- 分布式
Jenkins 可以輕松地在多臺機器上分配工作,幫助更快速地跨多個平臺推動構(gòu)建、測試和部署。
其實 Jenkins 有很多好玩的用法,今天我還是想先通過一個簡單的案例,先來和大家捋一捋如何使用 Jenkins 來實現(xiàn)一個 Spring Boot 項目的自動發(fā)布部署,這樣大家對 Jenkins 現(xiàn)有一個直觀的認(rèn)知,各種其他使用細(xì)節(jié)松哥在以后的文章中再來和大家細(xì)聊。
3. 準(zhǔn)備工作
3.1 整體規(guī)劃
我們先來通過如下一張圖片來看下 Jenkins 在整個流程中扮演的角色:
結(jié)合第一二小節(jié)的介紹,這張圖應(yīng)該很好理解。
3.2 準(zhǔn)備代碼
提前準(zhǔn)備好測試代碼,并上傳到代碼倉庫中。為了更加逼真一些,小伙伴們可以將這個代碼倉庫設(shè)置為私有的,這樣將來可以檢驗 Jenkins 中的配置是否正確。
考慮到 GitHub 網(wǎng)絡(luò)有時候不穩(wěn)定,我這里使用了 Gitee,一個很簡單的 Spring Boot 工程,里邊有一個 hello 接口,僅此而已。
我的代碼倉庫地址(私有倉庫):
https://gitee.com/lenve/jenkins_demo.git
3.3 準(zhǔn)備服務(wù)器
理論上,我們需要一臺服務(wù)器用來跑 Jenkins,還需要一臺服務(wù)器作為我的應(yīng)用服務(wù)器,但是我手頭沒有多余的服務(wù)器,所以我就將 Jenkins 和我的 Spring Boot 項目部署到一臺服務(wù)器上,在接下來的文章中我會和大家說明每個配置是針對 Jenkins 的還是針對 Spring Boot 的。
另外,有的小伙伴可能是在虛擬機上做實驗,因為將來我們的代碼提交到 Gitee 之后,Gitee 會通過一個 POST 請求將這個事件告知 Jenkins,進(jìn)而觸發(fā) Jenkins 的構(gòu)建操作。所以這就要求 Gitee 能夠訪問到你的 Jenkins 服務(wù)器,所以如果你的 Jenkins 剛好搭建在服務(wù)器上,這事就很容易了,但如果是搭建在虛擬機里,就得通過花生殼之類的內(nèi)網(wǎng)穿透工具來輔助你的工作了,比較麻煩,而且花生殼網(wǎng)速也慢。
不過小伙伴們不必?fù)?dān)心,如果你在虛擬上搭建的 Jenkins,并且不愿意折騰花生殼,那么也可以通過手動構(gòu)建/定時構(gòu)建的方式去完成項目構(gòu)建的。
4. 搭建 Jenkins
為了省事,我決定用 Docker 搭建 Jenkins,一行命令搞定。
為了操作方便,我們將 Jenkins 的工作目錄映射到我的宿主機中來,因此首先在宿主機中準(zhǔn)備一個數(shù)據(jù)目錄(不是必須):
# 創(chuàng)建 jenkins 目錄
mkdir /data/jenkins_home/
# 修改目錄的所有者,以便于 Jenkins 容器能夠操作該目錄
chown -R 1000:1000 /data/jenkins_home/
接下來創(chuàng)建并啟動 Jenkins 容器,同時掛載數(shù)據(jù)卷:
docker run -d --name jenkins -p 8088:8080 -p 50000:50000 -v /data/jenkins_home:/var/jenkins_home jenkins/jenkins
由于 Jenkins 在運行的時候需要用到 maven,所以有的人會選擇將 maven 目錄也作為掛載點,但是我覺得沒有必要,特別是對于初學(xué)者而言,這塊很容易出錯,不如將 maven 將來直接拷貝到 Jenkins 容器中,這樣反而省事一些。
執(zhí)行如上命令,安裝成功之后,瀏覽器輸入 http://localhost:8088 就可以訪問了。
然后稍等片刻,就可以訪問 Jenkins 了:
訪問之前,首先需要解鎖 Jenkins,解鎖密碼位置網(wǎng)頁上列出來了,但是由于我們創(chuàng)建容器的時候設(shè)置了數(shù)據(jù)卷,所以,現(xiàn)在直接去宿主機的 /data/jenkins_home/secrets/initialAdminPassword 位置查看初始化密碼,如下:
在網(wǎng)頁中,輸入密碼然后繼續(xù)。接下來會讓我們選擇需要的插件,第一次使用,安裝推薦插件即可。
如果因為網(wǎng)絡(luò)原因安裝失敗,可以點擊重試按鈕進(jìn)行重試。
接下來創(chuàng)建一個新的用戶,也可以不創(chuàng)建新的用戶,直接使用 admin 即可:
再設(shè)置 Jenkins 訪問地址:
這個頁面有亂碼,不過不影響,設(shè)置完成后,我們點擊保存并完成按鈕即可。接下來就可以進(jìn)入到 Jenkins 中了。
整個過程執(zhí)行完畢后,建議執(zhí)行如下命令重啟一下 Jenkins,因為有的插件需要重啟之后才會生效。
docker restart jenkins
5. 安裝插件
Jenkins 啟動成功之后,接下來我們安裝三個必要的插件:
- Maven Integration:Maven 構(gòu)建工具
- Publish Over SSH:整個工具,將來把 Jenkins 打包好的 jar 上傳到應(yīng)用服務(wù)器上。
- Gitee:協(xié)助使用 Gitee 倉庫。
安裝步驟如下:
點擊左邊的系統(tǒng)管理,然后點擊右邊的插件管理,進(jìn)行配置。
然后在可選插件中,搜索 Maven Integration 和 Publish Over SSH 以及 Gitee 三個插件:
搜索完成后,點擊 Install without restart。
安裝成功之后,重啟 Jenkins。
建議執(zhí)行 docker restart jenkins 去重啟,點擊網(wǎng)頁上的重啟,會卡很久,還是執(zhí)行 docker 重啟命令靠譜一些。
6. 配置 Jenkins
6.1 基本的環(huán)境配置
插件安裝成功之后,接下來我們開啟 Jenkins 的配置,在正式開始配置之前,先做一點準(zhǔn)備工作。
這個需要我們提前準(zhǔn)備好 Maven,由于 Jenkins 容器中已經(jīng)包含一個 JDK 了,所以我們可以不用提前準(zhǔn)備 JDK,只需要提前準(zhǔn)備 Maven 即可。為了避免權(quán)限問題,我們可以直接將 Maven 上傳到 jenkins 容器中,然后去配置即可。
如下將宿主機中的 maven 拷貝到 Jenkins 容器中:
# 這個命令表示將宿主機中的 maven 目錄拷貝到 jenkins 容器中的 /opt/ 目錄下
docker cp maven jenkins:/opt/
接下來就可以開始配置了,配置的位置如下圖:
6.2 JDK
首先我們來配置 JDK,Jenkins 中默認(rèn)安裝了 JDK,我們只需要將其配置配出出來即可:
別名隨意取,JAVA_HOME 則根據(jù)實際情況配置。
6.3 Maven
Maven 就是我們剛剛上傳到 docker 中期中的 Maven,配置一下位置即可,Jenkins 將來會自動從 Gitee 上將代碼拉下來,然后就利用你這里配置的 Maven 進(jìn)行構(gòu)建:
名字隨意取,MAVEN_HOME 則是前面剛剛上傳到容器中的 MAVEN 目錄。
6.4 Git
配置 Git,由于 Jenkins 容器中已經(jīng)存在 git 了,所以這里不需要額外安裝 git,默認(rèn)即可。
所有都配置完成,點擊保存按鈕。
6.5 遠(yuǎn)程的憑證配置
接下來還需要我們配置兩個遠(yuǎn)程登錄憑證。
6.5.1 應(yīng)用服務(wù)器信息
應(yīng)用服務(wù)器,就是將來 Jenkins 將代碼構(gòu)建成 jar 包后,要上傳的服務(wù)器的信息(地址、用戶名以及密碼)。
配置步驟如下,首先找到配置的位置:
往下拉找到 Publish Over SSH,然后點擊新增,開始配置,Hostname 位置填寫你服務(wù)器的域名或者 IP:
配置成功后,點擊測試連接進(jìn)行測試,確保連接是成功的。
有的小伙伴反饋這里用戶名密碼會導(dǎo)致 jar 包上傳失敗,要在應(yīng)用服務(wù)器上生成 ssh 密鑰對,然后將私鑰配置給 Jenkins(這塊大家結(jié)合自己情況來看,如果后面 jar 上傳失敗,可以回來改一下這里)。
6.5.2 Gitee 的信息
接下來我們配置 Gitee 的信息。
首先配置倉庫的基本信息:
接下來配置 Gitee 的憑證,要根據(jù)這些憑證,才能從 Gitee 上拉取代碼下來,點擊 添加->Jenkins,添加憑證:
添加成功之后,就可以選擇這個令牌了。
最后點擊測試連接,確保可以連上 Gitee。
所有配置工作都做完了,接下來我們就可以開始構(gòu)建一個項目了。
7. 開始一個項目的構(gòu)建
首先我們新建一個任務(wù):
接下來我們選擇構(gòu)建一個 Maven 項目:
點擊確定之后,拉到源碼管理位置,開始配置。
首先選擇 Git,填入 Gitee 上的倉庫地址,然后憑證就寫 Gitee 的用戶名/密碼。
這里有一個需要注意的地方,就是默認(rèn)的分支名稱,GitHub 上現(xiàn)在默認(rèn)的主分支名稱是 main,Gitee 似乎還是 master,這個無所謂了,但是小伙伴們注意圖片下面的分支,按你實際的情況填寫。
這里也要添加憑證信息:
這里也要注意下,有小伙伴反饋 Gitee 上的用戶名和用戶空間不是一回事(如果用的 GitHub 就不存在這個問題),我這里用戶名位置實際填入用戶空間名(如果你也不知道什么是用戶空間,那么恭喜你,直接寫用戶名就行了)。
加上時間,我們看下打印的過程:
接下來輸入項目構(gòu)建命令,將來 Jenkins 從 Gitee 上拉取代碼下來之后,就執(zhí)行該命令對項目進(jìn)行打包:
最后,配置上傳構(gòu)建好的文件,并執(zhí)行啟動命令,如下:
配置的詳細(xì)信息:
根據(jù)上圖的配置,我們使用 root 用戶登錄,root 登錄成功之后,默認(rèn)進(jìn)入到 /root 目錄下,接下來會自動進(jìn)入到 data 目錄,然后我們的 jar 包就上傳到這個位置上。
然后我們在應(yīng)用服務(wù)器上也提前準(zhǔn)備好一個 shell 腳本叫做 deploy.sh,位于 /root/data 目錄下,這個腳本內(nèi)容如下:
export JAVA_HOME=/opt/java
export PATH=$JAVA_HOME/bin:$PATH
JAR_PATH=/root/data
JARFILE=jenkins_demo-0.0.1-SNAPSHOT.jar
ps -ef | grep $JARFILE | grep -v grep | awk '{print $2}' | xargs kill -9
java -jar $JAR_PATH/$JARFILE > out.log &
if [ $? = 0 ];then
sleep 30
tail -n 50 out.log
fi
這個腳本其實很好理解,前面先配置一下環(huán)境變量,注意這個是應(yīng)用服務(wù)器的環(huán)境變量,不是 Jenkins 的。
然后先檢查一下,如果應(yīng)用程序已經(jīng)在運行了,就先將之停止掉。然后運行我們最新的 jar 即可。
另外,可以開啟 SSH 操作日志,開啟日志之后,就可以看到 Jenkins 中操作應(yīng)用服務(wù)器其的過程了,特別是大家第一次配置的時候,容易出錯,配置了日志,將來出錯就知道什么原因?qū)е碌腻e誤了。
配置方式如下圖:
至此,這個項目就配置完成了。
保存之后,點擊立即構(gòu)建按鈕,就可以開始構(gòu)建了:
開始構(gòu)建之后,可以點擊構(gòu)建按鈕,查看構(gòu)建過程:
點擊控制臺輸出,可以查看整個構(gòu)建過程:
構(gòu)建完成后,來到應(yīng)用服務(wù)器,執(zhí)行 jps 命令查看運行的 Java 進(jìn)程,就可以看到我們的應(yīng)用程序已經(jīng)跑起來了。
8. 自動構(gòu)建
好了,現(xiàn)在我們的項目還不是自動構(gòu)建,也就是當(dāng)我們向 Gitee 上的代碼倉庫提交代碼之后,并不會觸發(fā) Jenkins 的自動構(gòu)建,得我們手動點擊構(gòu)建按鈕,接下來我們再來繼續(xù)配置,實現(xiàn)自動觸發(fā)構(gòu)建。
為了實現(xiàn)自動觸發(fā)構(gòu)建,我們需要修改兩個地方。
8.1 修改 Jenkins
首先在 Jenkins 的當(dāng)前項目中,配置一下觸發(fā)構(gòu)建的規(guī)則:
大家注意,在網(wǎng)頁上 Jenkins 已經(jīng)給出了將來要配置的 Webhook 的地址了,大家直接拷貝該地址即可。
8.2 配置 Webhook
接下來在 Gitee 的項目中,配置 WebHook,在當(dāng)前項目中,選擇管理選項卡,左邊菜單點擊 WebHooks,然后點擊添加 WebHook。
由于 Jenkins 是要登錄之后才可以操作的,處于公網(wǎng)的 Jenkins 我們也不能降至設(shè)置為匿名訪問,所以這里我們將 Jenkins 的用戶名密碼放在請求地址中,最終地址類似這樣:http://username:password@11.11.11.11:8088/xxxx。
好啦,這就行了,配置完成后,接下來我們向 Gitee 代碼倉庫提交代碼,提交成功之后,我們?nèi)ゲ榭词欠駮|發(fā) Jenkins 自動構(gòu)建功能。
9. 小結(jié)
好啦,關(guān)于 Jenkins 還有很多好玩的用法,今天的文章限于篇幅我就先通過一個簡單的案例來和大家分享一下 Jenkins 的基本用法,以便于小伙伴們對 Jenkins 建立一個直觀的印象,更多的玩法,松哥將在后續(xù)的文章中和大家繼續(xù)介紹,小伙伴們也可以留言說說你想看 Jenkins 怎么玩。
參考資料:
https://www.redhat.com/zh/topics/devops/what-is-ci-cd