devops-4:Jenkins基於k8s cloud和docker cloud動態增減節點

2022-08-04 21:01:46

Jenkins管理動態節點

上文介紹Jenkins增加靜態agent的步驟,除了靜態增加外,還有動態管理的功能,兩者最大的差異在於動態可以在有job執行時,臨時加入一個agent到jenkins master,然後等job執行完畢之後,所加入的agent再自動刪除掉,達到一個動態的增刪節點效果,使所有的job都在遠端的某個叢集中執行。

目前執行動態擴縮節點的方式有docker cloud和k8s cloud。

docker cloud設定

  1. 首先需要安裝docker外掛,系統管理—>外掛管理—>可選外掛—>搜尋docker,主要的有Docker 、docker pipeline外掛,其他外掛可以酌情下載。

  2. 設定docker守護行程,使其可以通過主機ip+埠的形式存取:

    vi /etc/systemd/system/docker.service

    ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://0.0.0.0:8376
    

    新增此設定後,重新啟動docker,主機便會暴露8376埠,供使用者端存取,需要注意安全問題,可以通過防火牆等安全裝置對埠進行限制,也可以為此埠指定證書,必須有此埠證書和私鑰才可以存取成功。

  3. 在Jenkins端設定docker cloud,系統管理—>節點管理—>Configure Clouds—>Add a new cloud—>Docker

  4. 設定Docker Cloud details,主要是設定地址+埠,如果有證書則也設定上證書。

    設定完成後,點選後邊的Test Connection,顯示出docker version 和 Api version後,表示連線成功。

  5. 設定Docker Agent templates,要修改的主要設定為以下幾點:

    • Labels:agent的label,用於指定匹配該cloud
    • Name:用於加入Jenkins slave的名字字首
    • Docker Image:用於建立臨時節點的映象,相當於有job要執行時,會docker run此映象,然後以slave節點的方式加入到Jenkins Master,並將job在此slave節點執行,執行完畢後,會直接docker rm掉
    • Remote File System Root:臨時節點的家目錄
    • Connect method:節點的加入方式,一般選用Attach Docker container即可,jenkins master會直接將slave所需的程式碼複製到此節點中,並用容器內的java啟動,所以使用此方式要滿足兩條硬條件:必須有java環境和container的CMD必須是/bin/bash或者為空

    其他一些不是特別重要的引數,例如:Pull timeout拉取超時時間、Pull strategy拉取策略等可以進行相應的調整。

測試使用docker cloud執行一個Pipeline

以上步驟全部完成之後,docker cloud就可以正常使用,下邊建立一個測試流水線:

pipeline {
    agent {
        label 'java-maven-app'
    }
    options {
        buildDiscarder(logRotator(numToKeepStr: '10')) 
    }
    tools {
        maven 'apache-maven-3.8.6' 
    }
    stages {
        stage('mvn version') {
            steps {
                sh 'mvn -v'
            }
        }
        stage('java version') {
            steps {
                sh 'java -version'
            }
            post {
                always {
                    sh 'echo "test complete"'
                }
            }
        }
    }
}

開始執行流水線:

可見此流水線在名稱為 java-maven-app-001ocj3t66f69 的節點中執行,再去檢視節點列表,發現多了一個叫這個名字的節點:

再檢視docker容器,發現剛剛執行了一個jenkins/agent的容器:

Pipeline執行完畢後,容器被摧毀,節點也被剔除,實現了動態的docker cloud管理。

Kubernetes Cloud設定

  1. 系統管理->外掛管理->可選外掛,搜尋kubernetes直接安裝

  2. k8s外掛安裝完畢後,開始新增雲節點:系統管理—>節點管理—>Configure Clouds—>Add a new cloud—>Kubernetes

  3. 設定Kubernetes Cloud details,主要設定名稱、k8s apiserver地址、jenkins地址、k8s服務證書以及加密成.pfx型別的證書key:

    apiserver地址和jenkins地址不用強調,都知道怎麼填,重點需要強調兩個證書:

    • Kubernetes 服務證書 key:這個實際就是你k8s叢集的ca.crt證書,一般在/etc/kubernetes/pki/ca.crt,直接copy過來即可
    • 第二個主要是因為k8s apiserver是https的通訊方式,所以要將其叢集證書的公私鑰打包成.pfx型別,然後提供給jenkins來存取

    這裡需要手動生成第二個.pfx型別的證書

    (1)首先需要安裝證書生成工具:

    # curl -s -L -o /usr/local/bin/cfssl https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 
    # curl -s -L -o /usr/local/bin/cfssljson https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 
    # curl -s -L -o /usr/local/bin/cfssl-certinfo https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 
    
    # chmod +x /usr/local/bin/cfssl*
    

    (2)然後準備證書籤名請求

    vi jenkins-csr.json

    {
      "CN": "admin",
      "hosts": [],
      "key": {
        "algo": "rsa",
        "size": 2048
      },
      "names": [
        {
          "C": "CN",
          "ST": "BeiJing",
          "L": "XS",
          "O": "system:masters",
          "OU": "System"
        }
      ]
    }
    

    證書請求中的O 指定該證書的 Group 為 system:masters,而 RBAC 預定義的 ClusterRoleBinding 將 Group system:masters 與 ClusterRole cluster-admin 繫結,這就賦予了該證書具有所有叢集許可權 。

    (3)建立admin證書和私鑰

    # cfssl gencert -ca=/etc/kubernetes/pki/ca.crt -ca-key=/etc/kubernetes/pki/ca.key --profile=kubernetes jenkins-csr.json | cfssljson -bare admin
    
    # ls
    admin-key.pem  admin.pem  jenkins-csr.json
    

    生成證書與key

    (4)生成.pfx型別證書

    # openssl pkcs12 -export -out ./jenkins-admin.pfx -inkey ./admin-key.pem -in ./admin.pem -passout pass:jenkins
    # ls
    jenkins-admin.pfx 
    

    指定admin的公鑰私鑰生成jenkins-admin.pfx,並設定密碼為jenkins

    (5)將證書新增至jenkins憑證中

    (6)最終再應用到k8s cloud中

    測試連線出現版本號即連線成功

  4. 設定Pod Templates

    主要設定標籤和用法以及pod的出事YAML,其他像volume、network或secret等都可以再yaml中提前編寫

    有kubernetes-agent標籤的job會匹配到此agent

    定義的一個基礎YAML模板,可以在裡邊定義更多的設定

    再就是要定義一下workspace採取什麼形式,分別有這幾種:

    根據自己需求,需不需要持久化來決定使用哪種方式

  5. 至此基本設定已經完成,還有一點需要注意,當有job要執行時,生成的pod中會有自己定義的一個容器和jenkins用於提供agent連線的容器,共兩個,預設情況jenkins agent生成的容器會拉取jenkins/inbound-agent:4.11-1-jdk11這個映象,可以提前下載下來,或者重新指定一個映象:

編輯流水線測試使用Kubernetes cloud

新建任務—>pipeline—>拉到最下邊選擇Pipeline script form SCM—>SCM選擇Git—>填寫專案的URL及認證

—>指定分支—>指定指令碼的路徑

這個就表示會直接從你指定的程式碼倉庫中去拉取程式碼,並根據倉庫中指定的Jenkinsfile進行構建,程式碼倉庫結構如下:

指定的Jenkinsfile檔案內容如下:

pipeline {
    agent {
      kubernetes {
        cloud 'kubernetes-internal' //指定k8s cloud的名稱
        label 'kubernetes-agent' //指定label
        defaultContainer 'example.com:5000/jenkins/agent:latest'  //可以指定執行的映象,不指定會預設使用設定k8s cloud時的預設映象
        inheritFrom 'jenkins-agent' //指定所用的podTemplate,其實是多餘的,因為就算不指定,也會用設定k8s cloud時,設定的pod Template
        namespace 'default'
      }
    tools {
        maven 'apache-maven-3.8.6' 
    }
    options {
        buildDiscarder(logRotator(numToKeepStr: '10')) 
    }
    stages {
        stage('Build') {
            steps {
                sh 'mvn -B -DskipTests clean package'
            }
        }
        stage('Test') {
            steps {
                sh 'mvn test'
            }
            post {
                always {
                    junit 'target/surefire-reports/*.xml'
                }
            }
        }
        stage('Deliver') {
            steps {
                sh './jenkins/scripts/deliver.sh'
            }
        }
    }
}

執行結果:

以k8s pod為agent的臨時節點已經加入:

k8s中pod也已經啟動,Pipeline執行結束後,自動摧毀。