利用 Kubernetes 內建 PodTemplate 管理 Jenkins 構建節點

語言: CN / TW / HK

作者:Rick

Jenkins 可以很好地與 Kubernetes 整合,不管是控制器(controller)還是構建節點(agent),都能以 Pod 的形式執行在 Kubernetes 上。 熟悉 Jenkins 的使用者,都知道 Jenkins 支援多種型別的構建節點,例如:固定配置、動態配置。而節點與控制器連線的方式, 又包括:JNLP、SSH 等。對於已經在全面擁抱容器技術的使用者,大多數是通過連線 Kubernetes 叢集並動態啟動、銷燬 Pod 的方式來使用構建節點。 而隨著構建節點的種類、數量增多後,如何更有效地維護這些基於 Kubernetes 的節點,則逐漸成為一個問題。而在這篇文章中, 我將會介紹一種基於配置即程式碼的方案來管理、維護構建節點。

配置即程式碼(Configuration as Code,簡稱為:CasC),是一個非常讚的思路,它使得 Jenkins 使用者不需要再一次次地開啟 UI 介面去修改系統配置。 通過 UI 修改配置的優點是:藉助頁面上配置項的描述資訊,可以相對容易地理解其含義。但相對應的缺點也是非常明顯的:難以複用, 即便是完全相同的配置,也需要手動地在其他環境上再次操作;無法追蹤修改過程;發生錯誤時無法快速回滾。藉助 CasC 的能力, 我們可以把 Jenkins 的系統配置儲存到一個 Git 程式碼倉庫中,以及 GitOps 工具(例如:Argo CD),最終使得修改 Jenkins 系統配置, 成為一件可控、便捷的工作

不過,當 Jenkins 的變得配置複雜以後,對應的 YAML 配置檔案也可能會變得越來越大,難以維護。

迴歸到我們希望解決的核心問題上來,預期的方案是:只需要單獨維護 PodTemplate 即可實現對 Jenkins 構建節點的維護。為了解決該問題, 我們需要搞定 Jenkins 配置中的 PodTemplate 與 Kubernetes 中內建 PodTemplate 不一致的問題;以及如何動態載入 Jenkins 配置的問題。

為了解決上述的幾個問題點,只需要部署一個 Deployment 即可。這個元件負責監聽 Kubernetes 內建的 PodTemplate, 把其載入到 Jenkins 的系統配置(CasC YAML 檔案)中,再呼叫 Jenkins API 重新載入配置。為了充分地利用到 Kubernetes 的優勢, 我們把 CasC 配置儲存為 ConfigMap,並以卷(Volume)的形式掛載到 Jenkins 中。

以下是實驗步驟(本文提供的是核心思路和關鍵步驟,每個具體的檔案都可以在文末提供的程式碼倉庫地址中找到):

準備一個 Kubernetes 叢集,確保有足夠的訪問許可權,確保不會影響到叢集已有業務。推薦使用諸如:MiniKube、Kind、K3s 等便於開發、測試的輕型叢集。

首先,把 Jenkins 的系統配置以 CasC YAML 格式存放到 ConfigMap 中,例如:

yaml apiVersion: v1 data: jenkins_user.yaml: | jenkins: mode: EXCLUSIVE numExecutors: 0 scmCheckoutRetryCount: 2 disableRememberMe: true clouds: - kubernetes: name: "kubernetes" serverUrl: "https://kubernetes.default" skipTlsVerify: true kind: ConfigMap metadata: name: jenkins-casc-config namespace: kubesphere-devops-system

然後,把上面的 ConfigMap 掛載到 Jenkins 工作負載中。需要注意的是, 實驗中使用的 Jenkins 必須安裝的外掛有:kubernetes kubernetes-credentials-provider configuration-as-code。參考如下:

yaml spec: template: spec: containers: - image: ghcr.io/linuxsuren/jenkins:lts env: - name: CASC_JENKINS_CONFIG value: "/var/jenkins_home/casc_configs/" # loading config file from a directory that was mount from a ConfigMap volumeMounts: - mountPath: /var/jenkins_home/casc_configs name: casc-config # mount from a volume volumes: - configMap: defaultMode: 420 name: jenkins-casc-config # clamin a ConfigMap volume, all the CasC YAML content will be here name: casc-config

接下來,便是核心的 Kubernetes 控制器了。請參考如下配置建立對應的 Deployment:

yaml apiVersion: apps/v1 kind: Deployment metadata: name: jenkins-agent namespace: kubesphere-devops-system spec: template: spec: containers: - image: kubespheredev/devops-controller:dev-v3.2.1-rc.3-6726130 name: controller args: - --enabled-controllers - all=false,jenkinsagent=true,jenkinsconfig=true # only enable the necessary features of this controller

該控制器會監聽所有帶有標籤 jenkins.agent.pod 的 PodTemplate 資源,並把它轉化為 Jenkins 風格的 PodTemplate 後加載到系統配置中。 通常情況下,這可能會有 3~5 秒的延遲。

當你完成以上所有步驟,確保相關元件都正確啟動後,就可以嘗試新增一個 Kubernetes 內建的 PodTemplate了。然後,你可以建立一個流水線來測試對應的節點。

參考資料