前言:
Kubernetes,簡稱K8s,相信大家都不會陌生。這是一個開源的,用於管理雲平臺中多個主機上的容器化的應用。
Jenkins,是一個開源軟件項目,是基於Java開發的一種持續集成工具,用於監控持續重複的工作,旨在提供一個開放易用的軟件平臺,使軟件項目可以進行持續集成。
在程序員日常的開發當中,使用着各種不同的編程語言,流程中少不了開發、測試、打包、發佈等等的步驟,這其中的部分環節,是重複且必須的工作。所以慢慢地引入了持續集成的概念,從而減輕開發人員,運維人員的操作和時間成本,更好地服務好我們的程序猿(嗷嗷嗷 ~ 程序員太苦啦,是時候來點甜啦~)。
接下來讓我來給大家分享一下,如何結合K8S和Jenkins可以實現快速地實現以上的一些重複性且必要的工作,讓我們的攻城獅更好地專注在開發工作當中!
前置環境條件:
1、已經有部署好的K8S集羣環境;
2、已經在K8S環境中已經部署好Jenkins應用;
3、代碼倉庫(如gitlab、GitHub等)已經通過webhook等方式,和Jenkins能進行通訊;
4、jenkins添加好代碼倉庫對應的流水線作業。
1、登錄到Jenkins UI進行模版配置
登錄到Jenkins – 左菜單(系統設置) – 節點管理 – Configure Clouds,進行模版的配置
1.1 編輯Kubernetes模版
第一頁詳細配置如上圖,基本都是用默認值即可,有幾個地方需要根據實際的集羣信息進行填寫就可以啦,挺簡單的!!
1.2 編輯pod模版
2-1和2-2是pod模版的名稱和模版標籤
第二頁詳細配置如上圖,按照上圖說明即可。俗話說,工欲善其事,必先利其器,至此,jenkins的模版關鍵配置已經完成啦,接下來就是使用這些模版的時候啦,請繼續往下閱讀!!
2、可持續集成配置
2.1 Jenkinsfile使用詳解
這裏的lable是 上面的標籤設置的值
//模板需要修改的值:label(配置的jenkins的slave標籤),cloud:(配置的jenkins的cloud)
//定義變量
def label = "jenkins-slave-js"
//設置pod模版的信息,label是模版標籤,cloud是第一步設置的jenkins模版名
//以下操作都是在打包容器裏面進行,內容可以高度自定義,貼合不同的需求
podTemplate(label: label , cloud: 'kubernetes') {
node(label) {
//拉取倉庫代碼
def myRepo = checkout scm
def gitBranch = myRepo.GIT_BRANCH.replaceAll("origin/","").replaceAll("/","-").replaceAll("\\.","-")
def timestamp = sh(script: "echo `date '+%Y%m%d%H%M%S'`", returnStdout: true).trim()
def gitCommit = sh(script: "git rev-parse --short HEAD", returnStdout: true).trim()
gitCommit = "${gitCommit}_${timestamp}"
//鏡像標籤,這裏使用git分支名作爲鏡像的tag
def imageTag = "${gitBranch}"
//鏡像倉庫基礎地址
def dockerRegistryUrl = "http://xxxxx"
//應用服務名稱,統一用於以下各個變量名稱
def appName = "testAbc"
//模板需要更改的值 開始
//helm工具發佈時,使用的名稱,這裏使用【應用名-分支名】的格式
def helmReleaseName = "${appName}-${gitBranch}"
//部署應用服務的命名空間
def namespace = "${appName}"
//鏡像的中間名稱,用於平均基礎鏡像地址
def imageEndpoint = "${appName}/webapi"
//模板需要更改的值 結束
//完整鏡像地址(不包含鏡像tag)
def image = "${dockerRegistryUrl}/${imageEndpoint}"
//helmChart模版的倉庫名稱
def chartName = "${appName}"
//helmChart的版本
def chartVersion = "1.0"
//helmChart完整名稱
def chartDirName = "${appName}/${appName}"
//K8S的網絡模式,一般有Cluster(不對外訪問)、NodePort(釋放端口對外訪問)
def serviceType = "ClusterIP"
//如果serviceType值是NodePort,這裏可以設置指定供對外訪問的端口號,不指定則隨機,範圍詳見K8S的NodePort範圍,默認是30000-32767
def serviceNodePort = ""
//是否使用外部K8S存儲,是則設置true,否則設置false
def createPvc = true
//如果設置了使用外部存儲,則這裏需要填寫k8s的PVC資源的名稱,以便以發佈的應用服務能綁定此外部存儲
def pvcName = "${gitBranch}-${appName}-configs-pvc"
//設置外部存儲對應應用服務容器裏面的路徑
def pvcMountPath = "/var/www/${appName}/storage"
//定義不同階段,可以方便清晰地在jenkins UI上看到每個階段的耗時
stage('單元測試階段') {
script{
}
}
stage('項目編譯階段') {
//此處使用container指定第二步配置的容器名稱,就可以使用該容器環境的命令進行操作,如下面命令是前端node編譯代碼
container("node"){
sh "npm build ./main"
sh "npm run serve"
}
}
stage('構建 Docker 鏡像階段') {
container('構建 Docker 鏡像') {
withCredentials([[$class: 'UsernamePasswordMultiBinding',
credentialsId: 'docker-harbor',
usernameVariable: 'DOCKER_HUB_USER',
passwordVariable: 'DOCKER_HUB_PASSWORD']]) {
//此處是引入了docker環境,進行docker的打包,推送到遠程倉庫等操作
container('docker') {
sh """
docker login ${dockerRegistryUrl} -u ${DOCKER_HUB_USER} -p ${DOCKER_HUB_PASSWORD}
docker build -t ${imageEndpoint}:${imageTag} .
docker tag ${imageEndpoint}:${imageTag} ${dockerRegistryUrl}/${imageEndpoint}:${imageTag}
docker push ${image}:${imageTag}
"""
}
}
}
}
//K8S使用了helm發佈工具進行應用服務的發佈
stage('Helm 部署階段') {
withCredentials([[$class: 'UsernamePasswordMultiBinding',
credentialsId: 'docker-harbor',
usernameVariable: 'DOCKER_HUB_USER',
passwordVariable: 'DOCKER_HUB_PASSWORD']]) {
container('helm') {
// 這裏也可以做一些其他的分支判斷是否要直接部署
echo "[INFO] 開始 Helm 部署"
echo "1 初始化helm client"
sh "helm init --client-only --stable-repo-url https://mirror.azure.cn/kubernetes/charts/"
//添加打包容器裏面的本地helm倉庫
sh "helm repo add --username ${DOCKER_HUB_USER} --password ${DOCKER_HUB_PASSWORD} ${chartName} http://${dockerRegistryUrl}/chartrepo/${chartName}"
echo "2 如果更新了chart包則需要更新repo倉庫"
sh "helm repo update"
echo "3 更新 ${helmReleaseName} 應用服務"
sh """
helm upgrade --install ${helmReleaseName} ${chartDirName} \
--version ${chartVersion} \
--set namespace=${namespace} \
--set gitCommit=${gitCommit} \
--set gitBranch=${gitBranch} \
--set productionDeployment.image.repository=${image} \
--set canaryDeployment.image.repository=${image} \
--set productionDeployment.image.tag=${imageTag} \
--set canaryDeployment.image.tag=master \
--set createPvc=${createPvc} \
--set pvcName=${pvcName} \
--set pvcMountPath=${pvcMountPath} \
--set service.type=${serviceType} \
--set service.nodePort=${serviceNodePort} \
--namespace=${namespace}
"""
echo "[INFO] Helm 部署應用成功..."
}
}
}
}
}
至此,我們已經完成配置好jenkins模版和jenkinsfile完整的一套可持續集成系統的工作,我們後續開發時,只需要合併好代碼,觸發webhook流水線,通知jenkins進行打包、發佈、部署的操作即可,實現真正解放我們的雙手啦!!!哈哈哈!!!