動態jenkins slave

1、Jenkins CI/CD 背景介紹

持續構建與發佈是我們日常工作中必不可少的一個步驟,目前大多公司都採用 Jenkins 集羣來搭建符合需求的 CI/CD 流程,然而傳統的 Jenkins Slave 一主多從方式會存在一些痛點,比如:主 Master 發生單點故障時,整個流程都不可用了;每個 Slave 的配置環境不一樣,來完成不同語言的編譯打包等操作,但是這些差異化的配置導致管理起來非常不方便,維護起來也是比較費勁;資源分配不均衡,有的 Slave 要運行的 job 出現排隊等待,而有的 Slave 處於空閒狀態;最後資源有浪費,每臺 Slave 可能是實體機或者 VM,當 Slave 處於空閒狀態時,也不會完全釋放掉資源。

 

由於以上種種痛點,我們渴望一種更高效更可靠的方式來完成這個 CI/CD 流程,而 Docker 虛擬化容器技術能很好的解決這個痛點,下圖是基於 Kubernetes 搭建 Jenkins 集羣的簡單示意圖。

 

從圖上可以看到 Jenkins Master 和 Jenkins Slave 以 Docker Container 形式運行在 Kubernetes 集羣的 Node 上,Master 運行在其中一個節點,並且將其配置數據存儲到一個 Volume 上去,Slave 運行在各個節點上,並且它不是一直處於運行狀態,它會按照需求動態的創建並自動刪除。

 

這種方式的工作流程大致爲:當 Jenkins Master 接受到 Build 請求時,會根據配置的 Label 動態創建一個運行在 Docker Container 中的 Jenkins Slave 並註冊到 Master 上,當運行完 Job 後,這個 Slave 會被註銷並且 Docker Container 也會自動刪除,恢復到最初狀態。

 

這種方式帶來的好處有很多:

 

服務高可用,當 Jenkins Master 出現故障時,Kubernetes 會自動創建一個新的 Jenkins Master 容器,並且將 Volume 分配給新創建的容器,保證數據不丟失,從而達到集羣服務高可用。

動態伸縮,合理使用資源,每次運行 Job 時,會自動創建一個 Jenkins Slave,Job 完成後,Slave 自動註銷並刪除容器,資源自動釋放,而且 Kubernetes 會根據每個資源的使用情況,動態分配 Slave 到空閒的節點上創建,降低出現因某節點資源利用率高,還排隊等待在該節點的情況。

擴展性好,當 Kubernetes 集羣的資源嚴重不足而導致 Job 排隊等待時,可以很容易的添加一個 Kubernetes Node 到集羣中,從而實現擴展。

 

2、環境、軟件準備

 

1.centos 7

2.k8s集羣

 

3、部署 Jenkins Server 到 Kubernetes

文件在GitHub上

https://github.com/wenpengfan/k8s-jenkins-CI-CD

 

說明一下:這裏 Service 我們暴漏了端口 8080 和 50000,8080 爲訪問 Jenkins Server 頁面端口,50000 爲創建的 Jenkins Slave 與 Master 建立連接進行通信的默認端口,如果不暴露的話,Slave 無法跟 Master 建立連接。這裏使用 NodePort 方式暴漏端口,並未指定其端口號,由 Kubernetes 系統默認分配,當然也可以指定不重複的端口號(範圍在 30000~32767)。

 

接下來,通過 kubectl 命令行執行創建 Jenkins Service。

 

kubectl create -f jenkins-deployment.yaml

kubectl create -f jenkins-service.yaml

kubectl create -f service-account.yml

 

#當使用pvc持久化數據時,可能容器會起不來報錯(我這裏沒有做持久化)

https://github.com/wenpengfan/k8s-jenkins-CI-CD

 

如報錯Can not write to /var/jenkins_home/copy_reference_file.log. Wrong volume permissions?

是因爲默認的鏡像使用的是 jenkins 這個用戶,而我們通過 PVC 掛載到 nfs 服務器的共享數據目錄下面卻是 root 用戶的,所以沒有權限訪問該目錄,要解決該問題,也很簡單,我只需要在 nfs 共享數據目錄下面把我們的目錄權限重新分配下即可:

$ chown -R 1000 /data/k8s/jenkins

 

查看狀態

 

訪問jenkins

http://192.168.30.147:30002

 

注意: 初始化過程中,讓輸入 /var/jenkins_home/secret/initialAdminPassword 初始密碼時,因爲我們沒有掛載到外部路徑,可以進入到容器內部進行獲取。

 

$ kubectl exec -it jenkins-960997836-fff2q cat /var/jenkins_home/secrets/initialAdminPassword

 

4、Jenkins 配置 Kubernetes Plugin

管理員賬戶登錄 Jenkins Master 頁面,點擊 “系統管理” —> “管理插件” —> “可選插件” —> “Kubernetes plugin” 勾選安裝即可。 

 

安裝完畢後,點擊 “系統管理” —> “系統設置” —> “新增一個雲” —> 選擇 “Kubernetes”,然後填寫 Kubernetes 和 Jenkins 配置信息。 

說明一下:

 

kubernetes地址:https://kubernetes.default.svc.cluster.local

注意 namespace,我們這裏填 kube-ops,然後點擊Test Connection,如果出現 Connection test successful 的提示信息證明 Jenkins 已經可以和 Kubernetes 系統正常通信了,然後下方的 Jenkins URL 地址:http://jenkins.kube-ops.svc.cluster.local:8080,這裏的格式爲:服務名.namespace.svc.cluster.local:8080

 

另外需要注意,如果這裏 Test Connection 失敗的話,很有可能是權限問題,這裏就需要把我們創建的 jenkins 的 serviceAccount 對應的 secret 添加到這裏的 Credentials 裏面。

 

5、測試並驗證

好了,通過 Kubernetes 安裝 Jenkins Master 完畢並且已經配置好了連接,接下來,我們可以配置 Job 測試一下是否會根據配置的 Label 動態創建一個運行在 Docker Container 中的 Jenkins Slave 並註冊到 Master 上,而且運行完 Job 後,Slave 會被註銷並且 Docker Container 也會自動刪除吧!

 

在不填寫pod template的情況下,jenkins slave會默認使用jenkins/jnlp-slave:alpine鏡像

5.1、pipeline 類型支持

創建一個 Pipeline 類型 Job 並命名爲 my-k8s-jenkins-pipeline,然後在 Pipeline 腳本處填寫一個簡單的測試腳本如下:

 

def label = "mypod-${UUID.randomUUID().toString()}"

podTemplate(label: label, cloud: 'kubernetes') {

node(label) {

stage('Run shell') {

sh 'sleep 130s'

sh 'echo hello world.'

}

}

}

 

 

6, 配置 Pod Template

配置 Pod Template,其實就是配置 Jenkins Slave 運行的 Pod 模板,命名空間我們同樣是用 kube-ops,Labels 這裏也非常重要,對於後面執行 Job 的時候需要用到該值,然後我們這裏使用的是 cnych/jenkins:jnlp 這個鏡像,這個鏡像是在官方的 jnlp 鏡像基礎上定製的,加入了 kubectl 等一些實用的工具。 

另外需要注意我們這裏需要在下面掛載兩個主機目錄,一個是 /var/run/docker.sock,該文件是用於 Pod 中的容器能夠共享宿主機的 Docker,這就是大家說的 docker in docker 的方式,Docker 二進制文件我們已經打包到上面的鏡像中了,另外一個目錄下 /root/.kube 目錄,我們將這個目錄掛載到容器的 /home/jenkins/.kube 目錄下面這是爲了讓我們能夠在 Pod 的容器中能夠使用 kubectl 工具來訪問我們的 Kubernetes 集羣,方便我們後面在 Slave Pod 部署 Kubernetes 應用。 

 

另外還有幾個參數需要注意,如下圖中的Time in minutes to retain slave when idle,這個參數表示的意思是當處於空閒狀態的時候保留 Slave Pod 多長時間,這個參數最好我們保存默認就行了,如果你設置過大的話,Job 任務執行完成後,對應的 Slave Pod 就不會立即被銷燬刪除。 

到這裏我們的 Kubernetes Plugin 插件就算配置完成了。

 

 

echo "測試 Kubernetes 動態生成 jenkins slave"

echo "==============docker in docker==========="

docker info

echo "=============kubectl============="

kubectl get pods

 

 

現在我們直接在頁面點擊做成的 Build now 觸發構建即可,然後觀察 Kubernetes 集羣中 Pod 的變化

同樣也可以查看到對應的控制檯信息: 

 

到這裏證明我們的任務已經構建完成,然後這個時候我們再去集羣查看我們的 Pod 列表,發現 kube-ops 這個 namespace 下面已經沒有之前的 Slave 這個 Pod 了。

 

到這裏我們就完成了使用 Kubernetes 動態生成 Jenkins Slave 的方法。下節課我們來給大家介紹下怎麼在 Jenkins 中來發布我們的 Kubernetes 應用

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章