本文從目前業界實現Jenkins的高可用的實現方案,分析各方案的優缺點,引入vivo目前使用的Jenkins高可用方案,以及目前Jenkins資源的調度方案的設計實踐和目前的落地運行效果。
一、前言
現在的企業很多都在用Jenkins做持續集成,各個業務端都依靠Jenkins,vivo Devops也是使用Jenkins來進行持續構建,部署Jenkins服務時如何保障服務的高可用變得尤為重要。
下面是目前Jenkins存在的一些問題。
Jenkins本身是單體的,即只能有一個Jenkins Master。雖然你也可以在多臺機器上部署多個Jenkins Master,但這些Master之間沒有聯系,都是各自把任務交給手下的slave去執行,沒有任何交集。
也許某個master下的slave很忙,而另一個master下的slave卻很閑,資源得不到充分利用。
當其中一個slave宕機之后,該slave上的運行的job任務沒有版本重新進行分配,需要用戶重新執行。并且slave節點離線之后沒有通知管理員。
當系統業務量比較大的時候業務請求集中在Jenkins Master上,會對Jenkins造成壓力,甚至的造成Jenkins服務不可用。
當有job任務在jenkins Master上隊列排隊的時候,Jenkins Master宕機后,隊列任務不可持久化。
Jenkins Workspace沒有自動清理功能,會導致磁盤空間不足,任務執行不了的情況。
基于以上情況,vivo Devops對Jenkins的部署架構進行優化搭建,并且配套了一套Jenkins資源調度系統用于管理Jenkins資源。
二、業界實現
目前業界也包含一些Jenkins 高可用的設計方式,但是并不能完全的滿足解決上述問題,比如:
2.1 方案一 Gearman + Jenkins
這是OpenStack團隊使用的方案。這個方案使用了gearman, gearman是個任務分發框架。
需要在每個Master上安裝好gearman的插件,并配置好能連接到gearman server,同時在每個Master必須建立相同的job。
之后運行任務的流程如下:
gearman worker運行在各個Jenkins Master中等待gearman server分發任務;
gearman client向gearman server發出運行job的請求;
gearman server通知各個gearman worker有任務拉,第一個閑著的worker會接受任務,如果所有的worker都忙,則放入gearman的任務隊列,得worker空閑時再分配;
gearman worker閑下來后會從任務隊列里取job來執行,執行完之后,將結果發回給gearman server;
gearman server將結果返回給 gearman client。
優點:
這樣各個salver資源可以得到充分利用,某個master掛掉另外的master可以繼續服務。
弊端:
每個master的slave必須配置一致,否則會造成job調度錯誤,同時會造成一些資源的浪費。當一個master出現問題,該master的任務不會進行自動重新分配。
2.2 方案二 改造Jenkins的文件存儲方式
目前Jenkins的配置文件都是直接在硬盤上以文件形式存儲的,你在JENKINS_HOME的個文件夾下能看到各種.xml文件。
有些公司在Jenkins上進行二次開發,將Jenkins的數據存儲方式改為數據庫存儲,這樣前端可以起多個Jenkins服務,后端連相同的數據庫即可。數據庫也有比較成熟的高可用方案。
優點:
可以達到Jenkins的高可用也就是某個master掛掉另外的master可以繼續服務。
弊端:
需要對Jenkins進行二次開發,使用數據庫會降低讀取資源效率下降。
2.3方案三 最簡單的Jenkins一主一備模式
平時讓Jenkins A機器提供服務,并使用SCM Sync configuration plugin保存數據,JenkinsA機器修改配置后觸發Jenkins B更新配置,一旦Jenkins A出現問題掛掉后,切換到備機Jenkins B上。
優點:
可以達到Jenkins的高可用,當master宕機后會進行切換到備機上。
弊端:
會有一批Jenkins備機存在資源浪費,切換master時間過長,會導致有段時間Jenkins服務不可用。
三、vivo Jenkins Scheduler系統目標
由于目前業界的一些實現還不能完全的滿足我們目前的需求,所以我們進行了vivo jenkins scheduler系統的設計與實現。該系統需要達到如下的目的:
提升整個構建服務可靠性時長。
保證jenkins集群的高可用,解決目前master-slave的單點問題,保證整個構建服務的可靠性時長。
降低災難時服務恢復時長。
①提供精準流控方式,在jenkins構建出現請求量過高的時候可以進行流控和持久化操作,減少對目前系統的沖擊。
②當系統壓力減少后,放開流控可以快速的對堆積的請求進行分配執行。
有效分配任務至各個子節點,保證資源的有效利用。
能保證災難時的及時切換任務至可用節點上,同時能快速的通知管理員進行處理。
能進行數據的可視化分析,能提供一系列幫助改善開發效率的視圖,比如構建時長報表、構建量報表等。
四、 vivo Jenkins Scheduler設計
該系統我們從兩大部分進行了設計,首先,我們不采用原生的Jenkins部署方案,而是采用全master的方式。第二,設計并開發了一套用于管理Jenkins集群的調度系統。
五、底層 Jenkins 工具部署方案
不采用目前單master的搭建方案,采用多master的搭建方案,master下不進行掛載slave機器,任務直接有master進行處理,master之間的關系、任務分配、離線、插件安裝等由調度系統進行管理。這樣由于vivo Jenkins Scheduler系統為高可用的,解決了目前Jenkins的單點問題。
六、系統架構圖
七、系統說明
7.1 API-Gateway
主要提供系統的外部請求,網關系統,功能包含:
權限校驗:校驗用戶發送集群管理系統的請求的權限。
智能路由:接收外部一切請求,并轉發到后端的外服上去。
限流:與監控線程配合(當構建請求達到某個閾值時),進行限流操作。
API日志統一收集:類似于一個aspect切面,記錄接口的進入和出去時的相關日志。
數據處理:對請求的參數進行數據的轉換處理。
7.2 事件中心
是整個系統通信調用的主要模塊,采用的是Spring的Event機制實現,主要核心事件如下:
Jenkins注冊事件
(EVENT_REGIST_JENKINS):
Jenkins啟動后,通過自定的插件會向系統發送注冊請求時,系統接收到后會觸發Jenkins管理模塊將Jenkins的信息注冊至調度系統中。
Jenkins宕機事件
(EVENT_DOWN_JENKINS) :
監控管理輪詢檢查Jenkins狀態,當發現有Jenkins宕機的情況會觸發該事件,Jenkins管理模塊處理將Jenkins的信息狀態設置為不可用狀態,從而是任務不能分配至該臺jenkins。
任務從分配事件 (EVENT_JOB_REDO) :
當Jenkins宕機后,如果該臺jenkins上存在未執行完的任務時候,由job監控模塊觸發,job管理莫管處理,會對該Jenkins上未執行的job進行重新分配。
任務接受事件 (EVENT_JOB_RECIVE) :
當job管理模塊接受到創建請求,會觸發該事件,由job管理模塊放入Redis執行隊列。
任務執行事件 (EVENT_JOB_EXECUTE) :
job管理模塊中的執行線程(10s執行一次,會從Redis隊列中彈出任務),彈出任務后觸發該事件,由調度中心選取合適的jenkins進行執行。
7.3 調度中心
是整個系統的核心模塊,主要的功能是進行執行job時候能選取合適的jenkins進行處理任務,包含兩個核心算法:
7.3.1 Jenkins分組算法
每臺jenkins都可以使用標簽的方式,打上多個標簽,比如jenkins可以構建java程序,使用的構建工具可以是maven和gradle,這個時候我們就可以給其打上java、maven、gradle三個標簽。
標簽的維度主要有以下幾個:
標簽配置: 判斷構建配置是否配置了標簽,根據標簽選擇對應標簽的Jenkins,比如配置了(docker等)。
構建語言: 根據構建配置的語言,比如Java、C++、Python、Go等。
構建工具和版本: 比如Maven、gradle、Ant,Cmark、Blade等。
JDK版本:比如JDK7、JDK8等。
Go語言版本:比如1.15.x.、1.16.x等。
GCC版本:如6.x、4.x等。
Python版本:2.x、3.x等。
是否存活:判斷Jenkins是否存活,如果宕機直接過濾。
(可選策略)選擇執行過該job的Jenkins,減少下載代碼的過程:(第一次構建還是會比較慢,可以采用預執行的方式,在配置構建配置的時候,就預先執行一次,這樣在用戶執行的時候就使用該job執行過得workspace,減少代碼下載的時間)。
(可選策略)根據job的構建的平均構建時長,如果構建時長達到某個配置閾值時,優先選擇構建器空閑多的Jenkins進行執行,并指出Jenkins的鎖定功能。其他的job不允許分配上來。
如果我們給Jenkins打上標簽,那么我們就可以使用標簽為維度將Jenkins進行分組,并且存入至Redis中緩存,方便后續選取Jenkins用來執行任務:
7.3.2 Jenkins選取算法
當Jenkins分組好了后,我們接受到執行的job的信息就可以使用Jenkins選取算法進行快速的選取合適的Jenkins進行處理job,如下圖所示。
其中label子線程、語言子線程……就是我們上面的Jenkins分組的維度,有多少維度,那么這里就會有多少子線程處理。
構建任務進入主線程,然后主線程會按照分組維度分組操作并進行過濾,然后獲取到每個分組中合適的Jenkins,再進行取交集(這個時候就獲取到可以執行該構建任務的Jenkins了),在判斷是否需要經過可選策略,最終得到Jenkins。
7.4 流控管理&隊列管理
調度系統中的的任務接受采用的是隊列的方式實現,當系統請求量達到閥后,系統將不會進入Redis隊列,會將請求持久化至MySQL。
后續如果有請求過來,job管理模塊會檢查數據庫MySQL中是否有請求,如果有請求,會將請求放入Redis隊列,如果沒有請求就會將當前請求放入Redis隊列,具體流程如下:
其中基于Redis實現的消息隊列的時序圖如下:
7.5 回調中心
該模塊主要是監控任務的狀態,當任務開始執行、中斷執行、執行成功、執行失敗的時候進行通知業務并存儲數據,用于保存構建記錄,方便后續數據的統計,用來完成數據的可視化。
八、實施效果
目前該系統已經投入生產環境運行,Jenkins任務已采用調度系統進行調度執行,運行穩定,運行效果。
九、后續展望
隨著vivo Jenkins 調度系統的功能慢慢完善,Jenkins的機器也越來越多,目前還大多數運行在虛擬機上,從資源利用率和業務發布效率來看,未來的業務發布形態將會是以容器為主。目前公司也在大力發展k8s的容器生態建設,
所以我們希望將Jenkins工具后期進行容器化、池化,在提高資源利用率和發布效率的同時也可以為用戶提供可靠的、簡潔的、穩定調度執行。
審核編輯:劉清
-
數據存儲
+關注
關注
5文章
986瀏覽量
51107 -
python
+關注
關注
56文章
4810瀏覽量
85074 -
MYSQL數據庫
+關注
關注
0文章
96瀏覽量
9463 -
API串口
+關注
關注
0文章
13瀏覽量
4863 -
gcc編譯器
+關注
關注
0文章
78瀏覽量
3432
原文標題:vivo自研Jenkins資源調度系統設計與實踐
文章出處:【微信號:OSC開源社區,微信公眾號:OSC開源社區】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論