1. 程式人生 > >「持續整合實踐系列」Jenkins 2.x 搭建CI需要掌握的硬核要點

「持續整合實踐系列」Jenkins 2.x 搭建CI需要掌握的硬核要點

# 1. 前言 隨著網際網路軟體行業快速發展,為了搶佔市場先機,企業不得不持續提高軟體的交付效率。特別是現在國內越來越多企業已經在逐步引入DevOps研發模式的變遷,在這些背景催促之下,對於企業研發團隊所需要具備的持續整合和持續交付(簡稱CI/CD)能力變得越來越不可或缺。 相信現在不管是開發人員、測試人員或者是運維人員,在求職招聘時,基本上如果是面試的是中高階以上的職位,大多都要求要具備相關CI/CD的專案建設或參與搭建經驗。 為了幫助到更多技術讀者,從本週起,將以《持續整合實踐系列》為主題,分享幾篇搭建CI持續整合實踐的技術乾貨。 關於持續整合和持續交付(CI/CD)概念的介紹,之前的文章:[《DevOps研發模式下CI/CD實踐詳解指南》](https://mp.weixin.qq.com/s/4tgWfcbi433jMSzx1Z7mqg) 中有過較詳細的介紹,如果還不清楚什麼是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 '[email protected]: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 '[email protected]:zhoujinjian/intelligent-test-platform.git' } } stage("Compile"){ steps{ //執行Gradle進行編譯和單元測試 sh "gradle clean comileJava test" } } } } ``` 簡而言之,**對於新使用者和那些希望流水線具備傳統Jenkins一樣可讀性的使用者來說,宣告式流水線更容易學習和維護。指令碼式流水線更加靈活,允許使用者不受結構結束實現更多功能**。 不過,總的來說,**任何一種流水線型別對大多數場景而言同樣適用**。好了本文作為CI持續整合系列的開篇,先介紹到這裡吧。 詳細可檢視:[原文閱讀](https://mp.weixin.qq.com/s/TuAIL7yICF0bstD