0%

GitLab整合Jenkins自動部署到K8s集群

前言

原本公司內部CI/CD的流程是Gitlab => K8s ,或是 Gitlab => Docker

近期由於工作上的需要,需要更改流程為Gitlab => Jenkins => K8s

本篇主要是紀錄Gitlab串接Jenkins,最後透過Jenkins部屬到K8s集群的流程。

事前準備

此次測試需要準備一台Jenkins Server、一台Gitlab Server、K8s集群以及一個前端專案,前端專案資訊為以下:

  • NodeJs 18.19.0
  • Vue3 + Nuxt 3

Jenkins連結Gitlab

此處可以參考GitLab官方網站的教學
這邊就快速帶過

建立Jenkins作業

開啟Jenkins網站,選擇左側的”新增作業”

新增作業

輸入作業名稱,選擇作業類型選擇Pipeline,最後點選OK

設定作業類型

如果在上上節有設定成功

Gitlab Connection的部分應該可以選擇的到gitlab server

Gitlab-Connection

Build Triggers的部分只要勾”Build when a change is pushed to GitLab ….”
和”Push Events”這兩項,表示當Gitlab的前端專案有Push事件時,就會通知Jenkins做部屬

這裡的GitLab Webhook URL要記住等等設定Gitlab時會用到

p.s. 需要事先設定好Jenkins的Jenkins URL,否則Gitlab會連不上

設定作業

再來點選右下角的進階,點選裡面的Generate按鈕,會產生一組Secret token,Jenkins需要透過這組token和Gitlab傳過來的webhook驗證身分,很重要!

Secret-Token

最後Pipeline的部分目前先選擇右方的Hello World模板即可,設定完畢後點選儲存

Pipeline

設定Gitlab Webhook

回到Gitlab的前端專案,點選左側的Settings => Webhooks

Webhooks

輸入剛才的GitLab Webhook URL以及Secret token

Trigger 勾選Push events

Webhooks-Setting

如果Gitlab和Jenkins有HTTPS可以開啟SSL認證,最後點選Add webhook

Add-Webhook

會看到與Jenkins連結的Webhook已經建立完成了,現在可以測試webhook是否正常運行

點選Test按鈕

Add-Webhook-Done

再點選Push events

Push-Events

這裡沒問題的話就會在最底下出現一個狀態為200的Push-Hook Trigger

Webhook-Success

回去確認Jenkins狀態會看到此時有建置任務在跑了

PipLine-Running

安裝K8s plugins

確認Jenkins與Gitlab連線沒問題後

下一步驟就是要將專案部屬至K8s集群上

需要安裝的Jenkins plugins為以下:

設定K8s集群憑證

安裝完成後需要先設定k8s集群的憑證

這樣才能連入k8s集群內做操作

至”管理 Jenkins” => “Manage Credentials” => global => Add Credentials

Kind選擇”Kubernetes configuration(kubeconfig)”

ID、Description依照自己習慣定義即可

Kubeconfig選擇 “Enter directly”

接著到你自己的k8s master server

複製你的kubeconfig

我的kubeconfig如下圖所示

kubeconfig

將config檔的內容貼到jenkins上

jenkins-kubeconfig

最後選擇OK後,k8s的憑證就設定完成了

kubeconfig-done

完成Pipeline

最後要回到專案的Pipeline設定

以下是更改後的Pipeline:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

pipeline {
agent any;
tools {nodejs "NodeJS 18.19.0"}
environment {
// gitlab
GITLAB_DOMAIN = {your gitlab domain}
GITLAB_CID = {your gitlab Credentials ID}
GITLAB_PROJ_PATH = {your gitlab project Path}
GITLAB_PROJ_NAME = {your gitlab project Name}
GITLAB_BRANCH = {your gitlab project branch}
// registry
HARBOR_REG_URI = {your harbor domain}
HARBOR_REG_CID = {your harbor Credentials ID}
HARBOR_REG_PROJ_NAME = {your harbor Project Name}
HARBOR_REG_DATA_PATH = "${HARBOR_REG_PROJ_NAME}/${env.GITLAB_PROJ_PATH}/${env.GITLAB_PROJ_NAME}/${env.GITLAB_BRANCH}"
// k8s
KUBE_DEPLOYMENT_NAME = "deployment-${GITLAB_PROJ_NAME}"
KUBE_DEPLOYMENT_POD_NAME = "pod-${GITLAB_PROJ_NAME}"
KUBE_NAMESPACE = "${GITLAB_PROJ_NAME}-${GITLAB_BRANCH}"
KUBE_CID = 'k8s-kubeconfig'
}

stages {
stage('NPM INSTALL && BUILD') {
steps {
git url: "https://${env.GITLAB_DOMAIN}/${env.GITLAB_PROJ_PATH}/${env.GITLAB_PROJ_NAME}.git", branch: "${env.GITLAB_BRANCH}", credentialsId: "${env.GITLAB_CID}"
sh "npm install"
sh "npm run generate"
}
}
stage('上傳image') {
environment {
IMAGE_VER = sh(returnStdout: true, script: 'git rev-parse --short HEAD')
}
steps {
echo "上傳image 版本 ${env.IMAGE_VER}"
script {
docker.withRegistry("https://${env.HARBOR_REG_URI}", "${env.HARBOR_REG_CID}"){
def BuildImage = docker.build("${HARBOR_REG_DATA_PATH}")
BuildImage.push()
BuildImage.push("${IMAGE_VER}")
}
}
}
}
stage('建置服務') {
environment {
IMAGE_VER = sh(returnStdout: true, script: 'git rev-parse --short HEAD')
}
steps {
withCredentials([kubeconfigContent(credentialsId: "${KUBE_CID}", variable: 'KUBECONFIG_CONTENT')]) {
sh 'mkdir -p ~/.kube'
sh '''echo "$KUBECONFIG_CONTENT" > ~/.kube/config'''
sh "kubectl -n ${env.KUBE_NAMESPACE} set image deployment ${env.KUBE_DEPLOYMENT_NAME} ${env.KUBE_DEPLOYMENT_POD_NAME}=${env.HARBOR_REG_URI}/${HARBOR_REG_DATA_PATH}:${env.IMAGE_VER}"
script {
env.POD_COMPLETE_NAME = sh(returnStdout: true,script: "kubectl get pods -n ${env.KUBE_NAMESPACE} |grep ${env.KUBE_DEPLOYMENT_NAME} | awk '{ print \$1 }'| tr '\n' ' '").trim()
sh "kubectl -n ${env.KUBE_NAMESPACE} delete pods ${env.POD_COMPLETE_NAME} "
}
}
}
}
}
}

environment的部分用來設定gitlab、harbor以及k8s需要的參數

舉例來說 GITLAB_DOMAIN 就是你的 Gitlab 域名

GITLAB_CID 和 HARBOR_REG_CID 就是你用來登入Gitlab或是Harbor的憑證

詳細的憑證設定可參考官網的這兩篇教學

此處就不多作介紹

KUBE_DEPLOYMENT_NAME 是你k8s專案的 deployment 名稱
KUBE_DEPLOYMENT_POD_NAME 則是pod的名稱

此處CI/CD的前提是一開始需要手動跑一次kubectl apply -f deployment.yaml

之後在執行CI/CD時,會將舊的image更換成harbor內最新的image

所以每個專案都需要維護一份自己的k8s yaml檔

建議可以存在gitlab上方便維護

這裡有三個stage

依序是專案打包 => 上傳專案Image => 在k8s集群上建置該服務

這邊只是大概說明一下這個Pipeline在做甚麼

更詳細的參數說明可以再GOOGLE

確認Pipeline沒問題後即可點選儲存

建置任務

編輯完Pipeline後,回到JOB頁面

即可點選左側的馬上建置

等個幾秒鐘應該就會開始執行

run-pipeline

等待建置完畢後,查看k8s確認service是否有正確起動後即完成整個CI/CD流程👏

check-k8s

結尾

以上整個流程大致為:

Gitlab推Code => 觸發jenkins部屬流程 => 執行Pipeline的指令 => 將服務部屬至K8s集群上

該篇有許多細節沒有講到,例如Gitlab憑證要如何設定至jenkins上

以及k8s的deployment詳細該怎麼設定等等

以後如果有空再找時間補起來😫

目前先請大家自行研究一下🙏