1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

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

        共 11187字,需瀏覽 23分鐘

         ·

        2021-08-06 02:27

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

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

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

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

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

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

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

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

        • 動態(tài)伸縮,合理使用資源,每次運(yùn)行 Job 時(shí),會自動創(chuàng)建一個(gè) Jenkins Slave,Job 完成后,Slave 自動注銷并刪除容器,資源自動釋放,而且 Kubernetes 會根據(jù)每個(gè)資源的使用情況,動態(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》,在這里只是簡單介紹一下:

        • 使用 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


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


        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 來啟動,成功啟動后會有如下提示,日志輸出的密鑰就是 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 船長手牽手???????? :-)。配置 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)擊連接測試,如果提示 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 的配置存儲在 Jenkins 的插件里實(shí)在是不太方便;不方便后續(xù)的遷移備份之類的工作;后續(xù)插件升級后這些配置也可能會丟失。因此建議將 pod 模板的配置直接定義在 Jenkinsfile 中,靈活性更高一些,不會受 Jenkins 插件升級的影響??傊么a去管理這些 pod 配置維護(hù)成本將會少很多。

        Jenkinsfile


        • 流水線 Jenkinsfile,下面是一個(gè)簡單的任務(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 頁面點(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??梢詸z查一下 Jenkins master 上 系統(tǒng)管理 > 節(jié)點(diǎn)管理 > Configure Clouds 中 Jenkins 地址 和 Jenkins 通道 這兩個(gè)參數(shù)是否配置正確。

        結(jié)束


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

        - END -

         推薦閱讀 

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



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

        瀏覽 92
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

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

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            在线观看激情无码成人 | 男女裸体性婬乱视频免费看 | 啪一啪| 久久久久成人精品无码 | 卖婬老太HD视频 | 国产毛片电影 | 一二三四不卡日韩视频 | 欧美第六页| 色999综合 | av在线观看中文字幕日韩精品 |