<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 大叔與 kubernetes 船長手牽手 ????????

          共 20328字,需瀏覽 41分鐘

           ·

          2021-03-11 21:24


          背景

          雖然云原生時(shí)代有了 JenkinsX[1]、Drone[2]、Tekton[3] 這樣的后起之秀,但 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 (一)[4] ??

          kubernetes 集群

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

          • 使用 kubeadm 來創(chuàng)建一個(gè)單 master 節(jié)點(diǎn)的 kubernets 集群
          root@jenkins:~ # kubeadm init --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address=192.168.20.11
          • 集群成功部署完成之后會(huì)有如下提示:
          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)正常
          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)上。
          kubectl taint nodes $(hostname) node-role.kubernetes.io/master:NoSchedule-

          Jenkins master

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

          • docker-compose.yaml
          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。
          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 船長手牽手 ???????? :-)。配置 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:8080 Jenkins pod 連接 Jenkins master 的 URL
          Jenkins 通道 50000 Jenkins 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í)的影響??傊么a去管理這些 pod 配置維護(hù)成本將會(huì)少很多。

          Jenkinsfile

          • 流水線 Jenkinsfile,下面是一個(gè)簡(jiǎn)單的任務(wù),用于構(gòu)建 webp-server-go[7] 項(xiàng)目的 docker 鏡像。
          // 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 了。
          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 如下:
          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 頁面點(diǎn)擊 立即構(gòu)建 來運(yùn)行流水線任務(wù)。
          • 在 kubernetes 集群的機(jī)器上使用 kubectl 命令查看 pod 是否正常 Running
          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)建成功
          root@jenkins:~ # docker images | grep webps
          webps                                0.3.2-rc.1          f68f496c0444        20 minutes ago      13.7MB

          踩坑

          • pod 無法正常 Running
          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-fkmzq-qdw4m][Started] Started container jnlp

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

          結(jié)束

          到此為止,我們就完成了讓 Jenkins 大叔與 kubernetes 船長手牽手 ???????? 啦!上面使用了一個(gè)簡(jiǎn)單的例子來展示了如何將 Jenkins 的 Job 任務(wù)運(yùn)行在 kubernetes 集群上,但在實(shí)際工作中遇到的情形可能比這要復(fù)雜一些,流水線需要配置的參數(shù)也要多一些。那么我將會(huì)在下一篇博客中再講一下高級(jí)的用法:使用 Jenkins 完成 kubespray 離線安裝包打包。

          參考

          • 使用 Kubernetes 和 Jenkins 創(chuàng)建一個(gè) CI/CD 流水線[8]
          • 基于 Jenkins 的 CI/CD (一)[9]
          • PingCAP 面試:Jenkins 和 Kubernetes[10]
          • 基于 Kubernetes 的 Jenkins 服務(wù)也可以去 Docker 了[11]
          • Jenkins Pipeline 使用及調(diào)試[12]
          • 在 Kubernetes 上動(dòng)態(tài)創(chuàng)建 Jenkins Slave[13]
          • Jenkins X 不是 Jenkins ,而是一個(gè)技術(shù)棧[14]
          • Jenkins CI/CD (一) 基于角色的授權(quán)策略[15]

          參考資料

          [1]

          JenkinsX: https://jenkins-x.io/

          [2]

          Drone: https://www.drone.io/

          [3]

          Tekton: https://tekton.dev

          [4]

          基于 Jenkins 的 CI/CD (一): https://www.qikqiak.com/k8s-book/docs/36.Jenkins%20Slave.html

          [5]

          使用 kubeadm 快速部署體驗(yàn) K8s: https://blog.k8s.li/kubeadm-deploy-k8s-v1.17.4.html

          [6]

          基于 Jenkins 的 CI/CD (一): https://www.qikqiak.com/k8s-book/docs/36.Jenkins%20Slave.html

          [7]

          webp-server-go: https://github.com/webp-sh/webp_server_go

          [8]

          使用 Kubernetes 和 Jenkins 創(chuàng)建一個(gè) CI/CD 流水線: https://jenkins-zh.cn/wechat/articles/2020/03/2020-03-10-create-a-ci-cd-pipeline-with-kubernetes-and-jenkins/

          [9]

          基于 Jenkins 的 CI/CD (一): https://www.qikqiak.com/k8s-book/docs/36.Jenkins%20Slave.html

          [10]

          PingCAP 面試:Jenkins 和 Kubernetes: https://a-wing.top/kubernetes/2021/01/27/jenkins_and_kubernetes.html

          [11]

          基于 Kubernetes 的 Jenkins 服務(wù)也可以去 Docker 了: https://www.chenshaowen.com/blog/using-podman-to-build-images-under-kubernetes-and-jenkins.html

          [12]

          Jenkins Pipeline 使用及調(diào)試: https://www.chenshaowen.com/blog/jenkins-pipeline-usging-and-debug.html

          [13]

          在 Kubernetes 上動(dòng)態(tài)創(chuàng)建 Jenkins Slave: https://www.chenshaowen.com/blog/creating-jenkins-slave-dynamically-on-kubernetes.html

          [14]

          Jenkins X 不是 Jenkins ,而是一個(gè)技術(shù)棧: https://www.chenshaowen.com/blog/jenkins-x-is-not-jenkins-but-stack.html

          [15]

          Jenkins CI/CD (一) 基于角色的授權(quán)策略: https://atbug.com/using-role-based-authorization-strategy-in-jenkins/


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



          你可能還喜歡

          點(diǎn)擊下方圖片即可閱讀

          eBPF 的發(fā)展歷史和核心設(shè)計(jì)

          云原生是一種信仰 ??


          關(guān)注公眾號(hào)

          后臺(tái)回復(fù)?k8s?獲取史上最方便快捷的 Kubernetes 高可用部署工具,只需一條命令,連 ssh 都不需要!



          點(diǎn)擊 "閱讀原文" 獲取更好的閱讀體驗(yàn)!


          發(fā)現(xiàn)朋友圈變“安靜”了嗎?

          瀏覽 46
          點(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>
                  大香蕉丁香综合网 | 青娱乐超碰在线 | 久久四虎影院 | 好男人一区二区三区在线观看 | 色婷婷五月网 |