概述
XXX項目原CI系統(tǒng)由項目自行搭建,使用Jenkins傳統(tǒng)的Job方式來實現(xiàn)VerifyCI和MergeCI以及DailyBuild。隨著項目規(guī)模越來越大,分支越來越多,合代碼的頻率也逐漸增大的情況下,現(xiàn)有系統(tǒng)呈現(xiàn)出諸多不便之處。為解決這些問題,項目嘗試引入一系列現(xiàn)成公司級Devops研發(fā)工具并結(jié)合Jenkins2.0的Pipeline新特性來改造本項目Pipeline流程。
Pipeline as Code 是 Jenkins 2.0 版本的精華所在,是幫助 Jenkins 實現(xiàn)從 CI 到 CD 華麗轉(zhuǎn)身的關(guān)鍵工具。所謂 Pipeline,簡單來說,就是一套運行于 Jenkins 上的工作流框架,將原本獨立運行于單個或者多個節(jié)點的任務(wù)連接起來,實現(xiàn)單個任務(wù)難以完成的復(fù)雜發(fā)布流程。落實到代碼級別,即我們只需要把精力集中在編寫 Jenkinsfile 文件上,然后將其隨同代碼庫一起托管,Jenkins可以根據(jù)Jenkinsfile來迅速拉起項目的CI流程,方便高效。
但是隨著多個項目的試行、落地,發(fā)現(xiàn)基于Jenkins2.0的Pipeline功能強大,但是具體應(yīng)用到各個項目還有如下幾個痛點:
各個項目都在編寫自己特色的Jenkinsfile,很多時候互相復(fù)制修改一下代碼實現(xiàn),Jenkinsfile冗余度非常高;
按照Jenkins1.x時代的思路,訂制化自己的CI/CD流程、郵件通知、報告輸出,轉(zhuǎn)換過程緩慢而痛苦;
遇到技術(shù)問題沒有能力解決、采用一些過時的方法和工具,而其他項目組已經(jīng)解決一些技術(shù)問題或者采用了更加先進的方法和工具,互相并不能及時分享;
為了解決這些問題,經(jīng)過項目反復(fù)調(diào)研和摸底,最終采用了中開社上開源的Jenkins2.0的Pipeline共創(chuàng)庫iPipeline(又稱plll庫)來輔助本項目重構(gòu)CI流程。
iPipeline是簡化CI Pipeline部署的工具集,是面向開發(fā)人員和CI配置管理員的函數(shù)庫,其封裝了Jenkins 2.0的常用函數(shù),集成了Gerrit、制品庫、云CI、度量、告警采集、郵件通知,另外提供docker封裝的工具集(復(fù)雜度、Klocwork、度量分析、度量導(dǎo)入等)。利用其可以幫助我們節(jié)省很多精力,避免重復(fù)造輪子,因此非常滿足我們項目的需求。
問題描述
iPipeline框架在本項目的實踐過程中確實提高了很多效率和幸福感,但結(jié)合本項目一些實際的使用情況,發(fā)現(xiàn)其仍然存在一些優(yōu)化和改進的點。為此針對我們項目的需要,我們對iPipeline做了如下一些優(yōu)化并實踐。
問題1
利用plll庫提供的pdocker接口,可以很方便地在指定的節(jié)點上運行指定的Docker容器來完成相關(guān)CI任務(wù)。比如本項目圈復(fù)雜度檢查已經(jīng)Docker化,因此可以利用pdocker接口,通過配置上鏡像名、映射目錄以及需要運行的指令與腳本來執(zhí)行代碼的圈復(fù)雜度檢查。
但是實際在對pdocker接口的使用過程中發(fā)現(xiàn),plll庫每次都會去節(jié)點上pull鏡像,然后再運行,這對于鏡像其實已經(jīng)存在于本地節(jié)點的情況其實并沒有必要,因此需要改造。
問題2
目前plll庫提供的Update接口僅支持Gerrit代碼倉庫的代碼檢出更新,但本項目運行某些用例測試需要的報文存儲于SVN庫上,因此有必要擴充plll庫原有接口,使其支持SVN庫的代碼更新
帶著這兩個問題,我們對plll庫做出了對應(yīng)的一些優(yōu)化并且實踐之。
優(yōu)化實踐
優(yōu)化1:pdocker接口是否需要拉取鏡像由用戶自定義
改造pdocker接口,添加參數(shù)來控制是否需要pull鏡像,接口代碼片段如下:
/**
* 工具名稱:docker執(zhí)行
* 工具描述:
* image - 鏡像的全路徑
* needPull - 是否需要pull鏡像
* before_cmd - 以root執(zhí)行的命令行,在執(zhí)行user_cmd前執(zhí)行
* volumes - 路徑映射清單,"a:b,c:d"
* params - 執(zhí)行參數(shù)
* profile - 環(huán)境文件,可執(zhí)行
* user_cmd - 以當前用戶執(zhí)行的命令行(需要鏡像支持adduser命令)
* after_cmd - 以root執(zhí)行的命令行,在執(zhí)行user_cmd后執(zhí)行
* local_dir - 存放臨時文件的目錄(要求有權(quán)限映射到容器內(nèi))
* shared_dir - 存放代碼和產(chǎn)出文件的目錄(要求有權(quán)限映射到容器內(nèi))
* sh_exec - shell進程,默認為sh
**/
def call(image, needPull, before_cmd, volumes='',params='', profile='', user_cmd='', after_cmd='',
local_dir=env.LOCAL, shared_dir=env.SHARED, sh_exec='sh'){
// ...此處代碼省略...
if( needPull =="no"){
echo "no need to pull image !!! The image exists in local!"
writeFile file:docker_entry_file, text:"""
set -e
docker run --rm ${params} ${volumes} ${image} ${sh_exec} -x -c ${docker_run_file}
"""
}elseif( needPull =="yes"){
writeFile file:docker_entry_file, text:"""
set -e
docker pull ${image}
docker run --rm ${params} ${volumes} ${image} ${sh_exec} -x -c ${docker_run_file}
"""
}
// ...此處代碼省略...
}
由代碼可以看出,通過添加needPull參數(shù),即可由用戶自定義是否需要pull鏡像。
使用舉例:
例如本項目調(diào)用pdocker接口利用自制docker鏡像完成代碼圈復(fù)雜度檢查:
pnode("${env.NODE_NAME}"){
plll.Check("CCN_DOCKER","CCN_DOCKER",[
run_execute:{ pdocker (
/* image */"docker.zte.com.cn:5000/10010891/lizard:v1",
/* need pull */"no",
/* cmd */"cd /home/code/ && chmod -R 777 * && cd script/VerifyCI/CCNCheck/ && sh +x lizard.sh",
/* volumes */"-v ${env.SHARESPACE}/${env.XXXXX_DIR}:/home",
/* params */"--privileged",
)
},
param:[
report_file:[]
]
]);
}
由于docker.zte.com.cn:5000/10010891/lizard:v1已經(jīng)存在于我們的外掛節(jié)點上,因此此處needPull參數(shù)置為no即可控制pdocker內(nèi)部無需再去pull鏡像。
優(yōu)化2:擴充框架Update接口,使其支持SVN代碼更新
優(yōu)化Plll庫代碼,加入UpdateSVN接口來支持SVN庫的代碼檢出與更新
/**
* 功能名稱:Update
* 功能描述:通過SVN更新代碼
**/
defUpdateSVN(name, desc, args){
LogDebug("[DEBUG] Update: ${name}, ${desc}")
args.run_execute ={
dir("${args.scm.path}"){
svn_checkout( args.scm.keyid, args.scm.repo, args.scm.path )
}
}
/* 調(diào)用功能適配 */
FunctionAdapter("Update","update", name, desc, args){}
return
}
/**
* 工具名稱:svn_checkout
* 工具描述:svn更新代碼
* 參數(shù)描述:
* - keyid: SVN庫的Credentials ID
* - repo: SVN庫Repo路徑
* - path: 代碼下載路徑
**/
def svn_checkout(keyid, repo, path){
checkout([
$class:'SubversionSCM',
additionalCredentials:[],
excludedCommitMessages:'',
excludedRegions:'',
excludedRevprop:'',
excludedUsers:'',
filterChangelog:false,
ignoreDirPropChanges:false,
includedRegions:'',
locations:[
[credentialsId:"${keyid}", depthOption:'infinity', ignoreExternalsOption:true,local:".", remote:"${repo}"]
],
workspaceUpdater:[$class:'UpdateUpdater']
])
return
}
使用舉例:
用戶只需要配置上:
SVN庫的Credentials ID
SVN庫Repo路徑
代碼下載路徑
即可完成SVN代碼檢出和更新,示例如下:
// 先配置好SVN相關(guān)參數(shù)
env.SVN_KEY_ID ="89a6fe98-8f0c-4fe6-829e-6d1cbda188e1"
env.CASE_DIR ="/jenkins_ci/CASE_TEST/PATH"
env.CASE_SVN_URL ="svn://XXX.XX.XXX.XXX/XXXXXXX/case/XXXX"
// 調(diào)用UpdateSVN接口完成SVN庫代碼更新
plll.UpdateSVN('SVN_UP','更新SVN上報文',[
scm:[keyid:"${env.SVN_KEY_ID}", repo:"${env.CASE_SVN_URL}", path:"env.CASE_DIR"],
run_dir:"${->OUTPUT_PATH}"
])
推廣建議
本文章相關(guān)優(yōu)化改進可推廣至需要利用docker鏡像完成相關(guān)CI任務(wù)和代碼管控涉及SVN庫的項目
-
接口
+關(guān)注
關(guān)注
33文章
8459瀏覽量
150748 -
Pipeline
+關(guān)注
關(guān)注
0文章
28瀏覽量
9339
原文標題:干貨 | Jenkins2.0 Pipeline框架(iPipeline)優(yōu)化實踐之路(一)
文章出處:【微信號:ZTEdeveloper,微信公眾號:中興開發(fā)者社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論