通過前面兩篇文章,我們已經有了一個“嗷嗷待哺”的K8s集群環境,也對相關的概念與組件有了一個基本了解(前期對概念有個印象即可,因為只有實踐了才能對其有深入理解,所謂“紙上得來終覺淺,絕知此事要躬行”),本文從實踐角度介紹如何結合我們常用的Gitlab與Jenkins,通過K8s來實現項目的自動化部署,示例將包括基於SpringBoot的服務端項目與基於Vue.js的Web項目。
本文涉及到的工具與技術包括:
- Gitlab —— 常用的源代碼管理系統
- Jenkins, Jenkins Pipeline —— 常用的自動化構建、部署工具,Pipeline以流水線的方式將構建、部署的各個步驟組織起來
- Docker,Dockerfile —— 容器引擎,所有應用最終都要以Docker容器運行,Dockerfile是Docker鏡像定義文件
- Kubernetes —— Google開源的容器編排管理系統
- Helm —— Kubernetes的包管理工具,類似Linux的yum,apt,或Node的npm等包管理工具,能將Kubernetes中的應用及相關依賴服務以包(Chart)的形式組織管理
環境背景:
- 已使用Gitlab做源碼管理,源碼按不同的環境建立了develop(對應開發環境),pre-release(對應測試環境),master(對應生產環境)分支
- 已搭建了Jenkins服務
- 已有Docker Registry服務,用於Docker鏡像存儲(基於Docker Registry或Harbor自建,或使用雲服務,本文使用阿里雲容器鏡像服務)
- 已搭建了K8s集群
預期效果:
- 分環境部署應用,開發環境、測試環境、生產環境分開來,部署在同一集群的不同namespace,或不同集群中(比如開發測試部署在本地集群的不同namespace中,生產環境部署在雲端集群)
- 配置盡可能通用化,只需要通過修改少量配置文件的少量配置屬性,就能完成新項目的自動化部署配置
- 開發測試環境在push代碼時自動觸發構建與部署,生產環境在master分支上添加版本tag並且push tag后觸發自動部署
- 整體交互流程如下圖
項目配置文件
首先我們需要在項目的根路徑中添加一些必要的配置文件,如下圖所示
包括:
- Dockerfile文件,用於構建Docker鏡像的文件(參考 Docker筆記(十一):Dockerfile詳解與最佳實踐)
- Helm相關配置文件,Helm是Kubernetes的包管理工具,可以將應用部署相關的Deployment,Service,Ingress等打包進行發布與管理(Helm的具體介紹我們后面再補充)
- Jenkinsfile文件,Jenkins的pipeline定義文件,定義了各個階段需執行的任務
Dockerfile
在項目根目錄中添加一個Dockerfile文件(文件名就叫Dockerfile),定義如何構建Docker鏡像,以Spring Boot項目為例,
1 |
FROM frolvlad/alpine-java:jdk8-slim |
將SPRING_PROFILES_ACTIVE通過參數profile暴露出來,在構建的時候可以通過 –build-args profile=xxx 來進行動態設定,以滿足不同環境的鏡像構建要求。
SPRING_PROFILES_ACTIVE本可以在Docker容器啟動時通過
docker run -e SPRING_PROFILES_ACTIVE=xxx
來設定,因這里使用Helm進行部署不直接通過docker run
運行,因此通過ARG在鏡像構建時指定
Helm配置文件
Helm是Kubernetes的包管理工具,將應用部署相關的Deployment,Service,Ingress等打包進行發布與管理(可以像Docker鏡像一樣存儲於倉庫中)。如上圖中Helm的配置文件包括:
1 |
helm - chart包的目錄名 |
我們可以在Chart.yaml中定義每個項目的chart名稱(類似安裝包名),如
1 |
apiVersion: v2 |
在values.yaml中定義模板文件中需要用到的變量,如
1 |
#部署Pod的副本數,即運行多少個容器 |
這里在默認生成的基礎上添加了container部分,可以在這里指定容器的端口號而不用去改模板文件(讓模板文件在各個項目通用,通常不需要做更改),同時添加env的配置,可以在helm部署時往容器里傳入環境變量。將Service type從默認的ClusterIp改為了NodePort。部署同類型的不同項目時,只需要根據項目情況配置Chart.yaml與values.yaml兩個文件的少量配置項,templates目錄下的模板文件可直接復用。
部署時需要在K8s環境中從Docker鏡像倉庫拉取鏡像,因此需要在K8s中創建鏡像倉庫訪問憑證(imagePullSecrets)
1 |
|
Jenkinsfile
Jenkinsfile是Jenkins pipeline配置文件,遵循Groovy語法,對於Spring Boot項目的構建部署, 編寫Jenkinsfile腳本文件如下,
1 |
image_tag = "default" //定一個全局變量,存儲Docker鏡像的tag(版本) |
Jenkinsfile定義了整個自動化構建部署的流程:
- Code Analyze,可以使用SonarQube之類的靜態代碼分析工具完成代碼檢查,這里先忽略
- Maven Build,啟動一個Maven的Docker容器來完成項目的maven構建打包,掛載maven本地倉庫目錄到宿主機,避免每次都需要重新下載依賴包
- Docker Build,構建Docker鏡像,並推送到鏡像倉庫,不同環境的鏡像通過tag區分,開發環境使用dev.commitId的形式,如dev.88f5822,測試環境使用test.commitId,生產環境可以將webhook事件設置為tag push event,直接使用tag名稱
- Helm Deploy,使用helm完成新項目的部署,或已有項目的升級,不同環境使用不同的參數配置,如訪問域名,K8s集群的訪問憑證kube_config等
Jenkins配置
Jenkins任務配置
在Jenkins中創建一個pipeline的任務,如圖
配置構建觸發器,將目標分支設置為develop分支,生成一個token,如圖
記下這里的“GitLab webhook URL”及token值,在Gitlab配置中使用。
配置流水線,選擇“Pipeline script from SCM”從項目源碼中獲取pipeline腳本文件,配置項目Git地址,拉取源碼憑證等,如圖
保存即完成了項目開發環境的Jenkins配置。測試環境只需將對應的分支修改為pre-release即可
Jenkins憑據配置
在Jenkinsfile文件中,我們使用到了兩個訪問憑證——Docker Registry憑證與本地K8s的kube憑證,
1 |
DOCKER_REGISTER_CREDS = credentials('aliyun-docker-repo-creds') //docker registry憑證 |
這兩個憑證需要在Jenkins中創建。
添加Docker Registry登錄憑證,在Jenkins 憑據頁面,添加一個用戶名密碼類型的憑據,如圖
添加K8s集群的訪問憑證,在master節點上將/root/.kube/config文件內容進行base64編碼,
1 |
base64 /root/.kube/config > kube-config-base64.txt |
使用編碼后的內容在Jenkins中創建一個Secret text類型的憑據,如圖
在Secret文本框中輸入base64編碼后的內容。
Gitlab配置
在Gitlab項目的 Settings - Integrations 頁面配置一個webhook,在URL與Secret Token中填入前面Jenkins觸發器部分的“GitLab webhook URL”及token值,選中“Push events”作為觸發事件,如圖
開發、測試環境選擇“Push events”則在開發人員push代碼,或merge代碼到develop,pre-release分支時,就會觸發開發或測試環境的Jenkins pipeline任務完成自動化構建;生產環境選擇“Tag push events”,在往master分支push tag時觸發自動化構建。如圖為pipeline構建視圖
總結
本文介紹使用Gitlab+Jenkins Pipeline+Docker+Kubernetes+Helm來實現Spring Boot項目的自動化部署,只要稍加修改即可應用於其它基於Spring Boot的項目(具體修改的地方在源碼的Readme文件中說明)。