Jenkins分布式構建與並行構建
jenkins的架構
Jenkins采用的是“master+agent(slave)”架構。Jenkins master負責提供界面、處理HTTP請求及管理構建環境;構建的執行則由Jenkins agent負責
Jenkins agent的橫向擴容:只需要增加agent就可以輕松支持更多的項目同時執行
• node:節點,指包含Jenkins環境及有能力執行項目的機器。master和agent都被認為是節點。
• executor:執行器,是真正執行項目的單元。一個執行器可以被理解為一個單獨的進程(事實上是線程)。在一個節點上可以運行多個執行器。
• agent:代理,在概念上指的是相對於Jenkins master的一種角色,實際上是指運行在機器或容器中的一個程序,它會連接上Jenkins master,並執行Jenkins master分配給它的任務。
增加agent支持並行構建
Jenkins agent作為一個負責執行任務的程序,它需要與Jenkins master建立雙向連接。連接方式有多種,這也代表有多種增加agent的方式。
標簽是什么
當agent數量變多時,如何知道哪些agent支持JDK 8、哪些agent支持Node.js環境呢?我們可以通過給agent打標簽(有時也稱為tag)來確定。
同一個agent可以擁有多個標簽。在標簽名中不能包含空格,也不能包含!、&、|、<、>、(、)這些特殊字符中的任何一個。因為包含特殊字符的標簽名與標簽表達式(用於過濾agent)沖突。
通過JNLP協議增加agent
Java網絡啟動協議(JNLP)是一種允許客戶端啟動托管在遠程Web服務器上的應用程序的協議。Jenkins master與agent通過JNLP協議進行通信。而Java Web Start(JWS)可以被理解為JNLP協議的一個客戶端。
(1)進入Manage Jenkins→Global Security→TCP port for JNLP配置頁面,如圖所示。我們可以選擇開放固定端口或者隨機開放Jenkins master的一個端口來提供JNLP服務。
隨機開放端口不利於自動化,所以選擇開放固定端口。此端口用於master與agent之間的TCP通信,與訪問Jenkins界面時的端口有別。
(2)進入Manage Jenkins→Manage Nodes→New Node頁面,如圖所示。選項“Permanent Agent”指的是常駐代理客戶端。
單擊“OK”按鈕后,進入node配置頁面
• Name:agent名稱。
• Remote root directory:agent機器上的工作目錄(Jenkins master不關心),使用絕對路徑。
• Labels:agent的標簽。
• Usage:agent的使用策略。有兩種:
◦ Use this node as much as possible,盡可能使用此agent。
◦ Only build jobs with label expressions matching this node,只有當構建任務符合本agent的標簽時,才使用此agent。
• Launch method:agent的運行方式。JNLP協議的agent選擇“Launch agent via Java WebStart”。配置完成后進入節點列表頁面,此時master節點的狀態顯示是在線的,即可用的
當節點不可用時,如node1節點,Jenkins master不再分配任務給它
(3)單擊節點列表中的node1,跳轉到“Agent node1”頁面,顯示詳情如圖所示。
JNLP協議agent連接Jenkins master還有3種方式。一是在agent機器的瀏覽器中打開此頁面,單擊“Launch”按鈕。二是通過javaws命令從master節點下載Java Web Start程序。三是無界面方式連接。第3種方式不需要界面操作,我們毫不猶豫地選擇它,因為只有這樣才方便自動化。
(4)SSH登錄到Jenkins agent機器,下載agent.jar文件(JNLP協議的客戶端),下載路徑為:<Jenkins master地址>/jenkins/jnlpJars/agent.jar。假設這台機器已經安裝好JDK,則執行命令:java-jar agent.jar-jnlpUrl http://192.168.23.11:8667/jenkins/computer/node1/slave-agent.jnlp-workDir "/app"。其中-workDir參數用於指定agent的工作目錄。當命令提示連接成功后,我們打開Jenkins master頁面,查看node1的詳情頁,如圖所示,表示已經連接成功。
agent與master之間的連接過程沒有任何權限控制。這是因為我們沒有設置Jenkins的安全控制(默認Jenkins向匿名用戶開放所有權限)。當設置了安全控制后,新建node,我們將在node的詳情頁看到連接master的命令就變成了:
其中-secret******就是agent與master之間的連接憑證。每一個JNLP客戶端的憑證都不一樣。
提示:升級Jenkins后,也需要重新下載agent.jar。agent.jar需要與Jenkins master同步升級。
最后,我們看到通過JNLP協議增加agent的方式是需要在Jenkins界面上進行手動操作的(增加節點的操作)。這部分是無法自動化的,因此,我們只在以下場景中使用這種方式。
• 在安全性要求相對較高的情況下,只能手動增加agent。
• 增加Windows agent。
通過Swarm插件增加agent
Swarm插件只需要啟動Swarm客戶端(指定Jenkins master地址),master與agent就會自動建立連接。
(1)安裝Swarm插件。
(2)確保Jenkins agent機器上安裝有JDK。
(3)在Jenkins agent機器上下載Swarm客戶端
(4)在Jenkins agent上啟動swarm-client連接服務器端。
當日志顯示連接成功后,在節點列表頁面可以看到Swarm客戶端連接成功
swarm-client部分參數的介紹。
•-deleteExistingClients:如果Jenkins master上已經存在同名的node,則先刪除。(慎用)
•-description:描述。
•-disableClientsUniqueId:默認Swarm會在node名稱后加上一個唯一ID。加上此參數后,代表取消加上唯一ID。
•-disableSslVerification:取消SSL校驗。
•-executors N:設置executor的個數。
•-labels VAL:分配給agent的標簽,如果有多個,則使用空格分隔。注意,這是給agent打標簽。
•-master VAL:指定Jenkins master的URL。
•-mode MODE:Jenkins master分配項目給agent時使用的格式,即有兩種格式,即normal(盡可能分配job)和exclusive(當與指定label匹配時才分配項目)。
•-username VAL:連接時使用的用戶名。
•-password VAL:連接時使用的密碼。不推薦使用。
•-passwordEnvVariable VAL:從環境變量中讀取密碼。推薦使用。
•-passwordFile VAL:從文本文件中讀取密碼。推薦使用。
•-retry N:最大重連次數,默認無次數限制。
•-retryInterval N:每次重連間隔時長,單位為秒。默認值為10秒。
agent部分詳解
如何在pipeline中使用標簽呢
agent部分描述的是整個pipeline或在特定階段執行任務時所在的agent。換句話說,Jenkinsmaster根據此agent部分決定將任務分配到哪個agent上執行。agent部分必須在pipeline塊內的頂層定義,而stage塊內的定義是可選的。
agent any告訴Jenkins master任何可用的agent都可以執行。
agent部分的定義可以放在階段中,用於指定該stage執行時的agent。
注意:pipeline塊內的agent部分是必需的,不能省略。
通過標簽指定agent:
當pipeline需要在JDK 8環境下進行構建時,就需要通過標簽來指定agent。代碼如下:
有些構建任務是需要在JDK 8及Windows環境下執行的。也就是說,我們需要過濾同時具有windows和jdk8標簽的agent。
上文中,在增加agent時,已經配置好了該agent上的默認工作目錄路徑,但是agent部分允許我們對工作目錄進行自定義。node除了label選項,還提供了另一個選項——customWorkspace,自定義工作目錄,寫法如下:
customWorkspace選項除了寫絕對路徑,還可以寫相對於默認工作目錄路徑的相對路徑。
不分配節點 : agent none
when指令的beforeAgent選項 :
在默認情況下,階段內所有的代碼都將在指定的Jenkins agent上執行。when指令提供了一個beforeAgent選項,當它的值為true時,只有符合when條件時才會進入該Jenkins agent。這樣就可以避免沒有必要的工作空間的分配,也就不需要等待可用的Jenkins agent了。在某些場景下,beforeAgent選項通常用於加速pipeline的執行。示例如下:
只有分支為production時,才會進入“Example Deploy”階段。這樣就可以避免在some-label的agent中拉取代碼,從而達到加速pipeline執行的目的。