基於 kubernetes 的動態 jenkins slave

                          **基於 Jenkins 的 CI/CD**

既然要創建一個deployment,那我們先給他創建一個namespace

kubectl create namespace kube-ops

然後我們創建一個deployment

基於 kubernetes 的動態 jenkins slave
基於 kubernetes 的動態 jenkins slave

我們這裏使用一個名爲 jenkins/jenkins:lts 的鏡像,這是 jenkins 官方的 Docker 鏡像,然後也有一些環境變量,當然我們也可以根據自己的需求來定製一個鏡像,比如我們可以將一些插件打包在自定義的鏡像當中,可以參考文檔:https://github.com/jenkinsci/docker,我們這裏使用默認的官方鏡像就行,另外一個還需要注意的是我們將容器的 /var/jenkins_home 目錄掛載到了一個名爲 opspvc 的 PVC 對象上面,所以我們同樣還得提前創建一個對應的 PVC 對象

然後我們爲他創建pvc(pvc.yaml)
基於 kubernetes 的動態 jenkins slave

我們爲了測試方便,使用了nfs做到持久化存儲

然後我們創建這個pvc對象。

kubectl apply -f pvc.yaml

我們這裏還需要使用到一個擁有相關權限的 serviceAccount:jenkins2,我們這裏只是給 jenkins 賦予了一些必要的權限,當然如果你對 serviceAccount 的權限不是很熟悉的話,我們給這個 sa 綁定一個 cluster-admin 的集羣角色權限也是可以的,當然這樣具有一定的安全風險:(rbac.yaml)

基於 kubernetes 的動態 jenkins slave基於 kubernetes 的動態 jenkins slave

kubectl apply -f rbac.yaml

爲了方便我們測試,我們這裏通過 NodePort(後面會使用traefik,nginx-ingress) 的形式來暴露 Jenkins 的 web 服務,固定爲30005端口,另外還需要暴露一個 agent 的端口,這個端口主要是用於 Jenkins 的 master 和 slave 之間通信使用的。

一切準備的資源準備好過後,我們直接創建 Jenkins 服務:

kubectl apply -f jenkins2.yaml

我們首次創建的時候

基於 kubernetes 的動態 jenkins slave

可以看到該 Pod 處於 Running 狀態,但是 READY 值確爲0,然後我們用 describe 命令去查看下該 Pod 的詳細信息:

基於 kubernetes 的動態 jenkins slave

可以看到上面的 Warning 信息,健康檢查沒有通過,具體原因是什麼引起的呢?可以通過查看日誌進一步瞭解:

基於 kubernetes 的動態 jenkins slave

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

chown -R 1000 /data/k8s/jenkins2

然後我們重建

kubectl delete jenkins2.yaml
kubectl apply -f jenkins2.yaml

基於 kubernetes 的動態 jenkins slave

你就可以看到這個pods的狀態已經是正常的了。

我們就可以通過任意節點的 IP:30005 端口就可以訪問 jenkins 服務了,可以根據提示信息進行安裝配置即可:

基於 kubernetes 的動態 jenkins slave

到了這個頁面,我們就可以去pod裏面獲取密碼了,或者在日誌裏面查看密碼

kubectl exec -it jenkins2-6bbb7d9f4c-v9cfd -n kube-ops bash

然後根據上面的提示獲取密碼。
基於 kubernetes 的動態 jenkins slave

然後就看到了jenkins的主頁面了

先不要着集使用

我們知道持續構建與發佈是我們日常工作中必不可少的一個步驟,目前大多公司都採用 Jenkins 集羣來搭建符合需求的 CI/CD 流程,然而傳統的 Jenkins Slave 一主多從方式會存在一些痛點,比如:

主 Master 發生單點故障時,整個流程都不可用了
每個 Slave 的配置環境不一樣,來完成不同語言的編譯打包等操作,但是這些差異化的配置導致管理起來非常不方便,維護起來也是比較費勁
資源分配不均衡,有的 Slave 要運行的 job 出現排隊等待,而有的 Slave 處於空閒狀態
資源有浪費,每臺 Slave 可能是物理機或者虛擬機,當 Slave 處於空閒狀態時,也不會完全釋放掉資源。

正因爲上面的這些種種痛點,我們渴望一種更高效更可靠的方式來完成這個 CI/CD 流程,而 Docker 虛擬化容器技術能很好的解決這個痛點,又特別是在 Kubernetes 集羣環境下面能夠更好來解決上面的問題,下圖是基於 Kubernetes 搭建 Jenkins 集羣的簡單示意圖:

基於 kubernetes 的動態 jenkins slave

那麼我們使用這種方式帶來了哪些好處呢?

服務高可用,當 Jenkins Master 出現故障時,Kubernetes 會自動創建一個新的 Jenkins Master 容器,並且將 Volume 分配給新創建的容器,保證數據不丟失,從而達到集羣服務高可用。
動態伸縮,合理使用資源,每次運行 Job 時,會自動創建一個 Jenkins Slave,Job 完成後,Slave 自動註銷並刪除容器,資源自動釋放,而且 Kubernetes 會根據每個資源的使用情況,動態分配 Slave 到空閒的節點上創建,降低出現因某節點資源利用率高,還排隊等待在該節點的情況。
擴展性好,當 Kubernetes 集羣的資源嚴重不足而導致 Job 排隊等待時,可以很容易的添加一個 Kubernetes Node 到集羣中,從而實現擴展。

配置

接下來我們就需要來配置 Jenkins,讓他能夠動態的生成 Slave 的 Pod。

我們先進去到插件管理

基於 kubernetes 的動態 jenkins slave

因爲我已經安裝了,你們只需要在可選插件裏面選擇kubernetes安裝就好了。

安裝好了之後,我們到系統管理的系統配置,拖到最下方,選擇kubernetes

基於 kubernetes 的動態 jenkins slave

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

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

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

基於 kubernetes 的動態 jenkins slave

後面運行的命令和命令參數我們給他刪掉。

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

基於 kubernetes 的動態 jenkins slave

配置了後運行 Slave Pod 的時候出現了權限問題,如果出現了權限不足的問題,在 Slave Pod 配置的地方點擊下面的高級,添加上對應的 ServiceAccount 即可:

基於 kubernetes 的動態 jenkins slave

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

基於 kubernetes 的動態 jenkins slave

然後我們創建一個自由項目。

基於 kubernetes 的動態 jenkins slave

基於 kubernetes 的動態 jenkins slave

然後我們保存。

我們測試構建。

在構建的時候,我們去看jenkins的狀態,會創建一個jnlp的pod。

基於 kubernetes 的動態 jenkins slave

構建任務完成後,我們再去看pod列表,已經沒有這個jnlp的pod的。

到這裏我們就完成了使用 Kubernetes 動態生成 Jenkins Slave 的方法。

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