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