耿雷 趙宏翔 李建友 張華鵬 王鐵一
摘要:提出了一種基于Jenkins實現(xiàn)一鍵式快速部署的系統(tǒng)方案,介紹了Jenkins,Docker,Git以及Nexus Repository Manager關(guān)鍵技術(shù)及其特征,通過這些關(guān)鍵技術(shù)的集成,闡述了一鍵式部署方案的流程和系統(tǒng)架構(gòu)設(shè)計,并以操作系統(tǒng)CentOS7為例,詳細介紹了系統(tǒng)方案的環(huán)境搭建以及具體實現(xiàn),包括Dockerfile和Jenkinsfile的編寫。通過構(gòu)建Jenkins流水線任務(wù),在項目開發(fā)過程中需要重新打包部署時,開發(fā)人員能夠一鍵式快速完成項目上線。
關(guān)鍵詞:Jenkins;一鍵式部署;Docker
中圖分類號:TP393文獻標志碼:A文章編號:1008-1739(2022)24-50-5
隨著計算機技術(shù)的愈發(fā)成熟,軟件項目的復(fù)雜度也越來越高,傳統(tǒng)的瀑布式開發(fā)模式開發(fā)周期長、階段固化,無法適應(yīng)當今形勢的發(fā)展。此外,隨著信息化時代的飛速發(fā)展,如今的商業(yè)環(huán)境發(fā)生了翻天覆地的變化,人們每天接收到各種各樣的信息,對軟件的需求變化也越來越快,需求本身具備不確定性,不是一次性或者一段時間就可以完全定義清楚的,傳統(tǒng)的瀑布模型無法在開發(fā)過程中不斷根據(jù)需求變化動態(tài)地調(diào)整產(chǎn)品。整個商業(yè)環(huán)境日新月異,迫使企業(yè)更快地做出決策,更快地推出新產(chǎn)品到市場中去,因此,敏捷開發(fā)成為了市面上企業(yè)開發(fā)模式的主流趨勢[1]。
敏捷開發(fā)是一種迭代式開發(fā),在需求的不斷變更中,軟件需要頻繁進行部署,一個團隊里有多個開發(fā)人員,每個人在開發(fā)完各自新功能后可能都要訪問服務(wù)器進行部署,每個人的部署方式各異,這就會導(dǎo)致每次部署的軟件配置不統(tǒng)一,并且還浪費開發(fā)人員的時間精力。即使有專門的運維人員負責軟件迭代部署,每次部署的工作量也是比較大的。因此,本文提出了一種基于Jenkins流水線的一鍵式部署方案,并通過實踐,給出了設(shè)計方案的實現(xiàn)流程。
1.1 Jenkins
目前,企業(yè)軟件的開發(fā)流程主要分為:編碼、構(gòu)建、集成、測試、交付和部署6個階段,在這個流程中,持續(xù)集成(Continuous Integration,CI)、持續(xù)交付(Continuous Delivery, CD)和持續(xù)部署(Continuous Delivery,CD)都具有不同的自動化交付周期。
持續(xù)集成是指頻繁地將代碼整合到主分支中。把軟件單獨開發(fā)的一部分交給整體軟件,經(jīng)常進行持續(xù)集成,這樣可以更迅速地找到bug。持續(xù)集成有2大優(yōu)勢:①能夠迅速地找到bug。每次完成一小部分更新,都會被整合到主分支中,這樣能夠迅速地找到bug,并且易于查找錯誤。②避免其他分支明顯地從主分支上脫離。如果沒有頻繁地整合,并且主分支還在不斷地升級,那么日后的整合將會非常困難,甚至很難進行整合。持續(xù)集成的目標是在保證高品質(zhì)的前提下,使產(chǎn)品能夠迅速地進行迭代。其關(guān)鍵的一點是,在將代碼整合到主分支之前,必須經(jīng)過自動測試。如果其中一個測試案例是失敗的,那么將無法繼續(xù)進行。
持續(xù)交付是指經(jīng)常向用戶或質(zhì)量隊伍提供新版本的軟件,以便進行審核,如果審核被批準,則該代碼將被投入到產(chǎn)品中。持續(xù)的交付是基于持續(xù)的整合,在實際的運行環(huán)境中(貼近生產(chǎn)環(huán)境)部署整合后的代碼。持續(xù)交付是基于高度自動化的持續(xù)集成基礎(chǔ)上的軟件部署,在整個產(chǎn)品生命周期中,它的優(yōu)先級是最高的。可將持續(xù)交付視為持續(xù)整合的下一個步驟,其關(guān)鍵核心是,無論軟件怎么升級,無論何時何地,都能提供該軟件的交付版本。
持續(xù)部署是接下來的一個階段,即在經(jīng)過審核之后,軟件會被自動地部署到生產(chǎn)環(huán)境中。持續(xù)部署的目的是使軟件處于隨時都能部署的狀態(tài),并能投入到生產(chǎn)中。持續(xù)部署的先決條件是測試、構(gòu)建、部署等步驟自動化。
總體而言,持續(xù)集成、持續(xù)交付和持續(xù)部署提供了一個非常好的DevOps環(huán)境。它可以極大地提高整個開發(fā)團隊的開發(fā)效率,同時也帶來了挑戰(zhàn)。在任何情況下,頻繁部署、快速交付和自動化的測試過程將是未來軟件工程中的關(guān)鍵環(huán)節(jié)。
Jenkins是一個持續(xù)的集成工具,它是在Java開發(fā)基礎(chǔ)上能夠進行持續(xù)的軟件發(fā)行和持續(xù)的測試。Jenkins可以輕松地進行配置,從而使開發(fā)人員擺脫復(fù)雜的集成,將精力集中在更加關(guān)鍵的商業(yè)邏輯實施上。Jenkins具有以下特性:
①開源的Java語言開發(fā)持續(xù)集成工具,支持CI和CD;
②豐富的插件支持:支持插件的擴展,可以根據(jù)自己的小組需求,開發(fā)例如Docker,svn,maven,Git等工具;
③文件識別:Jenkins可以追蹤jar包是在哪次構(gòu)建產(chǎn)生的,使用的jar包的版本是什么等;
④安裝部署簡便:支持多種方式安裝部署,可以在yum上安裝,或者下載war軟件,或者通過Docker容器來進行安裝;支持在Web界面進行管理配置;
⑤支持分布式構(gòu)建:Jenkins可以支持多個電腦共同進行構(gòu)建和測試。
本文將使用Jenkins的流水線來構(gòu)建部署項目,使得整個部署過程流程化。Jenkins流水線的定義被寫入到一個名為Jenkinsfile的文本文件中,每次構(gòu)建時Jenkins會根據(jù)Jenkinsfile定義好的流水線語句自動執(zhí)行任務(wù),為本文一鍵式部署提供了很好的自動化、流程化工具。
1.2 Docker
Docker[2]是一個開源的應(yīng)用容器引擎,讓開發(fā)者可以將他們的軟件和依賴打包生成一個鏡像,然后在Docker啟動發(fā)布到服務(wù)器上。Docker將部署的項目容器化,在Docker環(huán)境中,簡化了對容器的復(fù)制、啟動、關(guān)閉和刪除,使得部署的操作更加簡捷;Docker具有更好的兼容性和移植性,除了內(nèi)核之外,它提供了一個完整的運行時環(huán)境,保證了執(zhí)行環(huán)境的一致性,用戶可以很輕易地將一個平臺上運行的應(yīng)用遷移到另一個平臺上,無需考慮操作系統(tǒng)和運行環(huán)境影響。
Docker是利用谷歌公司發(fā)布的Go語言來開發(fā)完成的,它使用了Linux內(nèi)核的cgroup和namespace等技術(shù),將進程封裝隔離起來,這是一種在操作系統(tǒng)級別上的虛擬化技術(shù)。因為被隔離的進程是與寄主或其他隔離進程無關(guān)的,所以也被稱為“容器”。Docker是以容器為基礎(chǔ),對其進行了再一次的包裝,從文件系統(tǒng)到網(wǎng)絡(luò)連接,再到進程隔離,大大簡化了創(chuàng)建和維護容器的流程,使Docker技術(shù)相比于虛擬機技術(shù)更加輕快、便捷。Docker作為一種新的虛擬技術(shù),它相比傳統(tǒng)的虛擬化方法有很多優(yōu)點:
①更有效地使用系統(tǒng)的資源
Docker可以更好地利用系統(tǒng)資源,因為它無需硬件虛擬和運行整個操作系統(tǒng)。相比于傳統(tǒng)的虛擬機技術(shù),Docker文件存儲速度、應(yīng)用程序的執(zhí)行速度和內(nèi)存消耗都要快得多。所以,與虛擬機技術(shù)相比,同一配置的主機,Docker可以執(zhí)行更多的應(yīng)用程序。
②更快地啟動
傳統(tǒng)的虛擬機技術(shù)通常要花費幾分鐘才能啟動一個應(yīng)用程序,但是Docker容器程序可以在幾秒、甚至毫秒級內(nèi)完成,因為它是在主機核心上運行的,不需要操作系統(tǒng)完整啟動,這極大地節(jié)省了開發(fā)、測試和部署的時間。
③擁有統(tǒng)一的運行環(huán)境
在軟件開發(fā)中,一個普遍存在的問題是環(huán)境的一致性。由于開發(fā)環(huán)境、測試環(huán)境和生產(chǎn)環(huán)境的不統(tǒng)一,可能造成一些bug以及在開發(fā)階段沒有被測試出來的問題。Docker的鏡像除了提供了一個完整的運行時環(huán)境,還保證了應(yīng)用程序運行環(huán)境的一致性,這樣就不會有“開發(fā)沒問題,部署跑不通”的問題了。
④支持持續(xù)交付和持續(xù)部署
對于開發(fā)和操作(DevOps)的人而言,最需要的是在完成了一次創(chuàng)建或者配置后,能夠在任何地點都能正常工作,即“一次配置,到處運行”。使用Docker可以通過自定義應(yīng)用鏡像,完成持續(xù)集成、持續(xù)交付和持續(xù)部署。開發(fā)者可以結(jié)合Dockerfile來創(chuàng)建鏡像,而且可以與持續(xù)集成系統(tǒng)協(xié)同來完成集成測試;運維人員可以將這個鏡像迅速地部署到生產(chǎn)環(huán)境中,甚至可以與持續(xù)集成工具整合完成自動快速部署。同時,通過Dockerfile來實現(xiàn)鏡像構(gòu)建,不僅開發(fā)團隊能夠了解應(yīng)用程序的運行環(huán)境,還可以讓維護團隊了解應(yīng)用程序的部署條件,從而更好地部把鏡像部署到生產(chǎn)環(huán)境中。
⑤擁有更快捷的移植性
因為Docker保證了運行環(huán)境的一致性,所以可以很輕松地進行移植。Docker支持在眾多平臺上運行,不管是虛擬機、物理機、私有云、公有云甚至筆記本,都能得到相同的運行結(jié)果。這樣,用戶就可以輕松地將一個應(yīng)用程序移植到另外一個平臺,而不必擔心由于運行環(huán)境的改變而使程序不能正常工作。
⑥易于維護和擴展
Docker采用了分層存儲和鏡像技術(shù),可以方便重用應(yīng)用程序中的重復(fù)部件,同時也可以簡化程序的維護和升級,并且可以輕松地通過基本鏡像來進一步擴展鏡像。同時,Docker團隊和不同的開放源碼項目小組共同維護了大量高品質(zhì)的官方鏡像,這些鏡像可以直接用于產(chǎn)品中,也可以作為基礎(chǔ)進行進一步的鏡像定制,從而大大減少了應(yīng)用程序的鏡像制作成本。
1.3 Git
Git是一款小巧靈活卻功能強大的分布式版本控制系統(tǒng),相比于集中式版本控制系統(tǒng),Git在每個開發(fā)者的計算機本地擁有一套完整的代碼倉庫,開發(fā)者可以把代碼提交到本地倉庫,然后將這些代碼發(fā)送到遠程倉庫,或者將最新的代碼提取出來,與本地的倉庫進行合并。Git更加強調(diào)個體,擁有良好的分支機制,能夠減輕公共服務(wù)器倉庫壓力。本文使用Git進行項目統(tǒng)一管理,部署所需的軟件包和文本文檔均來自于項目的Git遠程倉庫[3]。
1.4 Nexus Repository Manager
Nexus Repository Manager是一款強大的倉庫管理軟件,它大大簡化了對內(nèi)部倉庫的維護和對外部倉庫的存取,經(jīng)常被用作Maven的私有倉庫,也可以作為Docker,npm和yum等的私有倉庫,功能強大。本文使用Nexus作為Docker鏡像文件的私有倉庫,對鏡像文件統(tǒng)一管理,可以存儲Docker基礎(chǔ)鏡像文件或者已經(jīng)打好包的鏡像文件,用戶可以從Nexus倉庫拉取基礎(chǔ)鏡像構(gòu)建新鏡像,也可以拉取已經(jīng)做好的鏡像直接在本地Docker中啟動。
一鍵式部署的目標就是當軟件版本發(fā)生變更需要重新部署時,開發(fā)人員無需關(guān)注部署的各種繁雜細節(jié),只需要將軟件打好包上傳到項目遠程倉庫,在Jenkins中使用一鍵構(gòu)建,系統(tǒng)即可自動生成項目的Docker鏡像,將鏡像文件推送至遠程Nexus私有Docker倉庫,然后啟動運行容器。自動部署完成后即可訪問部署的新版本軟件。一鍵式部署方案流程如圖1所示。
整個工作流程涉及開發(fā)人員計算機、持續(xù)集成服務(wù)Jenkins、項目遠程倉庫服務(wù)、私有倉庫管理服務(wù)Nexus以及Docker服務(wù)。一鍵式部署方案架構(gòu)如圖2所示。其中,開發(fā)人員計算機使用Git客戶端工具從項目遠程倉庫中拉取項目最新代碼,將修改好的代碼和打包好的項目文件推送到項目遠程倉庫服務(wù);Jenkins服務(wù)使用Git插件從項目遠程倉庫中拉取項目文件夾,執(zhí)行Jenkinsfile腳本文件,從Nexus Docker鏡像倉庫拉取基礎(chǔ)鏡像構(gòu)建目標鏡像文件,將構(gòu)建好的鏡像推送至Nexus Docker鏡像倉庫,啟動容器時再從鏡像倉庫中拉取鏡像執(zhí)行啟動命令[4]。
3.2.1 Dockerfile
Dockerfile是一個文本文件,用于構(gòu)建自定義鏡像。在Dockerfile中首先需要聲明制定構(gòu)建新的鏡像文件所使用的基礎(chǔ)鏡像,以部署jar包為例,基礎(chǔ)鏡像使用的是openjdk,ip: port處輸入訪問Nexus的地址和端口;然后需要為RUN,CMD,ADD和ENTRYPOINT等指令設(shè)定工作目錄,將要部署的jar包文件添加到容器中并重命名為app.jar;把項目用到的端口暴露給外界;設(shè)置鏡像的時區(qū)以保證時間正確;使用RUN構(gòu)建鏡像,使用ENTRYPOINT配置容器,使其可執(zhí)行化。Dockerfile文件具體內(nèi)容如下:
FROM ip:port/ amd64/ openjdk:8u312
WORKDIR /tmp
ADD demo-2.3.5. RELEASE.jar app.jar
EXPOSE 8000 8010
ENV TZ=Asia/ Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime ENTRYPOINT ["java","-jar","app.jar"] 3.2.2 Jenkinsfile
Jenkins流水線的定義被寫在一個名為Jenkinsfile的shel1腳本文件中,因此,需要定義好一個流水線,使整個部署流程自動化。流水線具體操作分為以下4個步驟:
①File Check文件檢查。首先檢查構(gòu)建鏡像所需的文件正確齊全,例如jar包、Dockerfile等。
②Docker Build構(gòu)建鏡像。首先,使用docker rm命令,移除舊版本容器以及移除舊版鏡像,包括Nexus倉庫的鏡像,這一步是為了防止鏡像冗余導(dǎo)致不用的鏡像占用空間;接著,通過docker build -t demo:1.0 .命令構(gòu)建新鏡像,1.0表示版本號,后續(xù)更新版本可以進行相應(yīng)的修改。
③Docker Push推送鏡像。這一步是將上一步生成好的鏡像文件推送至Nexus遠程私有倉庫。先登錄Nexus私有倉庫(docker login),使用docker tag標記本地鏡像,將其歸入Nexus倉庫,然后使用docker push將其推送至Nexus倉庫。
④Docker Run運行容器。最后一步運行容器,使用docker run命令,通過指定鏡像文件、設(shè)置文件映射、端口映射和容器名稱等信息啟動容器。
本文分析了當前開發(fā)模式的現(xiàn)狀,在敏捷開發(fā)環(huán)境下項目需要頻繁部署,因為使用傳統(tǒng)的部署方式會大大占用開發(fā)人員的時間和精力,所有本文提出了一種基于Jenkins服務(wù)進行一鍵式部署項目的解決方案,整個方案架構(gòu)以Docker為基礎(chǔ)環(huán)境,通過整合Git,Jenkins和Nexus實現(xiàn)了便捷的一鍵式部署,大大節(jié)省了部署所需耗費的人力和物力。目前,本文的一鍵式部署方案已經(jīng)過驗證投入到實際應(yīng)用中,實現(xiàn)了項目的快速持續(xù)集成,提高了整個團隊的項目開發(fā)效率。
[1]程寧,戴遠泉.基于Jenkins持續(xù)集成部署研究與實現(xiàn)[J].電子制作,2021(22):46-48.
[2]張延冬,邢艷芳.基于Docker的運維平臺設(shè)計[J].計算機時代,2018(4):16-18.
[3]石慶冬.版本管理工具Git的主要特點[J].電子技術(shù)與軟件工程,2022(7):72-75.
[4]賈灶生.基于Jenkins的云原生應(yīng)用的持續(xù)集成設(shè)計和實現(xiàn)[D].西安:西安電子科技大學,2021.
[5]林美蓉. CentOS 8上Docker部署FTP服務(wù)器的兩種方式[J].網(wǎng)絡(luò)安全和信息化,2022(10):67-69.
[6]陳子通,馬迎新,關(guān)梅茹.基于Jenkins平臺的ECU軟件持續(xù)集成系統(tǒng)搭建[C]// 2020中國汽車工程學會年會.上海:機械工業(yè)出版社,2020:70-79.
[7]胡志寶.基于Jenkins技術(shù)實現(xiàn)自動測試系統(tǒng)研究[D].北京:華北電力大學(北京),2021.