Jenkins Kubernetes Slave 調度效率優化小記


Jenkins K8S Slave 調度效率優化#

by kimmin


使用kubernetes為測試工具Gatling進行大規模壓測,壓測期間發現Jenkins調度壓測實例較慢,單批幾百實例需要十分鍾左右也不能保證完整調度。

結合Jenkins Master源碼Jenkins Kubernetes插件源碼,對調度進行了細節的優化。調優過程中目標實例個數都設為300,調優后可以大體上允許一分鍾內從Jenkins Master調度完畢。如果目標實例個數線性增加,調度的時間也不會有明顯變化。
經過調優后,目前生成動態Jenkins Slave主要的耗時瓶頸是在Jenkins Master的任務隊列的填充上,目前可能已經將消費者端監聽隊列並且計算期待實例個數的算法調整到了最aggressive的策略,但是生產者喂Queue的效率低下導致消費者出於飢餓狀態。

繼續對Queue生產者端進行調優,應該需要修改Jenkins Master的源碼並且會對正常的構建任務進Queue產生未知影響,可能短期不會考慮。

如果要對Jenkins Master進行調優,可以從以下幾點着手:

  1. Jenkins的Master核心是由一系列定時任務組織起來的,目前瓶頸是在Jenkins Master的Queue生產者端,主要是調度任務在多級的Queue里面狀態遷移,這個做Queue內Job狀態遷移核心任務的執行間隔在Jenkins源碼里面是hardcode為5秒鍾,所以最壞情況下一個任務需要等待5s,才會在Queue內變化一次狀態,即使發生了狀態變化,沒有進入Pending狀態的Job也不會被算進NodeProvisioner的期待Slave列表中。那么我們可以修改這里的間隔來加速調度。
  2. Jenkins的Slave生成的任務是由一個Jenkins各組件共享的線程池來執行的,這個線程池使用的是java.util.concurrent.ExecutorService的newCachedThreadPool,池內用容量為0的java.util.concurrent.SynchronousQueue來維系生產者消費者的關系,之所以用這個線程池是為了讓生產者進程當沒有分配到線程時阻塞在submit方法。但是由於這種線程池對突來的大量任務會做緩沖導致一些任務沒有辦法立即調度,優化可以使用一個預聲明線程充足的有界隊列替換掉當前線程池

Jenkins Master和Kubernetes插件之間的關系的是什么?###

大體上,Kubernetes插件只是實現了Jenkins Master里Cloud類的provision接口ComputerLauncher的launch接口,provision接口是Jenkins Master想要生成一個Slave的時候調用的,那么Kubernetes插件只奉命做事和Kubernetes APIserver通信按照Pod Template創建一個用作Slave的Pod進行工作,launch接口是用來讓Jenkins Master的啟動一個Slave的,但是由於Kubernetes里面容器實例的創建是異步的過程,所以插件里launch只是在做輪詢Pod狀態來等待Pod創建完畢結束launch的過程。Kubernetes的Scale效率遠大於目前壓測實例的創建效率,所以我們定位瓶頸也是從Jenkins Master和Kubernetes插件上開始。


Jenkins Master參數優化###

快照間隔/調度間隔參數#####

按從消費者到生產者的順序進行分析,首先我們把Jenkins Master計算集群負載的快照間隔hudson.model.LoadStatistics.clock從10秒縮短到了2秒,btw,Jenkins Master防守式地用時間戳快照間隔最小限定到了1秒,但是為了可能更快的進行調度。我們並且且將進行provision的間隔hudson.slaves.NodeProvisioner.recurrencePeriod從6秒縮短到了2秒,這里參數比較危險的是當provision間隔小於快照間隔,可能導致短時間內無限創建slave的bug。

冷啟動初次調度等待參數#####

Jenkins服務啟動后的第一次provision是由參數hudson.slaves.NodeProvisioner.initialDelay決定的,這個參數是為了確保讓靜態的Jenkins Slave和Master建立起來連接,由於我們使用的Kubernetes插件其實並不存在雙向的通信,所以我們把初始的調度delay從100秒縮小到了20秒。

快照存儲EMA(Exponential Moving Average)變化參數#####

hudson.model.LoadStatistics.decay用於EMA抑制負載的抖動,這個參數原本的意義是用於抑制評估master負載的抖動,並且允許給使用者人肉反應時間來終止一些畸形的Job。默認decay是0.9。比如上一次快照負載為1,那么下次入隊列的快照評分就會是1 + (1-0.9)*當前負載,我們把快照decay設成了0.1,允許負載大幅度變化。從而每次provision的時候,Jenkins Master評估的負載就是在當前盡可能真實的負載之上評估的新實例個數。這個也是主要提升調度性能的參數之一。

EMA Threshold對浮點型負載進行整數對齊的參數#####
hudson.slaves.NodeProvisioner.MARGIN_DECAY
hudson.slaves.NodeProvisioner.MARGIN
hudson.slaves.NodeProvisioner.MARGIN0

如上圖所示,把調整這里的參數使負載做整數對齊的時候盡量向上對齊,從而多provision一個slave,以此來提高效率。

其他#####

另外發現一處可能的BUG,提交給了社區。

https://github.com/jenkinsci/kubernetes-plugin/pull/248


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM