<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Kubernetes 動(dòng)態(tài)創(chuàng)建 Jenkins Agent 壓力測(cè)試

          共 11006字,需瀏覽 23分鐘

           ·

          2020-12-04 16:24

          前面我們利用 Kubernetes 提供的彈性,在 Kubernetes 上動(dòng)態(tài)創(chuàng)建 Jenkins Slave,本文主要是對(duì) Jenkins 進(jìn)行大規(guī)模構(gòu)建的壓力測(cè)試。

          1. 集群配置

          1.1 Kubernetes 版本

          這里使用的是 v1.16.7

          kubectl?version

          Client?Version:?version.Info{Major:"1",?Minor:"16",?GitVersion:"v1.16.7",?GitCommit:"be3d344ed06bff7a4fc60656200a93c74f31f9a4",?GitTreeState:"clean",?BuildDate:"2020-02-11T19:34:02Z",?GoVersion:"go1.13.6",?Compiler:"gc",?Platform:"linux/amd64"}
          Server?Version:?version.Info{Major:"1",?Minor:"16",?GitVersion:"v1.16.7",?GitCommit:"be3d344ed06bff7a4fc60656200a93c74f31f9a4",?GitTreeState:"clean",?BuildDate:"2020-02-11T19:24:46Z",?GoVersion:"go1.13.6",?Compiler:"gc",?Platform:"linux/amd64"}

          1.2 節(jié)點(diǎn)數(shù)量

          集群節(jié)點(diǎn)總數(shù), 16 個(gè)

          kubectl?get?node?|grep?"Ready"?|?wc?-l

          16

          其中 master 節(jié)點(diǎn) 3 個(gè),worker 節(jié)點(diǎn) 13 個(gè)。

          kubectl?get?node?|grep?"master"?|?wc?-l

          3
          kubectl?get?node?|grep?"worker"?|?wc?-l

          13

          1.3 CI 節(jié)點(diǎn)

          選取其中的 10 個(gè)節(jié)點(diǎn)用于 CI 構(gòu)建,5 個(gè) 8 核 32 G ,5 個(gè) 16 核 32 G 。給這些節(jié)點(diǎn)打上 Label node-role.kubernetes.io/worker=ci ,用于構(gòu)建 Pod 選取 Node 使用,避免影響集群上的其他負(fù)載。

          kubectl?top?node?-l?node-role.kubernetes.io/worker=ci

          NAME???CPU(cores)???CPU%???MEMORY(bytes)???MEMORY%
          ci1????67m??????????0%?????1268Mi??????????8%
          ci10???100m?????????1%?????1273Mi??????????4%
          ci2????80m??????????1%?????1258Mi??????????8%
          ci3????90m??????????1%?????1274Mi??????????8%
          ci4????72m??????????0%?????1286Mi??????????8%
          ci5????80m??????????1%?????1276Mi??????????8%
          ci6????80m??????????1%?????1268Mi??????????4%
          ci7????89m??????????1%?????1293Mi??????????4%
          ci8????118m?????????1%?????1285Mi??????????4%
          ci9????81m??????????1%?????1268Mi??????????4%

          1.4 CI 資源配置

          • Pod 數(shù)量限制,足夠支持 1100 Pod

          按照官網(wǎng)文檔描述,Kubernetes 最大支持 5000 個(gè)節(jié)點(diǎn),15 W 個(gè) Pod。

          At?v1.18,?Kubernetes?supports?clusters?with?up?to?5000?nodes.?More?specifically,?we?support?configurations?that?meet?all?of?the?following?criteria:

          No?more?than?5000?nodes
          No?more?than?150000?total?pods
          No?more?than?300000?total?containers
          No?more?than?100?pods?per?node

          除了集群 Pod 總數(shù)有上限,這里有意義的是 kubelet 對(duì) pod 最大數(shù)量的限制。

          cat?/var/lib/kubelet/config.yaml|grep?max

          maxOpenFiles:?1000000
          maxPods:?110

          10 個(gè) CI 節(jié)點(diǎn),總共能提供 1100 個(gè) Pod,除去一些系統(tǒng)組件占用,已經(jīng)足夠。

          • Memory 和 CPU,足夠支持 400 條流水線并發(fā)

          每個(gè) Pod 大約占用 500 MB Memory,CPU 是構(gòu)建時(shí)瞬時(shí)值會(huì)比較高,但是維持時(shí)間較短,這里不用太多考慮。5 個(gè) 8 核 32 G ,5 個(gè) 16 核 32 G,總共有 120 核 320 G 內(nèi)存,足夠支撐 400 ( > 320 * 0.8 / 0.5 = 512) 條流水線同時(shí)構(gòu)建。另外,由于 Jenkins Agent Pod 配置的是軟親和,當(dāng) CI 節(jié)點(diǎn)資源不足時(shí),也可以調(diào)度到其他節(jié)點(diǎn)。

          2. Jenkins 配置

          2.1 Jenkins

          即使流水線是在 Agent 上執(zhí)行,但是大量的流水線同時(shí)運(yùn)行,也會(huì)對(duì) Jenkins 產(chǎn)生壓力,這里給 Jenkins 的 limit 為 8 核 16 GB ,也就是最大允許消耗的資源量。

          Jenkins 采用 Helm 部署,運(yùn)行在 Kubernetes 上。下面是截取的部分 Deployment 信息:

          kind:?Deployment
          apiVersion:?apps/v1
          metadata:
          ??name:?ks-jenkins
          ??namespace:?ks-jenkins
          ??labels:
          ????app.kubernetes.io/managed-by:?Helm
          ????chart:?jenkins-0.19.0
          spec:
          ??replicas:?1
          ??template:
          ????metadata:
          ??????labels:
          ????????chart:?jenkins-0.19.0
          ????spec:
          ??????containers:
          ????????-?name:?ks-jenkins
          ??????????image:?'jenkins/jenkins:2.176.2'
          ??????????env:
          ????????????-?name:?JAVA_TOOL_OPTIONS
          ??????????????value:?>-
          ????????????????-Xms3g?-Xmx6g?-XX:MaxRAM=16g
          ????????????????-Dhudson.slaves.NodeProvisioner.initialDelay=20
          ????????????????-Dhudson.slaves.NodeProvisioner.MARGIN=50
          ????????????????-Dhudson.slaves.NodeProvisioner.MARGIN0=0.85
          ????????????????-Dhudson.model.LoadStatistics.clock=5000
          ????????????????-Dhudson.model.LoadStatistics.decay=0.2
          ????????????????-Dhudson.slaves.NodeProvisioner.recurrencePeriod=5000
          ????????????????-Dio.jenkins.plugins.casc.ConfigurationAsCode.initialDelay=10000
          ????????????????-verbose:gc?-Xloggc:/var/jenkins_home/gc-%t.log
          ????????????????-XX:NumberOfGCLogFiles=2?-XX:+UseGCLogFileRotation
          ????????????????-XX:GCLogFileSize=100m?-XX:+PrintGC?-XX:+PrintGCDateStamps
          ????????????????-XX:+PrintGCDetails?-XX:+PrintHeapAtGC?-XX:+PrintGCCause
          ????????????????-XX:+PrintTenuringDistribution?-XX:+PrintReferenceGC
          ????????????????-XX:+PrintAdaptiveSizePolicy?-XX:+UseG1GC
          ????????????????-XX:+UseStringDeduplication?-XX:+ParallelRefProcEnabled
          ????????????????-XX:+DisableExplicitGC?-XX:+UnlockDiagnosticVMOptions
          ????????????????-XX:+UnlockExperimentalVMOptions?
          ????????????-?name:?kubernetes.connection.timeout
          ??????????????value:?'60000'
          ????????????-?name:?kubernetes.request.timeout
          ??????????????value:?'60000'
          ??????schedulerName:?default-scheduler
          ??????...

          2.2 Jenkins Agent

          使用 Kubernetes 提供的動(dòng)態(tài) Pod 作為 Jenkins Agent 用于構(gòu)建流水線,具體配置可以參考頂部的文檔鏈接。

          Pod 中的 Maven 容器鏡像 Dockerfile 主要內(nèi)容如下:

          centos:7
          #?java
          RUN?yum?install?-y?java-1.8.0-openjdk?\
          ????java-1.8.0-openjdk-devel?\
          ????java-1.8.0-openjdk-devel.i686
          ????...

          為了減少對(duì)其他節(jié)點(diǎn)的影響,在 Jenkins 中配置了軟親和,將創(chuàng)建的動(dòng)態(tài) Pod 盡量調(diào)度到指定的 CI 節(jié)點(diǎn)。

          spec:
          ??affinity:
          ????nodeAffinity:
          ??????preferredDuringSchedulingIgnoredDuringExecution:
          ??????-?weight:?1
          ????????preference:
          ??????????matchExpressions:
          ??????????-?key:?node-role.kubernetes.io/worker
          ????????????operator:?In
          ????????????values:
          ????????????-?ci

          2.4 Jenkins 中 Kubernetes 插件配置

          將容器數(shù)量和等待時(shí)間設(shè)置為一個(gè)較大值。

          2.5 測(cè)試用的 Pipeline Demo

          Demo 采用的是一個(gè) Java 項(xiàng)目,克隆代碼、執(zhí)行單元測(cè)試、鏡像構(gòu)建。由于鏡像內(nèi)容都一樣,這里就沒有推送鏡像,同時(shí)也減少了外部依賴。gitee.com 對(duì)拉取頻率也有限制,建議使用自己搭建的代碼倉庫。

          pipeline?{
          ??agent?{
          ????node?{
          ??????label?'maven'
          ????}
          ??}
          ??environment?{
          ????????REGISTRY?=?'docker.io'
          ????????DOCKERHUB_NAMESPACE?=?'shaowenchen'
          ????????APP_NAME?=?'devops-java-sample'
          ????????TAG_NAME?=?"SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER"
          ????}
          ??stages?{
          ????stage('checkout')?{
          ??????steps?{
          ????????container('maven')?{
          ??????????git?branch:?'master',?url:?'https://gitee.com/shaowenchen/devops-java-sample.git'
          ????????}
          ??????}
          ????}
          ????stage('unit?test')?{
          ??????steps?{
          ????????container('maven')?{
          ??????????sh?'mvn?clean?-o?-gs?`pwd`/configuration/settings.xml?test'
          ????????}

          ??????}
          ????}
          ????stage('build')?{
          ??????steps?{
          ????????container('maven')?{
          ??????????sh?'mvn?-o?-Dmaven.test.skip=true?-gs?`pwd`/configuration/settings.xml?clean?package'
          ??????????sh?'docker?build?-f?Dockerfile-online?-t?$REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER?.'
          ????????}

          ??????}
          ????}
          ????stage('sleep?0.5h')?{
          ??????steps?{
          ????????sh?'sleep?1800'
          ??????}
          ????}
          ??}
          }

          2.6 遠(yuǎn)程觸發(fā)流水線腳本

          #?-*-?coding:?utf-8?-*-
          #?import?time
          import?requests

          jenkins_job_name?=?"new"
          Jenkins_url?=?"http://jenkins.chenshaowen.com:8080"
          jenkins_user?=?"admin"
          jenkins_pwd?=?"password"
          #?buildWithParameters?=?True??#?if?there?are?parameters
          buildWithParameters?=?False
          jenkins_params?=?{'token':?'mytoken',
          ??????????????????'param1':?'valu1'}

          def?trigger():
          ????try:
          ????????auth?=?(jenkins_user,?jenkins_pwd)
          ????????crumb_data?=?requests.get(
          ????????????"{0}/crumbIssuer/api/json".format(Jenkins_url),
          ????????????auth=auth,
          ????????????headers={
          ????????????????'content-type':?'application/json'})
          ????????if?str(crumb_data.status_code)?==?"200":

          ????????????if?buildWithParameters:
          ????????????????data?=?requests.get(
          ????????????????????"{0}/job/{1}/buildWithParameters".format(
          ????????????????????????Jenkins_url,
          ????????????????????????jenkins_job_name),
          ????????????????????auth=auth,
          ????????????????????params=jenkins_params,
          ????????????????????headers={
          ????????????????????????'content-type':?'application/json',
          ????????????????????????'Jenkins-Crumb':?crumb_data.json()['crumb']})
          ????????????else:
          ????????????????data?=?requests.get(
          ????????????????????"{0}/job/{1}/build".format(
          ????????????????????????Jenkins_url,
          ????????????????????????jenkins_job_name),
          ????????????????????auth=auth,
          ????????????????????params=jenkins_params,
          ????????????????????headers={
          ????????????????????????'content-type':?'application/json',
          ????????????????????????'Jenkins-Crumb':?crumb_data.json()['crumb']})
          ????????????print(data.status_code)

          ????????????if?str(data.status_code)?==?"201":
          ????????????????print("Jenkins?job?is?triggered")
          ????????????else:
          ????????????????print("Failed?to?trigger?the?Jenkins?job")

          ????????else:
          ????????????print("Couldn't?fetch?Jenkins-Crumb")
          ????????????raise

          ????except?Exception?as?e:
          ????????print("Failed?triggering?the?Jenkins?job")
          ????????print("Error:?"?+?str(e))

          if?__name__?==?"__main__":
          ????for?i?in?range(400):
          ????????#?time.sleep(1)
          ????????print("Trigger-"?+?str(i))
          ????????trigger()

          3. 測(cè)試策略

          為了更好的測(cè)試 Jenkins 在 Kubernetes 上執(zhí)行流水線的性能,在上面的配置中,我提供了足夠 400 條流水線并發(fā)執(zhí)行的資源。

          由于首次運(yùn)行流水線時(shí),需要拉取鏡像、對(duì)依賴包進(jìn)行緩存。在執(zhí)行測(cè)試之前,執(zhí)行 20 次流水線對(duì)節(jié)點(diǎn)進(jìn)行預(yù)熱。

          主要進(jìn)行五組測(cè)試,分別為 50、100、200、400、800 條流水線并發(fā)。

          觀察的指標(biāo)

          • 觸發(fā)流水線成功率
          • Jenkins UI 能否正常打開
          • Jenkins 創(chuàng)建 Pod 的速度
          • 流水線執(zhí)行成功率
          • 失敗的原因

          4. 測(cè)試結(jié)果

          流水線并發(fā)數(shù)量觸發(fā)成功率UI 能否正常打開全部 Pod 創(chuàng)建成功耗時(shí)流水線執(zhí)行成功率失敗的原因
          5050/50可以12分鐘50/50-
          100100/100可以7分鐘100/100-
          200200/2004 秒加載7分鐘178/200Gitee 限制了拉取頻率
          400400/40011 秒加載21分鐘348/400Gitee 限制了拉取頻率
          800778/80017 秒加載18分鐘446/800觸發(fā)失敗、流水線堆積無法調(diào)度

          下面是具體的監(jiān)控?cái)?shù)據(jù)和分析

          • 50 并發(fā):正常執(zhí)行,應(yīng)該是預(yù)熱不夠充分,后半段速度變慢,創(chuàng)建時(shí)間較長(zhǎng)。
          • 100 并發(fā):正常執(zhí)行,創(chuàng)建 Pod 速度很快,3~4 秒一個(gè)
          • 200 并發(fā):觸發(fā)正常,執(zhí)行時(shí)部分流水線報(bào)錯(cuò)。這里的錯(cuò)誤,主要是拉取 git 服務(wù)器代碼受到了限制。錯(cuò)誤提示如下:
          • 400 并發(fā):有極少量調(diào)度到非 CI 節(jié)點(diǎn),同樣有大量拉取 git 服務(wù)器代碼提示錯(cuò)誤。
          • 800 并發(fā):460、461、551、552、759-776 觸發(fā)失敗。有少量調(diào)度到非 CI 節(jié)點(diǎn),大量流水線堆積在 Build Queue ,這些流水線長(zhǎng)時(shí)間不被調(diào)度,嘗試重啟 Jenkins 依然無法執(zhí)行。

          800 條流水線并發(fā),超過了集群的負(fù)載極限。Jenkins 使用的內(nèi)存達(dá)到了極限,能連接管理的 jnlp 數(shù)量也達(dá)到了極限。下面是相關(guān)的提示報(bào)錯(cuò):

          INFO:?Server?reports?protocol?JNLP-connect?not?supported,?skipping
          Aug?02,?2020?7:20:33?AM?hudson.remoting.jnlp.Main$CuiListener?error
          SEVERE:?The?server?rejected?the?connection:?None?of?the?protocols?were?accepted
          java.lang.Exception:?The?server?rejected?the?connection:?None?of?the?protocols?were?accepted
          at?hudson.remoting.Engine.onConnectionRejected(Engine.java:675)
          at?hudson.remoting.Engine.innerRun(Engine.java:639)
          at?hudson.remoting.Engine.run(Engine.java:474)

          -XX:MaxRAM=16g 的配置在 400 并發(fā)時(shí),明顯吃力,到了 800 并發(fā)時(shí),已經(jīng)不夠。之后,我又將最大內(nèi)存使用設(shè)置為 32 g 進(jìn)行測(cè)試,觸發(fā)成功率有所改善,依然達(dá)不到 100% ;Pod 創(chuàng)建速度變快,集群資源充足的情況下,依然有部分堵在 Build Queue 中無法調(diào)度。

          后來,我找了一個(gè) 202 個(gè)節(jié)點(diǎn)的集群進(jìn)行測(cè)試,Jenkins 內(nèi)存限制設(shè)置很大。通過接口不停地發(fā)送觸發(fā)請(qǐng)求,Pod 數(shù)量最高峰在 517(=520-3),Pod 中的 jnlp 與 Jenkins 連接出現(xiàn)問題。同時(shí),也伴隨著大量觸發(fā)和構(gòu)建錯(cuò)誤。下圖是,關(guān)于 Pod 數(shù)量監(jiān)控:

          5. 測(cè)試總結(jié)和建議

          從原理上講 Jenkins 的 Kubernetes 插件實(shí)現(xiàn)的功能是調(diào)用 Kubernetes 的接口,創(chuàng)建 Pod 用于構(gòu)建。創(chuàng)建的 Pod 中包含 jnlp 和真正構(gòu)建環(huán)境的容器。

          在高并發(fā)、高負(fù)載的場(chǎng)景下,瓶頸會(huì)出現(xiàn)在如下方面:

          • Jenkins 提供的 API
          • Jenkins 的調(diào)度算法
          • Jenkins 調(diào)用的 Kubernetes API
          • Kubernetes 調(diào)度創(chuàng)建 Pod 的速度
          • Pod 運(yùn)行時(shí)的資源消耗,CPU、Mem、IO 等
          • Jenkins 的 Mem 和 CPU 限制

          這次測(cè)試不算特別完善,有如下問題:

          • 預(yù)熱不夠充分。測(cè)試 50 并發(fā)的數(shù)據(jù)有明顯問題,創(chuàng)建速度比 100 并發(fā)還慢,說明有些節(jié)點(diǎn)沒有相關(guān)的鏡像或緩存。
          • Jenkins 內(nèi)存不夠充足。在 400 并發(fā)時(shí),Jenkins 的內(nèi)存使用已經(jīng)接近 limit 限制,頁面打開緩慢。

          配置建議:

          • 限制 Jenkins 同時(shí)連接 Pod 的數(shù)量,配置足夠的情況下,200 并發(fā)是沒有問題的,400 并發(fā)是可以爭(zhēng)取的。Jenkins 需要與每一個(gè) Pod 中的 jnlp 通信,控制并發(fā)數(shù)量能有效減輕 Jenkins 的負(fù)擔(dān),避免觸發(fā)失敗的發(fā)生。
          • 使用專用的 CI 節(jié)點(diǎn)。讓流水線的 Pod 在節(jié)點(diǎn)之間隨意漂移,充分享受 Kubernetes 提供的彈性固然很好,但是大量并發(fā)的流水線會(huì)擠走節(jié)點(diǎn)上的負(fù)載,導(dǎo)致其他應(yīng)用不穩(wěn)定。
          • 構(gòu)建的 Pod 需要設(shè)置合適的 request 。與創(chuàng)建應(yīng)用負(fù)載類似,過小的 request 會(huì)導(dǎo)致調(diào)度成功,但是 Pod 起不來的問題。大量流水線并發(fā)時(shí),過小的 request 可能會(huì)直接壓垮節(jié)點(diǎn)。
          • 充足的 Jenkins 內(nèi)存,16 G 基本能保證系統(tǒng)穩(wěn)定,CPU 4C 及以上即可。Java 應(yīng)用占用內(nèi)存比較多。分配充足的內(nèi)存給 Jenkins,可以提高觸發(fā)成功率,提高 Pod 的創(chuàng)建效率,同時(shí) Jenkins 也更穩(wěn)定,不容易出現(xiàn) Jenkins 頁面打不開的情況。
          • 綁定一個(gè)專門的節(jié)點(diǎn)用來運(yùn)行 Jenkins。當(dāng)給 Jenkins 設(shè)置了較大的內(nèi)存限制時(shí),隨著并發(fā)數(shù)量上升,內(nèi)存使用逐漸增加,雖然 limit 很大,但是節(jié)點(diǎn)內(nèi)存可能不夠,這樣可能會(huì)導(dǎo)致 Jenkins 被調(diào)度到其他節(jié)點(diǎn)。
          • 使用單實(shí)例 Jenkins 。Jenkins 使用磁盤文件存儲(chǔ)數(shù)據(jù),多實(shí)例會(huì)讓 Jenkins 紊亂。提示錯(cuò)誤如下:
          Error
          Jenkins?detected?that?you?appear?to?be?running?more?than?one?instance?of?Jenkins?that?share?the?same?home?directory?'/var/jenkins_home'.?This?greatly?confuses?Jenkins?and?you?will?likely?experience?strange?behaviors,?so?please?correct?the?situation.

          This?Jenkins:????449134911?contextPath=""?at?6@ks-jenkins-68b8949bb-mgmjc
          Other?Jenkins:????1869668338?contextPath=""?at?6@ks-jenkins-68b8949bb-kg49k

          原文鏈接:https://www.chenshaowen.com/blog/the-stress-test-about-kubernetes-dynamically-creates-jenkins-agent.html


          ?點(diǎn)擊屏末?|??|?即刻學(xué)習(xí)

          瀏覽 110
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  a 免费在线观看 | 干视频在线 | 多人操逼 | 人妻无码丰满中出 | 视频偷拍网址大全 |