自從Jenkins 2.0 版本升級之后,支持了通過代碼(Groovy DSL)來描述一個構建流水線,靈活方便地實現持續交付,大大提升 Jenkins Job 維護的效率,實現從 CI 到 CD 到轉變。而在2016 Jenkins World 大會上,Jenkins 發布了1.0版本的聲明式流水線 - Declarative Pipeline,目前已經到發布了1.2版本,它是一種新的結構化方式定義一個流水線。今天我們一起對比這兩種定義流水線的方式以及特性。
1.Pipeline特性- Pipeline As Code
Jenkins 從根本上講是一種支持多種自動化模式的自動化引擎。Pipeline 為其添加了一套強大的自動化工具,支持從簡單的持續集成到全面的持續交付。Jenkins Pipeline 特性如下:
代碼:Pipeline 以代碼的形式描述,通常存儲於源代碼控制系統,如 Git,使團隊能夠編輯,審查和迭代其流程定義。
持久性:Pipeline 可以在計划和計划外重新啟動 Jenkins Master 管理時不被影響。
可暫停:Pipeline 可以選擇停止並等待人工輸入或批准,然后再繼續 Pipeline 運行。
多功能:Pipeline 支持復雜的項目持續交付要求,包括並行分支/連接,循環和執行 Job 的能力。
可擴展:Pipeline 插件支持其 DSL 的自定義擴展以及與其他插件集成。
基於 Jenkins Pipeline,用戶可以在一個 JenkinsFile 中快速實現一個項目的從構建、測試以到發布的完整流程,並且可以保存這個流水線的定義。
下面的流程圖是在 Jenkins Pipeline 中建模的一個持續交付方案的示例:
2.Pipeline 基本概念
Node: 一個 Node 就是一個 Jenkins 節點,或者是 Master,或者是 Agent,是執行 Step 的具體運行環境,Pipeline 執行中的大部分工作都是在一個或多個聲明 Node 步驟的上下文中完成的。
Stage: 一個 Pipeline 可以從邏輯上划分為若干個 Stage,每個 Stage 代表一組操作,如:Build、Test、Deploy。注意,Stage 是一個邏輯分組的概念,可以跨多個 Node。
Step: Step 是最基本的操作單元,小到執行一個 Shell 腳本,大到構建一個 Docker 鏡像,由各類 Jenkins Plugin 提供,當插件擴展Pipeline DSL 時,通常意味着插件已經實現了一個新的步驟。
另外在 Jenkins Pipeline 中定義的 Stage(各個階段的邏輯划分),Jenkins 提供了 Stage View 插件,按照 Stage 邏輯划分任務,對用戶透明化、可視化展示流水線的執行,如下圖:
3.Scripted Pipeline
上圖通過 Jenkinsfile 定義了流水線的各個階段(不僅限這幾個階段):構建,測試以及發布,在每個階段可以執行相應的任務,而在 Scripted Pipeline 中,用戶可以使用 Groovy 語法腳本來自定義流程控制,如下:
CurrentBuild 可以獲取檔次執行的結果,可以用於判讀后續流程走向,Jenkins 還提供了更多內置環境變量以及 DSL 對象,方便我們操作流水線任務,如:BUILD_ID、JOB_NAME、BRANCH_NAME、CHANGE_ID 等等,可參考Global Variable。這種方式受 Jenkins 的限制較少,我們可以靈活控制和定義一個流水線,甚至我們可以在 JenkinsFile 中定義多個 Groovy 函數來擴展 Jenkins Pipeline 的能力。
4.Declarative Pipeline
同樣的,上圖定義了流水線的各個階段,Declarative Pipeline 這種方式受 Jenkins 限制較多,需使用預定義的結構。Jenkins 已經預置了很多描述流水線的結構,可以在沒有 Groovy 基礎上快速建立流水線,當然在 Declarative Pipeline 同樣支持寫 Groovy 腳本,但官方不推薦把腳本直接寫在流水線中,應該把這些邏輯定義在 Shared Libraries 中。
如下:
4.1 Declarative Pipeline 語法
下面介紹幾個重點 Declarative Pipeline 語法:
定義執行環境
通過 Agent 來定義 Pipeline 的執行環境,在每個 Pipeline,Agent 是必需存在的。Agent 也可以用 Label 指定具體的 Jenkins Slave Node,並且每個 Stage 可以單獨指定 Agent,靈活調度資源以及運行環境。
環境變量
可以定義為全局的,也可以為 Stage 來定義。
已定義的環境變量,可以通過 Env 來訪問,與 Scripted Pipeline 一樣,可以訪問 Jenkins 預置的環境變量。
參數
可以通過 Params 對象來訪問構建時的參數。如:
流程控制
可以通過 When 語法控制流程走向,判斷環境變量或自定義表達式,是否執行某一個 Stage,同時 Anyof, Allof 進行邏輯運算,Anyof 對應或運算,Allof 對應與運算。
超時、重試機制
資源的清理工作 & 結束后操作
使用 Post 來完成一些資源的清理工作。其和Stages平級:
清理結束階段也可以執行一個郵件通知:
並發 Stages
Declarative Pipeline 1.2 版本對並發語法做了升級:
其中 FailFast 可以控制如果並發的任務的其中一個失敗,立即結束流水線,執行清理結束任務。
5.總結
Scripted Pipeline 和 Declarative Pipeline 兩種流水線定義的主要區別在於語法和靈活性上, Declarative Pipeline 語法要求更嚴,需使用 Jenkins 預定義的DSL 結構,使用簡單; Scripted Pipeline 受限很少,限制主要在 Groovy 的結構和語法,大家可以根據個人或企業的情況選擇兩種方式,比如如果公司沒有 Groovy 技術棧,可以考慮直接使用 Declarative Pipeline, 學習曲線低,可以快速上手,並且新的 Blue Ocean Editor 插件可以幫助我們可視化的創建一個流水線,如果對Groovy非常熟悉,那Scripted Pipeline 是一個不錯的選擇。