基于Jenkins的持续交付全流程设计与实践
1 從理論開(kāi)始
什么是DevOps?
近年來(lái),隨著DevOps理念的逐漸深入人心,企業(yè)逐漸意識(shí)到從看似重復(fù)的手工勞動(dòng)中實(shí)現(xiàn)自動(dòng)化流程處理,對(duì)于提高企業(yè)勞動(dòng)生產(chǎn)力已經(jīng)非常重要,尤其是面向互聯(lián)網(wǎng)的開(kāi)發(fā)者,往往每次上線時(shí),最大的挑戰(zhàn)并非需求的走查或測(cè)試和改bug,而是由于發(fā)布的流程不夠規(guī)范,將成果發(fā)布到目標(biāo)環(huán)境后可能造成的配置錯(cuò)誤或引發(fā)其他已知未知問(wèn)題所造成的額外工作量,使得生產(chǎn)環(huán)境的發(fā)布流程總會(huì)存在不順利。
而DevOps則致力于統(tǒng)一整合軟件開(kāi)發(fā)和軟件運(yùn)維,其特點(diǎn)是強(qiáng)烈倡導(dǎo)對(duì)構(gòu)建軟件的所有環(huán)節(jié)(從集成、測(cè)試、發(fā)布到部署和基礎(chǔ)架構(gòu)管理)進(jìn)行全面的自動(dòng)化監(jiān)控。目標(biāo)是縮短軟件開(kāi)發(fā)周期,提高部署頻率和更可靠的發(fā)布,與業(yè)務(wù)目標(biāo)保持一致。
在實(shí)際操作過(guò)程中,對(duì)于許多公司而言,開(kāi)發(fā)者和運(yùn)維者并沒(méi)有明確的界限,而且即便將運(yùn)維與開(kāi)發(fā)的崗位職責(zé)分開(kāi)了,也并非意味著雙方的職業(yè)發(fā)展方向?qū)⒋蟛幌嗤?shí)際上在實(shí)際操作過(guò)程中,開(kāi)發(fā)人員和運(yùn)維人員依然會(huì)使用相同的工具、統(tǒng)一的流程、一致的管理思想,并通過(guò)一系列管理手段和工具實(shí)現(xiàn)流程的優(yōu)化。
什么是持續(xù)集成和持續(xù)交付?
持續(xù)集成(Continuous Integration)與持續(xù)交付(Continuous Delivery)也正是DevOps中最為基礎(chǔ)的兩種企業(yè)級(jí)研發(fā)和交付活動(dòng)。
持續(xù)集成來(lái)源于敏捷項(xiàng)目管理思想,其核心是團(tuán)隊(duì)成員應(yīng)該經(jīng)常集成他們的工作,通常每天要求集成一次,當(dāng)然也可以要求團(tuán)隊(duì)成員每天集成多次。每次集成之后,會(huì)通過(guò)持續(xù)集成工具自動(dòng)運(yùn)行自動(dòng)化的構(gòu)建手段(例如編譯、單元測(cè)試、集成測(cè)試、系統(tǒng)測(cè)試),并對(duì)集成后的成果進(jìn)行驗(yàn)證,從而實(shí)現(xiàn)了企業(yè)管理流程中盡早的發(fā)現(xiàn)未知問(wèn)題的目標(biāo)。而在傳統(tǒng)的軟件交付中,可能會(huì)將所有問(wèn)題積壓到系統(tǒng)整體測(cè)試或甚至UAT(用戶驗(yàn)收測(cè)試)環(huán)節(jié),使得軟件的測(cè)試時(shí)間被拉長(zhǎng),甚至使得軟件的問(wèn)題流入到客戶現(xiàn)場(chǎng),讓客戶成為小白鼠的情況時(shí)有發(fā)生。
實(shí)際上而言,看似簡(jiǎn)單的集成,卻并非簡(jiǎn)單,他應(yīng)該是企業(yè)管理過(guò)程中的一項(xiàng)鐵律,只有嚴(yán)格執(zhí)行,才能確保軟件時(shí)刻處于可用狀態(tài);否則就意味著所謂交付過(guò)程中完成進(jìn)度的百分之多少,只不過(guò)是一個(gè)虛無(wú)縹緲的空口白話。
持續(xù)集成往往離不開(kāi)持續(xù)交付,在喬梁老師翻譯的《持續(xù)交付》一書(shū)中,作者Jez Humber說(shuō):持續(xù)交付是一種能力,也就是說(shuō),能夠以可持續(xù)的方式,安全快速的把代碼變更(包括特性、配置、缺陷和試驗(yàn))部署到生產(chǎn)環(huán)境中,讓用戶使用。這本書(shū)的作者也在書(shū)的最后一章中指出:它(持續(xù)交付)不僅僅是一種新的軟件交付方法論,而且對(duì)依賴軟件的業(yè)務(wù)來(lái)說(shuō),也是一種全新的范式。
持續(xù)交付與持續(xù)部署看似類似,其實(shí)有所區(qū)別,前者往往是指將環(huán)境推送到用戶面前,使用戶能夠觸及和使用它們;而部署則僅僅只是把軟件包安裝到目標(biāo)計(jì)算機(jī)上,用戶可能還無(wú)法直接使用。
對(duì)于面向互聯(lián)網(wǎng)的軟件企業(yè)來(lái)說(shuō),往往都已經(jīng)在過(guò)去若干年間已經(jīng)建立了一套完整的持續(xù)集成/持續(xù)交付流程,但對(duì)于某些處于飛速發(fā)展期的企業(yè)來(lái)說(shuō),依然相對(duì)而言后知后覺(jué),主要是由于企業(yè)過(guò)去飛速發(fā)展的背后所依托的人力物力資源,能夠足以保證企業(yè)的產(chǎn)出能夠適應(yīng)企業(yè)發(fā)展的需要,然而隨著團(tuán)隊(duì)規(guī)模的發(fā)展趕不上企業(yè)業(yè)務(wù)發(fā)展的需要時(shí),重復(fù)勞動(dòng)和看似毫無(wú)價(jià)值的等待期、后期積壓的測(cè)試任務(wù)、無(wú)法有效度量的軟件功能實(shí)現(xiàn),實(shí)質(zhì)上也會(huì)造成企業(yè)的管理成本進(jìn)一步提高。
從哪里可以獲得系統(tǒng)的方法論?
對(duì)于需要搭建一套完整環(huán)境的開(kāi)發(fā)者來(lái)說(shuō),網(wǎng)上資料很齊全,本文也試圖盡可能的對(duì)各方面的內(nèi)容進(jìn)行綜述,努力為開(kāi)發(fā)者提供一個(gè)開(kāi)箱即用的操作流程,但是對(duì)于那些想系統(tǒng)的學(xué)習(xí)持續(xù)交付或DevOps領(lǐng)域的知識(shí)的開(kāi)發(fā)者來(lái)說(shuō),你其實(shí)不僅僅滿足于把環(huán)境搭起來(lái),那么你應(yīng)該看看書(shū)。
在持續(xù)集成和持續(xù)交付領(lǐng)域有大量?jī)?yōu)秀的作品,而我覺(jué)得來(lái)自喬梁老師的作品《持續(xù)交付2.0》堪稱精品,喬梁老師是一位經(jīng)驗(yàn)豐富的行業(yè)專家,在他的職業(yè)生涯中積累了與該領(lǐng)域相關(guān)非常豐富的產(chǎn)品研發(fā)經(jīng)驗(yàn),他也身體力行的參與到許多企業(yè)的持續(xù)交付流程優(yōu)化過(guò)程中,這些經(jīng)驗(yàn)都讓他能夠從更全面的視角來(lái)分析持續(xù)交付的問(wèn)題。在這本書(shū)中介紹了許多直接拿來(lái)就可以使用的管理方法、項(xiàng)目案例、工具,能夠讓有需求在該領(lǐng)域有所作為的開(kāi)發(fā)者帶來(lái)不少思考。
實(shí)質(zhì)上對(duì)于一家要實(shí)踐持續(xù)集成/持續(xù)交付的企業(yè)來(lái)說(shuō),將工具搭建完成并非核心難點(diǎn),難點(diǎn)依然在于如何使用敏捷項(xiàng)目管理的思想,實(shí)現(xiàn)軟件的細(xì)粒度任務(wù)拆分,并能夠?qū)蝹€(gè)任務(wù)進(jìn)行更好的測(cè)試,或許TDD是一種不錯(cuò)的模式,但是卻可能給開(kāi)發(fā)者的基礎(chǔ)技能提出了更高的要求,這將導(dǎo)致TDD無(wú)法落地。
如何快速驗(yàn)證產(chǎn)品需求?在《持續(xù)交付2.0》中提出的了一系列的方法,例如裝飾窗、最小可行特性法、特區(qū)法、定向搜索法、稻草人法、、最小可行產(chǎn)品法等六種方法,通過(guò)建立快速驗(yàn)證模型,提高軟件從需求到實(shí)現(xiàn)的整個(gè)流程,能夠?yàn)槠髽I(yè)帶來(lái)不少便利。
而在研發(fā)階段,可以采用特性分支和特性開(kāi)關(guān)的手法,利用git源代碼管理工具分支的妙處,將需求和代碼有機(jī)的耦合在一起,同時(shí)又依托項(xiàng)目管理工具,實(shí)現(xiàn)從需求=》實(shí)現(xiàn)=》發(fā)布的完整閉環(huán),從而為需求的驗(yàn)證提供了雙保險(xiǎn);特性開(kāi)關(guān)我最早在劉華老師的《獵豹行動(dòng)-敏捷轉(zhuǎn)型》一書(shū)中看到,通過(guò)使用軟開(kāi)關(guān)的形式,避免未開(kāi)發(fā)完成的提前上線造成巨大的風(fēng)險(xiǎn),而在這邊書(shū)中也同樣提到了這樣的方法。在.NET中同樣也可以使用特性分支組件,后期我將嘗試一下。
而對(duì)于如何減少等待期,作者提到的方法是:
1、通過(guò)“拉動(dòng)”讓價(jià)值流動(dòng)起來(lái),例如,如果是一個(gè)生產(chǎn)線的滯留,通過(guò)擴(kuò)大瓶頸的處理能力,讓更多的需求能夠快速交付,這種手法看似能夠臨時(shí)提高環(huán)節(jié)處理能力,保障團(tuán)隊(duì)的產(chǎn)出,但是顯然不是個(gè)良好的措施,更合理的措施就是根據(jù)下游的生產(chǎn)能力來(lái)確定上游的處理能力,由下游來(lái)拉動(dòng)上游的需求。這客觀上要求將任務(wù)和需求的粒度進(jìn)一步均勻化,將需求劃分成更加易于執(zhí)行、工作量類似的小需求,使得開(kāi)發(fā)過(guò)程更加平滑。
2、任務(wù)自助化:也就是讓團(tuán)隊(duì)掌握某些通用技能,以便在其他人員阻塞時(shí),能夠同步完成相關(guān)任務(wù),避免了某些關(guān)鍵任務(wù)阻塞造成了整體流程的滯后。
在此我就不過(guò)多描述書(shū)中的精華了,有興趣的可以入手一本,絕對(duì)物超所值。
2、總體流程和環(huán)境部署
接下來(lái)我將進(jìn)入本文的主題,首先我將構(gòu)建一個(gè)簡(jiǎn)單的企業(yè)級(jí)持續(xù)集成/持續(xù)交付的管理流程,然后再對(duì)流程的實(shí)現(xiàn)過(guò)程進(jìn)行較為詳細(xì)的介紹。
流程圖
[圖片](
)
在這個(gè)流程中,使用了master/dev的分支模式。
1、對(duì)于dev分支提交的代碼,經(jīng)過(guò)代碼編輯、靜態(tài)代碼掃描、自動(dòng)化單元測(cè)試的流程,在運(yùn)行通過(guò)后,有測(cè)試人員進(jìn)行代碼的測(cè)試,并在代碼測(cè)試通過(guò)后,通過(guò)pull request提交給master分支的審查人員進(jìn)行代碼檢查和合并。
2、測(cè)試人員對(duì)dev提交的代碼進(jìn)行確認(rèn),并由master分支代碼審查人員進(jìn)行代碼審查,通過(guò)后對(duì)代碼進(jìn)行確認(rèn),并生成用于發(fā)布的生成包。
涉及的組件和說(shuō)明
在流程中,使用了以下工具,依次安裝即可。
1、安裝OpenJDK
2、安裝Jenkins和相關(guān)插件
3、安裝PostgresDb
4、安裝SonarQube
5、安裝dotnetsdk3.1
6、安裝git
7、安裝nexus包管理器 for windows版用以實(shí)現(xiàn)包管理。
8、安裝Qy Wechat Notification或HTTP Request 用以實(shí)現(xiàn)企業(yè)微信提醒。
好吧,環(huán)境安裝就不介紹了。。
安裝補(bǔ)充說(shuō)明
1、其中jenkins安裝的版本為2.190.3,OpenJDK安裝的版本為openjdk12.0。安裝完jenkins和openjdk后,需要進(jìn)行環(huán)境變量的設(shè)置。
2、SonarQube安裝的版本為7.9.1,根據(jù)官方網(wǎng)站的說(shuō)明,推薦使用的數(shù)據(jù)庫(kù)包括:sqlserver\oracle\postgresdb,在7.9.1和更高版本中,已經(jīng)不再推薦使用mysql。
3、SonarQube默認(rèn)使用了基于H2內(nèi)存數(shù)據(jù)庫(kù)的嵌入式數(shù)據(jù)庫(kù),可以在測(cè)試環(huán)境下使用,但是不建議用于生產(chǎn)環(huán)境。
5、安裝完sonarqube、和數(shù)據(jù)庫(kù)后,需要修改sonarqube/conf/sonar.properties文件中的數(shù)據(jù)庫(kù)配置地址,并將sonarqube的服務(wù)重啟。
[圖片](?
)
在windows系統(tǒng)中,點(diǎn)擊sonarqube-xxx\bin\windows-x86-64文件夾中的InstallNTService.bat用以安裝SonarQube的服務(wù),而StartNTService.bat則用于啟動(dòng)SonarQube的應(yīng)用服務(wù)。如果數(shù)據(jù)庫(kù)配置失敗,則SonarQube會(huì)啟動(dòng)失敗,并提示以下錯(cuò)誤:
[sonar-1510653879773] exception caught on transport layer [[id: 0x346b46fb, /127.0.0.1:59330 => /127.0.0.1:9001]], closing connection
java.io.IOException: An existing connection was forcibly closed by the remote host
6、由于使用了自行搭建的Nuget包源管理器,所以在進(jìn)行構(gòu)建時(shí),會(huì)提示錯(cuò)誤,jenkins會(huì)使用
Jenkins的項(xiàng)目類型
在jenkins中提供了自由風(fēng)格、單流水線、多分支流水線、多配置項(xiàng)目等不同類型的項(xiàng)目,可以根據(jù)實(shí)際情況進(jìn)行取舍,在本人的嘗試過(guò)程中,分別總結(jié)了三種不同類型的項(xiàng)目可適用的場(chǎng)景:
自由風(fēng)格項(xiàng)目
操作流程簡(jiǎn)單,無(wú)需配置groovy腳本,即可簡(jiǎn)單的完成項(xiàng)目的自動(dòng)化構(gòu)建。
在自由風(fēng)格模式的項(xiàng)目中,實(shí)現(xiàn)代碼編譯的過(guò)程主要在構(gòu)建窗口中,主要使用dotnet -相關(guān)命令來(lái)完成。包括:
1、dotnet restore 還原依賴包。
2、dotnet build 編譯
3、dotnet publish -o ./bin/release 發(fā)布到指定目錄下。
4、如果需要使用sonarqube來(lái)進(jìn)行靜態(tài)代碼檢查,需要在服務(wù)器上安裝dotnet-sonarscanner組件,這個(gè)組件是基于.net core構(gòu)建的靜態(tài)代碼檢查組件,安裝的命令為:
dotnet tool install --global dotnet-sonarscanner --version 4.8.0;
5、如果采用.net framework 傳統(tǒng)框架,則可以繼續(xù)使用原來(lái)的SonarScanner.MSBuild.exe組件進(jìn)行代碼檢查結(jié)果的上傳。
6、如果需要在自由風(fēng)格項(xiàng)目中使用powershell腳本,可以在jenkins=》插件管理=》可用插件中搜索powershell即可。
單流水線項(xiàng)目
單流水線項(xiàng)目:可適用于只有一個(gè)分支和一套環(huán)境需要部署時(shí)的項(xiàng)目構(gòu)建,其發(fā)布流程需要使用groovy腳本來(lái)實(shí)現(xiàn)。點(diǎn)擊查看pipeline的語(yǔ)法
1、在流水線項(xiàng)目中,都在項(xiàng)目文件的根目錄中添加jenkinsfile文件(無(wú)擴(kuò)展名)作為jenkins編譯時(shí)的腳本文件,而這個(gè)文件的腳本語(yǔ)法采用groovy語(yǔ)言,并支持開(kāi)發(fā)者按照腳本語(yǔ)言進(jìn)行擴(kuò)展。
2、在單流水線項(xiàng)目中不支持groovy的分支判斷條件,支持邏輯比較簡(jiǎn)單的腳本。
3、與編譯有關(guān)的結(jié)構(gòu)均寫在jenkinsfile中,因此jenkins的UI界面可以理解為配置與項(xiàng)目相關(guān)的環(huán)境變量信息。
4、可以在jenkinsfile中定義輸入的參數(shù),例如:
parameters{
? ? ? ? string(name:'ProjectName', defaultValue: 'Enter Your ProjectName', description: 'Enter your project name here')
? ? ? ? string(name:'Contact', defaultValue: '"@All","xxx"', description: 'Enter Your Contract')?
? ? ? ? string(name:'RepoUrl', defaultValue: 'https://xxx.com/xxx/xxx.git', description: ' gitee代碼路徑')
}
在jenkins界面中,可以顯示成
[圖片](?
)
在具體場(chǎng)景下就可以通過(guò)jenkins界面?zhèn)魅胂嚓P(guān)參數(shù)進(jìn)行編譯的測(cè)試了。
多流水線項(xiàng)目
多分支流水線項(xiàng)目:使用于一個(gè)倉(cāng)庫(kù)下各分支不同環(huán)境需要部署時(shí)的項(xiàng)目構(gòu)建,其發(fā)布流程也需要使用groovy腳本實(shí)現(xiàn)。
1、多流水線項(xiàng)目支持使用分支判斷條件的語(yǔ)法,因此可以使用的場(chǎng)景更多。
2、其他的總體上和單分支流水線差不多,此處就不在贅述了。
以下編寫了一個(gè)簡(jiǎn)單的示例,僅供參考。
pipeline{agent any?parameters{string(name:'Contact', defaultValue: '"@All",""', description: 'Enter Your Contract')?string(name:'RepoUrl', defaultValue: '', description: ' 代碼路徑')string(name:'SonarUrl', defaultValue: 'http://xxx:9000', description: ' sonar代碼路徑')}?stages {stage('When Master') {?when {expression {BRANCH_NAME==~/(master)/}}?steps{? ? ? ?checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'xxx', url: params.RepoUrl]]])}}stage ("When Dev"){when {branch 'dev'}?steps{ rojectName}")?}}?stage("test"){when{expression{return true}}steps{echo "OK"}}? ??stage('Web Dev Build') {steps{}}?}post{success{SendToWeChatWork("CI Task success,ProjectName is ${params.ProjectName}")?echo 'Publish Success'}failure{SendToWeChatWork("CI Task Failure,ProjectName is ${params.ProjectName}")?echo 'Publish Failure'}} } def SendToWeChatWork(content) {? ? }多配置項(xiàng)目
如果組件代碼需要在不同的配置、不同的環(huán)境下重復(fù)部署,其基本邏輯類似,只是配置不同,就可以使用多配置項(xiàng)目。
好吧,我就沒(méi)有嘗試了,因?yàn)槲乙呀?jīng)用了多流水線項(xiàng)目來(lái)實(shí)現(xiàn)了。在這篇示例中對(duì)多配置項(xiàng)目有比較詳細(xì)的用法,需要可自取。
總結(jié)
將企業(yè)級(jí)持續(xù)集成的環(huán)境搭建起來(lái)本身并不難,難的是如何將整套體系與公司現(xiàn)有的開(kāi)發(fā)流程相結(jié)合,考慮到受康威定律的影響,不同的組織對(duì)于新事物的接受程度總是不同的,所以難免需要做一些準(zhǔn)備。
好文要頂?關(guān)注我?收藏該文??
總結(jié)
以上是生活随笔為你收集整理的基于Jenkins的持续交付全流程设计与实践的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Asp.Net Core下的开源任务调度
- 下一篇: Beetlex之redis驱动