1. 前言
隨着互聯網軟件行業快速發展,為了搶占市場先機,企業不得不持續提高軟件的交付效率。特別是現在國內越來越多企業已經在逐步引入DevOps研發模式的變遷,在這些背景催促之下,對於企業研發團隊所需要具備的持續集成和持續交付(簡稱CI/CD)能力變得越來越不可或缺。
相信現在不管是開發人員、測試人員或者是運維人員,在求職招聘時,基本上如果是面試的是中高級以上的職位,大多都要求要具備相關CI/CD的項目建設或參與搭建經驗。
為了幫助到更多技術讀者,從本周起,將以《持續集成實踐系列》為主題,分享幾篇搭建CI持續集成實踐的技術干貨。
關於持續集成和持續交付(CI/CD)概念的介紹,之前的文章:《DevOps研發模式下CI/CD實踐詳解指南》 中有過較詳細的介紹,如果還不清楚什么是CI/CD的讀者,可以在閱讀本文前先,參考一下這篇文章。
2. CI系列大綱
市面上關於CI/CD的建設如果僅從工具、框架層面來講,方案有挺多,如TeamCity
、GitLab CI
、Bamboo
、Circle CI
、Travis CI
、Jenkins
、公司自研
(在研發建設CI/CD能力時,除了CI/CD工具、框架鏈的建設外,還包括研發協同文化的建設等, 文化層面的這個不在本系列的討論范圍內)。
而在眾多的持續集成CI建設工具體系中,Jenkins基本上可以說是獨占鰲頭,也是大多數公司最常用、最首選的工具之一,占據了將近70%以上的市場。
而隨着Jenkins本身的不斷發展,當前Jenkins已演變發展到了2.x系列,在Jenkins 2.x系列中,其中最核心的特性是引入了流水線機制,並提出了流水線即代碼(pipeline as code)的理念。
因此本系列也將以Jenkins 2.x作為《持續集成實踐系列》的載體,為大家介紹在結合Jenkins 2.x搭建持續集成CI能力過程中常見的一些知識要點和實現過程。
系列大綱分為(初步擬訂):
- Jenkins 2.x 搭建CI需要掌握的硬核要點(一)
- Jenkins 2.x 搭建CI流水線執行流程(二)
- Jenkins 2.x 搭建CI流水線實現案例(三)
- Jenkins 2.x 搭建CI流水線通知機制(四)
- Jenkins 2.x 搭建CI擴展流水線:自定義共享庫(五)
PS: 當然Jenkins 2.x & CI流水線的知識要點遠不止如此。
3. 先介紹一下Jenkins 2.x
Jenkins 2本身的概念比較寬泛。在特定的上下文環境中,它用來泛指支持流水線即代碼及其它類似Jenkinsfile等新特性的新版Jenkins。
Jenkins 1.X版本主要通過插件的方式來實現,確切地講,Jenkins 2也是通過對已有插件的重點升級和新插件的引入來獲取新功能。
相比之前,用戶只能通過WEB界面進行配置的方式來定義Jenkins任務,Jenkins 2則通過使用Jenkins DSL和Groovy語言編寫程序,用戶可以定義流水線並執行各種任務。
這里提到的DSL代表領域特定語言(Domain-Specific Language),可以理解為一種適用於Jenkins的編程語言。DSL基於Grovvy實現,並通過概念和結構封裝了Jenkins的特定功能。
Jenkins 2推薦使用名為Jenkinsfile的文件保存任務配置和流水線信息,不同的項目和分支都會有自己的Jenkinsfile,其內容各不相同。你可以將全部代碼寫在一個Jenkinsfile中,也可以通過共享庫的方式調用外部代碼。
4. Jenkins 2.x 實現流水線的兩種語法
當我們通過Jenkins 2.x實現流水線時,有兩種不同的語法樣式:腳本式語法(script syntax)和聲明式語法(declarative syntax)。
腳本式語法(script syntax)是Jenkins最開始實現流水線即代碼的方式,這是一種命令式風格,在以前版本的Jenkins中,流水線即代碼大體就是Groovy腳本,其中插件部分針對Jenkins的DSL步驟。這種方式幾乎沒有結構上的約束,程序流程也基於Groovy語法結構實現。
這種模式現在被稱為腳本式流水線。在腳本式流水線中,DSL支持為數眾多的任務步驟,但是仍然缺失了部分面向Jenkins任務的核心特性,比如,構建后處理、流水線結構錯誤檢查以及基於不同執行狀態發送通知的功能。當然大多數功能都可以通過Groovy編程機制來模擬實現,比如try-catch-finally語法。但是這在面向Jenkins編程的基礎上對Groovy語言技能提出了更高的要求。
而聲明式語法,是Jenkins提供的一種新的選擇,聲明式風格的流水線代碼被編排在清晰的段落中,相對於只關注實現邏輯。
5. 如何選擇腳本式語法或聲明式語法
那么有哪些因素會影響選擇腳本式語法或聲明式語法呢?和大多數事情一樣,這也不是一個嚴謹的科學問題。在特定的情況下,對比需求、實現的結構和流程以及構建流水線的人員技能和背景,二者可能各有千秋。
比如,腳本式流水線具有以下優點:
- 更少的代碼段落和弱規范要求。
- 更強大的程序代碼能力。
- 更像編寫代碼程序。
- 傳統的流水線即代碼模型,用戶熟悉並向后兼容性。
- 更靈活的自定義代碼操作。
- 能夠構建更復雜的工作流和流水線。
但同時,腳本式流水線也具有以下缺點:
- 普遍要求更高的編程水平。
- 語法檢查受限於Groovy語言及環境。
- 和傳統的Jenkins模型有很大差異。
- 與聲明式流水線的實現相比,同一工作流會更復雜。
看一則簡單的,腳本式流水線示例:
node("worker_node1"){
stage("Source"){
//從Git倉庫中獲取代碼
git 'git@github.com:zhoujinjian/intelligent-test-platform.git'
}
stage("Compile"){
//運行Gradle進行編譯和單元測試
sh "gradle clean comileJava test"
}
}
而聲明式流水線優點有:
- 更結構化,貼近傳統的Jenkins Web表單形式。
- 更強大的聲明內容能力,高可讀性。
- 可以能過Blue Ocean圖形化界面自動生成。
- 段落可映射到常見的Jenkins概念,比如通過。
- 更友好的語法檢查和錯誤識別。
- 提升流水線間的一致性。
但如此同時,聲明式流水線的缺點也很明顯:
- 對迭代邏輯支持較弱(相比程序而已)
- 對於傳統的Jenkins中部分功能缺乏支持。
- 更嚴格的結構。
- 目前對於復雜的流水線和工作流難以勝任。
聲明式流水線示例:
pipeline{
agent{
lable "worker_node1"
}
stages{
stage("Source"){
steps{
//從Git倉庫中獲取代碼
git 'git@github.com:zhoujinjian/intelligent-test-platform.git'
}
}
stage("Compile"){
steps{
//運行Gradle進行編譯和單元測試
sh "gradle clean comileJava test"
}
}
}
}
簡而言之,對於新用戶和那些希望流水線具備傳統Jenkins一樣可讀性的用戶來說,聲明式流水線更容易學習和維護。腳本式流水線更加靈活,允許用戶不受結構結束實現更多功能。
不過,總的來說,任何一種流水線類型對大多數場景而言同樣適用。好了本文作為CI持續集成系列的開篇,先介紹到這里吧。
詳細可查看:原文閱讀