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

狂師發表於2020-05-27

1. 前言

隨著網際網路軟體行業快速發展,為了搶佔市場先機,企業不得不持續提高軟體的交付效率。特別是現在國內越來越多企業已經在逐步引入DevOps研發模式的變遷,在這些背景催促之下,對於企業研發團隊所需要具備的持續整合和持續交付(簡稱CI/CD)能力變得越來越不可或缺。

相信現在不管是開發人員、測試人員或者是運維人員,在求職招聘時,基本上如果是面試的是中高階以上的職位,大多都要求要具備相關CI/CD的專案建設或參與搭建經驗。

為了幫助到更多技術讀者,從本週起,將以《持續整合實踐系列》為主題,分享幾篇搭建CI持續整合實踐的技術乾貨。

關於持續整合和持續交付(CI/CD)概念的介紹,之前的文章:《DevOps研發模式下CI/CD實踐詳解指南》 中有過較詳細的介紹,如果還不清楚什麼是CI/CD的讀者,可以在閱讀本文前先,參考一下這篇文章。

2. CI系列大綱

市面上關於CI/CD的建設如果僅從工具、框架層面來講,方案有挺多,如TeamCityGitLab CIBambooCircle CITravis CIJenkins公司自研(在研發建設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持續整合系列的開篇,先介紹到這裡吧。

詳細可檢視:原文閱讀

相關文章