概述
XXX項目原CI系統由項目自行搭建,使用Jenkins傳統的Job方式來實現VerifyCI和MergeCI以及DailyBuild。隨著項目規模越來越大,分支越來越多,合代碼的頻率也逐漸增大的情況下,現有系統呈現出諸多不便之處。為解決這些問題,項目嘗試引入一系列現成公司級Devops研發工具并結合Jenkins2.0的Pipeline新特性來改造本項目Pipeline流程。
Pipeline as Code 是 Jenkins 2.0 版本的精華所在,是幫助 Jenkins 實現從 CI 到 CD 華麗轉身的關鍵工具。所謂 Pipeline,簡單來說,就是一套運行于 Jenkins 上的工作流框架,將原本獨立運行于單個或者多個節點的任務連接起來,實現單個任務難以完成的復雜發布流程。落實到代碼級別,即我們只需要把精力集中在編寫 Jenkinsfile 文件上,然后將其隨同代碼庫一起托管,Jenkins可以根據Jenkinsfile來迅速拉起項目的CI流程,方便高效。
但是隨著多個項目的試行、落地,發現基于Jenkins2.0的Pipeline功能強大,但是具體應用到各個項目還有如下幾個痛點:
各個項目都在編寫自己特色的Jenkinsfile,很多時候互相復制修改一下代碼實現,Jenkinsfile冗余度非常高;
按照Jenkins1.x時代的思路,訂制化自己的CI/CD流程、郵件通知、報告輸出,轉換過程緩慢而痛苦;
遇到技術問題沒有能力解決、采用一些過時的方法和工具,而其他項目組已經解決一些技術問題或者采用了更加先進的方法和工具,互相并不能及時分享;
為了解決這些問題,經過項目反復調研和摸底,最終采用了中開社上開源的Jenkins2.0的Pipeline共創庫iPipeline(又稱plll庫)來輔助本項目重構CI流程。
iPipeline是簡化CI Pipeline部署的工具集,是面向開發人員和CI配置管理員的函數庫,其封裝了Jenkins 2.0的常用函數,集成了Gerrit、制品庫、云CI、度量、告警采集、郵件通知,另外提供docker封裝的工具集(復雜度、Klocwork、度量分析、度量導入等)。利用其可以幫助我們節省很多精力,避免重復造輪子,因此非常滿足我們項目的需求。
問題描述
iPipeline框架在本項目的實踐過程中確實提高了很多效率和幸福感,但結合本項目一些實際的使用情況,發現其仍然存在一些優化和改進的點。為此針對我們項目的需要,我們對iPipeline做了如下一些優化并實踐。
問題1
利用plll庫提供的pdocker接口,可以很方便地在指定的節點上運行指定的Docker容器來完成相關CI任務。比如本項目圈復雜度檢查已經Docker化,因此可以利用pdocker接口,通過配置上鏡像名、映射目錄以及需要運行的指令與腳本來執行代碼的圈復雜度檢查。
但是實際在對pdocker接口的使用過程中發現,plll庫每次都會去節點上pull鏡像,然后再運行,這對于鏡像其實已經存在于本地節點的情況其實并沒有必要,因此需要改造。
問題2
目前plll庫提供的Update接口僅支持Gerrit代碼倉庫的代碼檢出更新,但本項目運行某些用例測試需要的報文存儲于SVN庫上,因此有必要擴充plll庫原有接口,使其支持SVN庫的代碼更新
帶著這兩個問題,我們對plll庫做出了對應的一些優化并且實踐之。
優化實踐
優化1:pdocker接口是否需要拉取鏡像由用戶自定義
改造pdocker接口,添加參數來控制是否需要pull鏡像,接口代碼片段如下:
/**
* 工具名稱:docker執行
* 工具描述:
* image - 鏡像的全路徑
* needPull - 是否需要pull鏡像
* before_cmd - 以root執行的命令行,在執行user_cmd前執行
* volumes - 路徑映射清單,"a:b,c:d"
* params - 執行參數
* profile - 環境文件,可執行
* user_cmd - 以當前用戶執行的命令行(需要鏡像支持adduser命令)
* after_cmd - 以root執行的命令行,在執行user_cmd后執行
* local_dir - 存放臨時文件的目錄(要求有權限映射到容器內)
* shared_dir - 存放代碼和產出文件的目錄(要求有權限映射到容器內)
* 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參數,即可由用戶自定義是否需要pull鏡像。
使用舉例:
例如本項目調用pdocker接口利用自制docker鏡像完成代碼圈復雜度檢查:
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已經存在于我們的外掛節點上,因此此處needPull參數置為no即可控制pdocker內部無需再去pull鏡像。
優化2:擴充框架Update接口,使其支持SVN代碼更新
優化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 )
}
}
/* 調用功能適配 */
FunctionAdapter("Update","update", name, desc, args){}
return
}
/**
* 工具名稱:svn_checkout
* 工具描述:svn更新代碼
* 參數描述:
* - 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相關參數
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"
// 調用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}"
])
推廣建議
本文章相關優化改進可推廣至需要利用docker鏡像完成相關CI任務和代碼管控涉及SVN庫的項目
-
接口
+關注
關注
33文章
8601瀏覽量
151167 -
Pipeline
+關注
關注
0文章
28瀏覽量
9367
原文標題:干貨 | Jenkins2.0 Pipeline框架(iPipeline)優化實踐之路(一)
文章出處:【微信號:ZTEdeveloper,微信公眾號:中興開發者社區】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論