<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>

          Jenkins Pipeline 流水線部署 Kubernetes 應(yīng)用

          共 11187字,需瀏覽 23分鐘

           ·

          2021-08-06 02:27

          原文鏈接:https://blog.k8s.li/jenkins-with-kubernetes.html
          背景

          雖然云原生時(shí)代有了 JenkinsXDroneTekton 這樣的后起之秀,但 Jenkins 這樣一個(gè)老牌的 CI/CD 工具仍是各大公司主流的使用方案。比如我司的私有云產(chǎn)品打包發(fā)布就是用這老家伙完成的。然而傳統(tǒng)的 Jenkins Slave 一主多從方式會(huì)存在一些痛點(diǎn),比如:

          • 每個(gè) Slave 的配置環(huán)境不一樣,來完成不同語言的編譯打包等操作,但是這些差異化的配置導(dǎo)致管理起來非常不方便,維護(hù)起來也是比較費(fèi)勁

          • 資源分配不均衡,有的 Slave 要運(yùn)行的 job 出現(xiàn)排隊(duì)等待,而有的 Slave 處于空閑狀態(tài)

          • 資源有浪費(fèi),每臺(tái) Slave 可能是物理機(jī)或者虛擬機(jī),當(dāng) Slave 處于空閑狀態(tài)時(shí),也不會(huì)完全釋放掉資源。

          正因?yàn)樯厦娴?Jenkins slave 存在這些種種痛點(diǎn),我們渴望一種更高效更可靠的方式來完成這個(gè) CI/CD 流程,而 Docker 虛擬化容器技術(shù)能很好的解決這個(gè)痛點(diǎn),又特別是在 Kubernetes 集群環(huán)境下面能夠更好來解決上面的問題,下圖是基于 Kubernetes 搭建 Jenkins slave 集群的簡(jiǎn)單示意圖:

          從圖上可以看到 Jenkins Master 時(shí)以 docker-compose 的方式運(yùn)行在一個(gè)節(jié)點(diǎn)上。Jenkins Slave 以 Pod 形式運(yùn)行在 Kubernetes 集群的 Node 上,并且它不是一直處于運(yùn)行狀態(tài),它會(huì)按照需求動(dòng)態(tài)的創(chuàng)建并自動(dòng)刪除。這種方式的工作流程大致為:當(dāng) Jenkins Master 接受到 Build 請(qǐng)求時(shí),會(huì)根據(jù)配置的 Label 動(dòng)態(tài)創(chuàng)建一個(gè)運(yùn)行在 Pod 中的 Jenkins Slave 并注冊(cè)到 Master 上,當(dāng)運(yùn)行完 Job 后,這個(gè) Slave 會(huì)被注銷并且這個(gè) Pod 也會(huì)自動(dòng)刪除,恢復(fù)到最初狀態(tài)。

          那么我們使用這種方式帶來了以下好處:

          • 動(dòng)態(tài)伸縮,合理使用資源,每次運(yùn)行 Job 時(shí),會(huì)自動(dòng)創(chuàng)建一個(gè) Jenkins Slave,Job 完成后,Slave 自動(dòng)注銷并刪除容器,資源自動(dòng)釋放,而且 Kubernetes 會(huì)根據(jù)每個(gè)資源的使用情況,動(dòng)態(tài)分配 Slave 到空閑的節(jié)點(diǎn)上創(chuàng)建,降低出現(xiàn)因某節(jié)點(diǎn)資源利用率高,還排隊(duì)等待在該節(jié)點(diǎn)的情況。

          • 擴(kuò)展性好,當(dāng) Kubernetes 集群的資源嚴(yán)重不足而導(dǎo)致 Job 排隊(duì)等待時(shí),可以很容易的添加一個(gè) Kubernetes Node 到集群中,從而實(shí)現(xiàn)擴(kuò)展。

          上面的大半段復(fù)制粘貼自 基于 Jenkins 的 CI/CD (一) ??

          kubernetes 集群


          關(guān)于 kubernetes 集群部署,使用 kubeadm 部署是最為方便的了,可參考我很早之前寫過的文章《使用 kubeadm 快速部署體驗(yàn) K8s》,在這里只是簡(jiǎn)單介紹一下:

          • 使用 kubeadm 來創(chuàng)建一個(gè)單 master 節(jié)點(diǎn)的 kubernets 集群


          1
          root@jenkins:~ # kubeadm init --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address=192.168.20.11


          • 集群成功部署完成之后會(huì)有如下提示:


          1
          2
          3
          4
          5
          Your Kubernetes control-plane has initialized successfully!
          To start using your cluster, you need to run the following as a regular user:
          mkdir -p $HOME/.kube
          sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
          sudo chown $(id -u):$(id -g) $HOME/.kube/config


          • 查看節(jié)點(diǎn)狀態(tài)和 pod 都已經(jīng)正常


          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          root@jenkins:~ # kubectl get pod -A
          NAMESPACE NAME READY STATUS RESTARTS AGE
          kube-system coredns-f9fd979d6-9t6qp 1/1 Running 0 89s
          kube-system coredns-f9fd979d6-hntm8 1/1 Running 0 89s
          kube-system etcd-jenkins 1/1 Running 0 106s
          kube-system kube-apiserver-jenkins 1/1 Running 0 106s
          kube-system kube-controller-manager-jenkins 1/1 Running 0 106s
          kube-system kube-proxy-8pzkz 1/1 Running 0 89s
          kube-system kube-scheduler-jenkins 1/1 Running 0 106s
          root@jenkins:~ # kubectl get node
          NAME STATUS ROLES AGE VERSION
          jenkins Ready master 119s v1.19.8


          • 去除 master 節(jié)點(diǎn)上的污點(diǎn),允許其他的 pod 調(diào)度在 master 節(jié)點(diǎn)上,不然后面 Jenkins 所創(chuàng)建的 pod 將無法調(diào)度在該節(jié)點(diǎn)上。


          1
          kubectl taint nodes $(hostname) node-role.kubernetes.io/master:NoSchedule-


          Jenkins master


          至于 Jenkins master 的部署方式,個(gè)人建議使用 docker-compose 來部署。運(yùn)行在 kubernetes 集群集群中也沒什么毛病,可以參考 基于 Jenkins 的 CI/CD (一) 這篇博客。但從個(gè)人運(yùn)維踩的坑來講,還是將 Jenkins master 獨(dú)立于 kubernetes 集群部署比較方便??。

          • docker-compose.yaml


          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          version: '3.6'
          services:
          jenkins:
          image: jenkins/jenkins:2.263.4-lts-slim
          container_name: jenkins
          restart: always
          volumes:
          - ./jenkins_home:/var/jenkins_home
          network_mode: host
          user: root
          environment:
          - JAVA_OPTS=-Duser.timezone=Asia/Shanghai


          • 使用 docker-compose up 來啟動(dòng),成功啟動(dòng)后會(huì)有如下提示,日志輸出的密鑰就是 admin 用戶的默認(rèn)密碼,使用它來第一次登錄 Jenkins。


          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          jenkins    | 2021-03-06 02:22:31.741+0000 [id=41]	INFO	jenkins.install.SetupWizard#init:
          jenkins |
          jenkins | *************************************************************
          jenkins | *************************************************************
          jenkins | *************************************************************
          jenkins |
          jenkins | Jenkins initial setup is required. An admin user has been created and a password generated.
          jenkins | Please use the following password to proceed to installation:
          jenkins |
          jenkins | 4c2361968cd94323acdde17f7603d8e1
          jenkins |
          jenkins | This may also be found at: /var/jenkins_home/secrets/initialAdminPassword
          jenkins |
          jenkins | *************************************************************
          jenkins | *************************************************************
          jenkins | *************************************************
          ************


          • 登錄上去之后,建議選擇 選擇插件來安裝,盡可能少地安裝插件,按需安裝即可。


          • 在 Jenkins 的插件管理那里安裝上 kubernetes 插件



          • 接下來開始配置 Jenkins 大叔如何與 kubernetes 船長(zhǎng)手牽手???????? :-)。配置 kubernets 的地方是在 系統(tǒng)管理 > 節(jié)點(diǎn)管理 > Configure Clouds。點(diǎn)擊 Add a new cloud,來添加一個(gè) kubernetes 集群。


          • 配置連接參數(shù)


          參數(shù)說明
          名稱kubernetes也是后面 pod 模板中的 cloud 的值
          憑據(jù)kubeconfig 憑據(jù) id使用 kubeconfig 文件來連接集群
          Kubernetes 地址默認(rèn)即可
          Use Jenkins Proxy默認(rèn)即可
          Kubernetes 服務(wù)證書 key默認(rèn)即可
          禁用 HTTPS 證書檢查默認(rèn)即可
          Kubernetes 命名空間默認(rèn)即可
          WebSocket默認(rèn)即可
          Direct Connection默認(rèn)即可
          Jenkins 地址http://jenkins.k8s.li:8080Jenkins pod 連接 Jenkins master 的 URL
          Jenkins 通道50000Jenkins JNLP 的端口,默認(rèn)為 50000
          Connection Timeout默認(rèn)即可Jenkins 連接 kubernetes 超時(shí)時(shí)間
          Read Timeout默認(rèn)即可
          容器數(shù)量默認(rèn)即可Jenkins pod 創(chuàng)建的最大數(shù)量
          Pod Labels默認(rèn)即可Jenkins pod 的 lables
          連接 Kubernetes API 的最大連接數(shù)默認(rèn)即可
          Seconds to wait for pod to be running默認(rèn)即可等待 pod 正常 running 的時(shí)間


          • 在 Jenkins 的憑據(jù)那里添加上 kubeconfig 文件,憑據(jù)的類型選擇為 Secret file,然后將上面使用 kubeadm 部署生成的 kubeconfig 上傳到這里。


          • 點(diǎn)擊連接測(cè)試,如果提示 Connected to Kubernetes v1.19.8 就說明已經(jīng)成功連接上了 kubernetes 集群。


          • 關(guān)于 pod 模板

          其實(shí)就是配置 Jenkins Slave 運(yùn)行的 Pod 模板,個(gè)人不太建議使用插件中的模板去配置,推薦將 pod 的模板放在 Jenkinsfile 中,因?yàn)檫@些配置與我們的流水線緊密相關(guān),把 pod 的配置存儲(chǔ)在 Jenkins 的插件里實(shí)在是不太方便;不方便后續(xù)的遷移備份之類的工作;后續(xù)插件升級(jí)后這些配置也可能會(huì)丟失。因此建議將 pod 模板的配置直接定義在 Jenkinsfile 中,靈活性更高一些,不會(huì)受 Jenkins 插件升級(jí)的影響。總之用代碼去管理這些 pod 配置維護(hù)成本將會(huì)少很多。

          Jenkinsfile


          • 流水線 Jenkinsfile,下面是一個(gè)簡(jiǎn)單的任務(wù),用于構(gòu)建 webp-server-go 項(xiàng)目的 docker 鏡像。


          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          // Kubernetes pod template to run.
          def JOB_NAME = "${env.JOB_NAME}"
          def BUILD_NUMBER = "${env.BUILD_NUMBER}"
          def POD_NAME = "jenkins-${JOB_NAME}-${BUILD_NUMBER}"
          podTemplate(
          # 這里定義 pod 模版
          )
          { node(POD_NAME) {
          container(JOB_NAME) {
          stage("Build image") {
          sh """#!/bin/bash
          git clone https://github.com/webp-sh/webp_server_go /build
          cd /build
          docker build -t webps:0.3.2-rc.1 .
          """
          }
          }
          }
          }


          • pod 模版如下,將模板的內(nèi)容復(fù)制粘貼到上面的 Jenkinsfile 中。在容器中構(gòu)建鏡像,我們使用 dind 的方案:將 pod 所在宿主機(jī)的 docker sock 文件掛載到 pod 的容器內(nèi),pod 容器內(nèi)只要安裝好 docker-cli 工具就可以像宿主機(jī)那樣直接使用 docker 了。


          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
          24
          25
          26
          27
          podTemplate(
          cloud: "kubernetes",
          namespace: "default",
          name: POD_NAME,
          label: POD_NAME,
          yaml: """
          apiVersion: v1
          kind: Pod
          spec:
          containers:
          - name: ${JOB_NAME}
          image: "debian:buster-docker"
          imagePullPolicy: IfNotPresent
          tty: true
          volumeMounts:
          - name: dockersock
          mountPath: /var/run/docker.sock
          - name: jnlp
          args: ["\$(JENKINS_SECRET)", "\$(JENKINS_NAME)"]
          image: "jenkins/inbound-agent:4.3-4-alpine"
          imagePullPolicy: IfNotPresent
          volumes:
          - name: dockersock
          hostPath:
          path: /var/run/docker.sock
          """,
          )


          • 構(gòu)建 debian:buster-docker 鏡像,使用它來在 pod 的容器內(nèi)構(gòu)建 docker 鏡像,使用的 Dockerfile 如下:


          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          FROM debian:buster
          RUN apt update \
          && apt install -y --no-install-recommends \
          vim \
          curl \
          git \
          make \
          ca-certificates \
          gnupg \
          && rm -rf /var/lib/apt/lists/*
          RUN curl -fsSL "https://download.docker.com/linux/debian/gpg" | apt-key add -qq - >/dev/null \
          && echo "deb [arch=amd64] https://download.docker.com/linux/debian buster stable" > /etc/apt/sources.list.d/docker.list \
          && apt update -qq \
          && apt-get install -y -qq --no-install-recommends docker-ce-cli \
          && rm -rf /var/lib/apt/lists/*


          定義好 jenkinsfile 文件并且構(gòu)建好 pod 模板中的鏡像后,接下來我們開始使用它來創(chuàng)建流水線任務(wù)。

          流水線


          • 在 Jenkins 上新建一個(gè)任務(wù),選擇任務(wù)的類型為 流水線



          • 將定義好的 Jenkinsfile 內(nèi)容復(fù)制粘貼到流水線定義 Pipeline script 中并點(diǎn)擊保存。在新建好的 Job 頁(yè)面點(diǎn)擊 立即構(gòu)建 來運(yùn)行流水線任務(wù)。


          • 在 kubernetes 集群的機(jī)器上使用 kubectl 命令查看 pod 是否正常 Running


          1
          2
          3
          root@jenkins:~ # kubectl get pod
          NAME READY STATUS RESTARTS AGE
          jenkins-webps-9-bs78x-5x204 2/2 Running 0 66s


          • Job 正常運(yùn)行并且狀態(tài)為綠色表明該 job 已經(jīng)成功執(zhí)行了。



          • 在 kubernetes 集群機(jī)器上查看 docker 鏡像是否構(gòu)建成功


          1
          2
          root@jenkins:~ # docker images | grep webps
          webps 0.3.2-rc.1 f68f496c0444 20 minutes ago 13.7MB


          踩坑


          • pod 無法正常 Running


          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
          24
          25
          Running in Durability level: MAX_SURVIVABILITY
          [Pipeline] Start of Pipeline
          [Pipeline] podTemplate
          [Pipeline] {
          [Pipeline] node
          Created Pod: kubernetes default/debian-35a11b49-087b-4a8c-abac-bd97d7eb5a1f-fkmzq-9wm0r
          [Normal][default/debian-35a11b49-087b-4a8c-abac-bd97d7eb5a1f-fkmzq-9wm0r][Scheduled] Successfully assigned default/debian-35a11b49-087b-4a8c-abac-bd97d7eb5a1f-fkmzq-9wm0r to jenkins
          [Normal][default/debian-35a11b49-087b-4a8c-abac-bd97d7eb5a1f-fkmzq-9wm0r][Pulling] Pulling image "debian:buster"
          [Normal][default/debian-35a11b49-087b-4a8c-abac-bd97d7eb5a1f-fkmzq-9wm0r][Pulled] Successfully pulled image "debian:buster" in 2.210576896s
          [Normal][default/debian-35a11b49-087b-4a8c-abac-bd97d7eb5a1f-fkmzq-9wm0r][Created] Created container debian
          [Normal][default/debian-35a11b49-087b-4a8c-abac-bd97d7eb5a1f-fkmzq-9wm0r][Started] Started container debian
          [Normal][default/debian-35a11b49-087b-4a8c-abac-bd97d7eb5a1f-fkmzq-9wm0r][Pulling] Pulling image "jenkins/inbound-agent:4.3-4-alpine"
          Still waiting to schedule task
          ‘debian-35a11b49-087b-4a8c-abac-bd97d7eb5a1f-fkmzq-9wm0r’ is offline
          [Normal][default/debian-35a11b49-087b-4a8c-abac-bd97d7eb5a1f-fkmzq-9wm0r][Pulled] Successfully pulled image "jenkins/inbound-agent:4.3-4-alpine" in 3.168311973s
          [Normal][default/debian-35a11b49-087b-4a8c-abac-bd97d7eb5a1f-fkmzq-9wm0r][Created] Created container jnlp
          [Normal][default/debian-35a11b49-087b-4a8c-abac-bd97d7eb5a1f-fkmzq-9wm0r][Started] Started container jnlp
          Created Pod: kubernetes default/debian-35a11b49-087b-4a8c-abac-bd97d7eb5a1f-fkmzq-qdw4m
          [Normal][default/debian-35a11b49-087b-4a8c-abac-bd97d7eb5a1f-fkmzq-qdw4m][Scheduled] Successfully assigned default/debian-35a11b49-087b-4a8c-abac-bd97d7eb5a1f-fkmzq-qdw4m to jenkins
          [Normal][default/debian-35a11b49-087b-4a8c-abac-bd97d7eb5a1f-fkmzq-qdw4m][Pulled] Container image "debian:buster" already present on machine
          [Normal][default/debian-35a11b49-087b-4a8c-abac-bd97d7eb5a1f-fkmzq-qdw4m][Created] Created container debian
          [Normal][default/debian-35a11b49-087b-4a8c-abac-bd97d7eb5a1f-fkmzq-qdw4m][Started] Started container debian
          [Normal][default/debian-35a11b49-087b-4a8c-abac-bd97d7eb5a1f-fkmzq-qdw4m][Pulled] Container image "jenkins/inbound-agent:4.3-4-alpine" already present on machine
          [Normal][default/debian-35a11b49-087b-4a8c-abac-bd97d7eb5a1f-fkmzq-qdw4m][Created] Created container jnlp
          [Normal][default/debian-35a11b49-087b-4a8c-abac-bd97d7eb5a1f-fkm
          zq-qdw4m][Started] Started container jnlp


          這是因?yàn)?Jenkins pod 中的 jnlp 容器無法連接 Jenkins master。可以檢查一下 Jenkins master 上 系統(tǒng)管理 > 節(jié)點(diǎn)管理 > Configure Clouds 中 Jenkins 地址 和 Jenkins 通道 這兩個(gè)參數(shù)是否配置正確。

          結(jié)束


          到此為止,我們就完成了讓 Jenkins 大叔與 kubernetes 船長(zhǎng)手牽手????????啦!上面使用了一個(gè)簡(jiǎn)單的例子來展示了如何將 Jenkins 的 Job 任務(wù)運(yùn)行在 kubernetes 集群上,但在實(shí)際工作中遇到的情形可能比這要復(fù)雜一些,流水線需要配置的參數(shù)也要多一些。

          - END -

           推薦閱讀 

          Kubernetes 企業(yè)容器云平臺(tái)運(yùn)維實(shí)戰(zhàn) 
          快、狠、準(zhǔn)!系統(tǒng)有效的排查運(yùn)維類故障
          OpenStack 與 Kubernetes 的共存
          Nginx 常用配置清單
          最強(qiáng)整理!常用正則表達(dá)式速查手冊(cè)
          運(yùn)維的工作邊界,這次真的搞明白了!
          七年老運(yùn)維實(shí)戰(zhàn)中的 Shell 開發(fā)經(jīng)驗(yàn)總結(jié)
          面試數(shù)十家Linux運(yùn)維工程師,總結(jié)了這些面試題(含答案)
          快速入門 Ansible 自動(dòng)化運(yùn)維工具 | 16張圖
          12年資深運(yùn)維老司機(jī)的成長(zhǎng)感悟



          點(diǎn)亮,服務(wù)器三年不宕機(jī)

          瀏覽 92
          點(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>
                  国产久久在线 | 国产无遮挡又黄又爽又色视频软件 | 亚洲视频在线视频播放 | 亚洲最大视频在线观看 | 日本一级 黄 色 片图片视频 |