朋友的真實操作流程,使用 Jenkins 和 Kubernetes 完成持續集成和持續部署,有搭建,有入門,手把手教學文檔,幹得擰不出水來,分享一波。
本文作者:孫丹丹,女,單身,DevOps 運維工程師,CKA 認證。就職於某容器雲平臺服務公司,負責國內多家知名企業 DevOps 運維交付。
安裝 Jenkins
啟動 Jenkins 容器
檢查 Jenkins 服務狀態
啟動成功後,就可以通過 ip:port 在瀏覽器上訪問了。ip 為 docker 所在機器的 ip, port 為 Jenkins 容器映射的宿主機埠
配置 Jenkins
Jenkins 啟動成功後,需要執行一些快速的 "一次性" 步驟。當你第一次訪問一個新的 Jenkins 實例時, 要求你使用自動生成的密碼對其進行解鎖。密碼為 Jenkins 所在容器的 /var/jenkins_home/secrets/initialAdminPassword 的內容:
或者用 K8S 命令 kubectl
在 Unlock Jenkins 頁面, 粘貼該密碼到 Administrator password 欄位並點擊 Continue。解鎖 Jenkins 後,插件安裝頁面出現,點擊 Install suggested plugins 即可。
這個過程會耗時一段時間。
創建第一個管理員用戶,可以填寫,也可以跳過,直接使用 admin 帳戶繼續。
這邊我選擇了跳過,點擊開始使用 Jenkins,就可以使用 Jenkins 了。
實現 Java 應用持續集成和持續發布
Fork 和 Clone GitHub 示例倉庫
登錄 GitHub 帳號:https://github.com
上傳代碼到 GitHub 代碼倉庫中,或 Fork 到你的 GitHub 倉庫中,演示代碼 prometheus-test-demo,地址為 https://github.com/0820sdd/prometheus-test-demo
將你的 GitHub 帳戶中的 prometheus-test-demo 倉庫 Clone 到本地機器:
打開一個終端/命令提示符,並且進入正確的目錄路徑: Mac OS 系統路徑為/Users//Documents/GitHub/ Linux 系統路徑為/home//GitHub/ Windows 系統路徑為C:\Users\\Documents\GitHub\(推薦使用 Git bash 命令行,而不是通常的 Microsoft 命令提示符)
運行以下命令完成倉庫的 clone:git clone https://github.com/YOUR-GITHUB-ACCOUNT-NAME/simple-java-maven-app其中YOUR-GITHUB-ACCOUNT-NAME 是你的 GitHub 帳戶的名稱。
在 Jenkins 中創建流水線
登錄 Jenkins,點擊頁面創建一個新任務。若是你無法看見該內容,點擊左上方的新建 item。
為新建的流水線項目指定名稱(例如 prometheus-test-demo),選擇流水線,點擊確定。
安裝 K8S 插件
登錄 Jenkins,系統管理 插件管理 搜索 kubernetes,選擇第二個 Kubernetes,點擊 安裝,安裝完成後重啟 Jenkins 。
對接 K8S 集群
申請 K8S 憑據
因為 Jenkins 伺服器在 kubernetes 集群之外,所以我們準備以下文件才能從外面連接到 kubernetes 集群。
然後點擊 Jenkins,選擇全局憑據(Unrestricted)
添加憑據,類型選擇 X.509 Client Certificate
Client Key: .kube/config文件中 client-key 對應的 key 文件
Client Certificate: .kube/config文件中 client-certificate 對應的 crt 或是 pem 文件
Server CA Certificate:.kube/config 文件中 certificate-authority 對應的 crt 或是 pem 文件,K8S 的最高權限證書
ID:可不填寫,默認會自動生成一串字符串,也可以自行設置
描述:描述下這個憑據的作用,比如這個可以寫 對接 K8S 集群憑據
填寫完畢,點擊確定。
配置 K8S 集群的對接
登錄 Jenkins,點擊 系統管理 系統配置 滑動到頁面最下面
點擊 a separate configuration page:
Kubernetes 地址:kubernetes服務地址,也就是 apiserver 的地址,一般是master 節點 NodeIP+6443 埠
Kubernetes 服務證書 key:kube-ca.crt 文件的內容
憑據:剛才創建的 certificate 憑據
Jenkins 地址:Agent 連接 Jenkins Master 的地址
其他都使用默認配置,點擊連接測試,連接測試成功,點擊 Save 存儲。
K8S pod template 配置
Jenkins 的 kubernetes-plugin 在執行構建時會在 kubernetes 集群中自動創建一個 Pod,並在 Pod 內部創建一個名為 jnlp 的容器,該容器會連接 Jenkins 並運行 Agent 程序,形成一個 Jenkins 的 Master 和 Slave 架構,然後 Slave 會執行構建腳本進行構建,但如果構建內容是要創建 Docker Image 就要實現 Docker In Docker 方案(在 Docker 裡運行 Docker),如果要在集群集群內部進行部署操作可以使用 kubectl 執行命令,要解決 kubectl 的安裝和權限分配問題。
為了方便配置一個 Pod Templates,在配置 kubernetes 連接內容的下面,這裡的模板只是模板(與類一樣使用時還要實例化過程),名稱和標籤列表不要以為是 Pod 的 name 和 label,這裡的名稱和標籤列表只是 Jenkins 查找選擇模板時使用的,Jenkins 自動創建 Pod 的 name 是項目名稱+隨機字母的組合,所以我們填寫 jenkins-slave,命名空間填寫對應的 namespace。
這邊要注意,添加 2 個 container,第一個,Pod 內添加一個容器名稱是 jnlp,Docker 鏡像填寫:jenkins/jnlp-slave:4.3-7,後面的使用默認的即可,然後在添加一個 container,容器名稱是 jnlp-kubectl,是這個容器裡面有 kubectl 的命令,鏡像名稱填寫harbor.edu.cn/library/centos-docker-kubectl:v1.0,下面增加了 Host Path Volume:/var/run/docker.sock、/root/.kube/、/etc/kubernetes/pki,這邊便是為了 jenkins-slave 下有足夠的權限可以執行 docker 及 kubectl 部署到 k8s 集群的權限,因為 jenkins-slave pod 有可能會被調度到任一 worker 節點,所以所有的 worker 節點上都必須有 /root/.kube/、/etc/kubernetes/pki,配置好之後點擊保存。
Jenkins pipeline 說明
Pipeline,簡單來說,就是一套運行在 Jenkins 上的工作流框架,將原來獨立運行於單個或者多個節點的任務連接起來,實現單個任務難以完成的複雜流程編排和可視化的工作。
Jenkins Pipeline 有幾個核心概念:
Node:節點,一個 Node 就是一個 Jenkins 節點,Master 或者 Agent,是執行 Step 的具體運行環境,比如我們之前動態運行的 Jenkins Slave 就是一個 Node 節點
Stage:階段,一個 Pipeline 可以劃分為若干個 Stage,每個 Stage 代表一組操作,比如:Build、Test、Deploy,Stage 是一個邏輯分組的概念,可以跨多個 Node
Step:步驟,Step 是最基本的操作單元,可以是列印一句話,也可以是構建一個 Docker 鏡像,由各類 Jenkins 插件提供,比如命令:sh 'make',就相當於我們平時 shell 終端中執行 make 命令一樣。
Pipeline的使用:
Pipeline 腳本是由 Groovy 語言實現的
Pipeline 支持兩種語法:Declarative(聲明式)和 Scripted Pipeline(腳本式)語法
Pipeline 也有兩種創建方法:可以直接在 Jenkins 的 Web UI 界面中輸入腳本;也可以通過創建一個 Jenkinsfile 腳本文件放入項目源碼庫中
一般我們都推薦在 Jenkins 中直接從原始碼控制(SCMD)中直接載入 Jenkinsfile Pipeline 這種方法,但是本次為了更直觀的展示,我們在 Web UI 界面中輸入腳本
Jenkins pipeline 入門
創建並運行 pipeline
進入到 Jenkins 首頁,點擊項目 prometheus-test-demo,點擊左側配置
點擊頁面頂部的Pipeline 選項卡,向下滾動到Pipeline 部分
在定義域中,選擇Pipeline script選項
點擊保存,切換到 Jenkins 頁面,點擊左側的 打開 Blue Ocean 進入Jenkins的Blue Ocean界面,進入到 相應的項目下,點擊 運行 。
也可以在 Jenkins prometheus-test-demo 項目下,點擊左側菜單 立即構建,然後點擊正在構建的任務,就可以看到 Console Output:
在 Slave 中運行 Pipeline
上面對 Jenkins 的 Pipeline 做了簡單的測試,但是其並未在我們的 Slave中運行,如果要在 Slave 中運行,其就要使用我們在對接 K8S 集群時 Pod Template 指定的標籤列表 ,點擊進 prometheus-test-demo 項目,點擊左側菜單 配置,進入到 pipeline scripts 部分,修改 pipeline scripts 如下:
點擊 立即構建,同時可以登錄到k8s集群,使用 kubectl get po -w 可以看到 jenkins-slave pod 的生命周期,就是我們開始構建這個任務,選擇了使用 jenkins slave,所以在執行過程中jenkins-slave就會自動創建,任務執行完成,jenkins-slave 對應的pod會自動回收:
在構建日誌裡我們也可以看到 jenkins 啟動了 jenkins-slave-dj3vc pod 進行這個任務的執行,也和上面的 pod 名稱對應起來了。
完整 pipeline 示例
部署應用的流程如下:
拉取 Github 代碼
maven 打包
編寫 Dockerfile
構建打包 Docker 鏡像
推送 Docker 鏡像到倉庫
編寫 Kubernetes YAML 文件
更改 YAML 文件中 Docker 鏡像 TAG
利用 kubectl 工具部署應用
最終的 Pipeline 腳本如下:
注意,prometheus-test-demo.yaml 可放在 GitHub 的 prometheus-test-demo 倉庫裡,也可以另外新建一個倉庫專門放 YAML 文件。
下面我們分解講下上面過程的具體含義:
克隆代碼
這步就是從 GitHub 上拉取代碼,注意這邊的 GitHub 倉庫倉庫比如是 公開的,因為 private 的需要各種權限配置,Jenkins 必須有一個公網 IP 或者是公網域名,但因資源問題,這部分暫時沒有辦法實現。注意,這邊 agent 裡面指定運行環境,選擇了 master,即是這個步驟在 Jenkins master節點執行。
maven 打包
maven 構建,我們指定了 maven 打包的 agent 是在 Jenkins 所在節點另起一個 docker 容器,容器的 image 為 maven:latest,並且使用-v參數把本地的 /root/.m2 掛載到 容器的 /root/.m2 目錄下,下面 steps 的步驟即是在這個 maven 容器裡面的具體操作:mvn -B clean package -Dmaven.test.skip=true。
構建鏡像
maven 構建成功,下一步就是使用 maven build 生成的 prometheus-test-demo-0.0.1-SNAPSHOT.jar 包進行 docker build,docker build 的具體命令有2條 bash 命令 組成,第一步 docker build 使用-f指定了 Dockerfile 的文件,使用--build-arg參數指定了一些參數,比如上面指定了 jar_name 是 target/prometheus-test-demo-0.0.1-SNAPSHOT.jar,最後使用-t參數指定了 docker build 的 image 的名稱及版本號。第二步就是 使用 docker tag 命令把上一步 docker build 完成的鏡像 打 tag 為 harbor.edu.cn/library/prometheus-test-demo:$,這步打 tag 的步驟是為了上傳到 harbor 鏡像倉庫,可以隨時使用。
推送鏡像
拉取鏡像
現在鏡像已經打包完成,並推送到了鏡像倉庫,後面我們所要做的就是拉取 k8s 編排文件,這一步和第一步的 拉取代碼實際是一樣的,只不過上面的拉取代碼是為了 build image,這一步是為了進行部署到 K8S。
注意:這邊指定了運行此步驟的節點是在 Jenkins 的 slave 節點下的 jnlp-kubectl container 下,這個 slave 是指在配置 對接 K8S 集群時,在 Pod Template 下指定的 標籤列表的名稱,必須與這個名稱一致,不然 jenkins 執行過程中就會報找不到對應的 label 。還有這邊指定了 jnlp-kubectl container ,這是因為 jnlp-kubectl container下有 kubectl 命令,且配置 對接 k8s 集群時,指定了把宿主機的 /root/.kube /etc/kubernetes/pki 目錄分別掛載到 container 的 /root/.kube /etc/kubernetes/pki目錄下,這邊就是 jnlp-kubectl container 可以訪問 K8S 集群的原因。
替換 YAML 文件變量
yaml文件拉取完畢,替換其中的變量。
部署
使用 kubectl 命令部署 prometheus-test-demo 應用到 K8S 集群。
最終執行效果如下
-- END --