Jenkins:乘著 Kubernetes 的翅膀_Kubernetes中文社群
前言
Kubernetes + Docker 是一對有意思的組合,為微服務架構的落地,掃清了最後一公里的障礙,在符合企業 IT 治理需求的前提之下,為傳統企業應用的平滑過渡提供了有效條件和方法。
作為軟體生產環節中重要組成部分的持續構建和釋出過程,自然也要隨勢而動,這方面的老將 Jenkins 不但提供了用於構建、推送 Docker 映象的外掛,更提供了利用 Kubernetes 執行構建叢集的能力。本文將利用一個簡單的 Hello world 專案,來展示 Jenkins 的這一特性。
準備工作
Kubernetes 叢集安裝
要在 Kubernetes 叢集完成下面所有的工作,因此首先進行叢集的安裝和配置,這方面可以參考
叢集安裝後,應該具有以下能力:
- 叢集具有受 DNS 支援的服務定址能力;
- 能夠利用 Kubectl 或者其他方法釋出容器應用的能力;
- 私有映象庫,或者到 Docker Hub 的網路連線;
- Pause 映象也自然是 Kubernetes 中執行應用的必須條件。
Jenkins 映象
本文例子採用自制的一個整合映象為基礎工具,該映象集成了眾多常用的 CI/CD 工具,另外同時還包含了 Jenkins 的 Master 和 Slave 兩種模式,映象託管在 Docker Hub,原始碼可在 Github 瀏覽和下載。
如果具有直接連線 Docker Hub 的網路連線,則可無需理會;否則就需要下載映象,並上傳至私庫。為行文方便,這裡假設採用私庫方式,映象地址為 10.211.55.5:5000/jenkins:2.7.4.5
共享儲存
因容器在叢集中的執行狀況未知,一般來說是需要為容器化應用提供共享儲存服務的,本文中採用最簡單的 NFS 方式,當然也可以使用官方支援的其他方式,例如 GlusterFS、Flocker 以及 Ceph 等等,具體支援能力可以參看官方說明,當然,如果只是學習測試,使用預設的 Empty 格式亦可,或者偷懶使用 HostPath 方式結合限定 Node 執行的方式也能夠完成任務。
Jenkins Master
YAML
首先要為我們的 Jenkins 映象編寫一個 Yaml ,用於提交到叢集中執行:
kind: ReplicationController apiVersion: v1 metadata: name: jenkins labels: name: jenkins spec: replicas: 1 selector: name: jenkins template: metadata: labels: name: jenkins spec: containers: - name: jenkins image: 10.211.55.5:5000/jenkins:2.7.4.5 ports: - containerPort: 8080 protocol: TCP - containerPort: 8081 protocol: TCP volumeMounts: - name: jenkins mountPath: /data/jenkins volumes: - name: jenkins nfs: server: 10.211.55.5 path: /var/data/nfs/ci/jenkins readOnly: false --- kind: Service apiVersion: v1 metadata: name: jenkins labels: name: jenkins spec: type: NodePort ports: - protocol: TCP nodePort: 32502 targetPort: 8080 port: 8080 name: web - protocol: TCP targetPort: 8081 port: 8081 name: service selector: name: jenkins
上面的 YML 檔案有幾點需要注意
- 掛載:Jenkins 的所有外掛、配置和工作檔案都處於環境變數 JENKINS_HOME 所示的路徑中,因此我們這裡利用 NFS 把位於 10.211.55.5 上的 /var/data/nfs/ci/jenkins 目錄對映到容器的/data/jenkins 之中,讓 Jenkins 獲得持久化儲存。
- 埠:Jenkins 預設執行需要 8080 埠對外提供 Web 介面。這裡我們另外聲明瞭一個 8081 埠,為叢集內新建的 Slave 提供通訊能力,可以看到,下面的 Service 定義中,僅僅使用 NodePort 方式暴露了一個 Web 埠
- 時區:映象提供了 TIMEZONE 環境變數,這一變數將會在執行時影響容器作業系統以及 Jenkins 的 JVM 的時區設定。這一變數預設使用 Asia/Shanghai。
- JENKINS_MODE:用於指示 Jenkins 的執行模式,可選值為 MASTER 或者 SLAVE,預設執行在MASTER 模式下。
執行和配置
接下來就可以使用 kubectl create -f jenkins.yaml 來執行映象了。執行之後可以刷 kubectl get pods 來檢視啟動情況。
這一 RC 的啟動需要載入 NFS 卷,因此如果啟動時間過長,可以使用 kubectl get events 命令檢視是否加載出了問題。
Pod 變為 Running 狀態之後,就可以嘗試採用上面 YAML 中定義的 Node Port 來訪問 Jenkins 介面了,經過一段時間的 “Jenkins正在啟動,請稍後…..”,系統要求輸入/data/jenkins/secrets/initialAdminPassword 檔案中儲存的初始密碼,假設前面 get pods 命令得到的 Pod 名稱是 jenkins-7nmka,這裡就可以使用 kubectl exec jenkins-7nmka cat /data/jenkins/secrets/initialAdminPassword 來檢視,獲取結果後即可複製黏貼到錄入框中繼續安裝。
接下來的外掛安裝,為節省時間直接 Select None。接下來設定管理員使用者名稱密碼,儲存後,安裝結束。
安裝和配置 Kubernetes 外掛
安裝
接下來就是進入 pluginManager/available 頁面安裝外掛。
如果網路需要代理,可以進入網址 /pluginManager/advanced,設定代理伺服器。 如果可選外掛頁面為空,可以在 /pluginManager/advanced 頁面裡面點選 “立即獲取” 按鈕進行重新整理。
過濾框中輸入 “kubernetes” 會看到列表中的 “Kubernetes plugin”,選擇安裝。
配置 Jenkins
安裝成功後,進入配置頁面(/configure)。
首先為了測試方便,我們把 “執行者數量” 設定為 0,也就是說只使用 Jenkins Slave 進行構建。
配置 Kubernetes
可以看到,頁面下方有一個按鈕 “新增一個雲”,點選後出現 Kubernetes 配置專案。
這裡我們用無認證的 http 方式進行連線,Kubernetes URL 中填入 API Server 的 http 地址,例如:http://10.211.55.5:8080。
Jenkins URL 中,這裡要注意我們不應該使用瀏覽器位址列中的 Node 地址,而是應該使用叢集內部的服務地址,根據上文中 Service 的定義,這裡使用 http://jenkins:8080。
最後是 ”Add Pod Template“ 按鈕,來定義 Slave 的 Pod 模板:
- 這裡的 “Docker Image” 專案跟上面使用的是同一個地址,也就是10.211.55.5:5000/jenkins:2.7.4.5;
- 根據前文說道的環境變數,這裡我們新增一個環境變數:JENKINS_MODE=SLAVE,
- “Jenkins slave root directory” 這一項填寫 /data/jenkins,
- “Command to run slave agent ” 這裡填寫映象中的啟動命令 /usr/local/bin/run.sh
填寫完成後,儲存。
配置埠
最後需要到安全配置頁面(/configureSecurity),TCP port for JNLP agents 一項填寫固定埠 8081。
Hello world
建立
新建一個 Free Style 專案。構建步驟中新增 “Execute shell script” 環節,並儲存,內容為
echo "Hello World"
構建
點選該任務的 “立即構建” 按鈕,即可觸發構建動作。
因為前面我們設定 Master 不執行構建工作,所以在構建啟動之後,會在構建執行狀態中看到有節點被動態新建,來執行我們的構建過程。這一過程中如果使用 kubectl get events 或者 kubectl get pods 命令,能看到 Jenkins Slave Pod 的建立、執行和銷燬過程。
尾聲
上面只是一個最為基礎的構建過程,甚至都無法稱為是一個完整過程,Kubernetes 外掛還提供了很多其他選項,結合自定義的 Slave 映象,能夠完成更多更復雜的任務,用於配合實際的生產過程。