新聞中心
Tekton系列之實踐篇-由Jenkins改成Tekton
作者:喬克 2022-03-21 09:40:48
云計算
云原生 從Jenkins遷移到Tekton,主要就是pipeline的改寫,但是從整體來看并不復(fù)雜,因為Jenkins中的過程都是定義好的,我們只需要按它的步驟改造成Tekton適配的語法即可。

創(chuàng)新互聯(lián)建站服務(wù)項目包括昌寧網(wǎng)站建設(shè)、昌寧網(wǎng)站制作、昌寧網(wǎng)頁制作以及昌寧網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,昌寧網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到昌寧省份的部分城市,未來相信會繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!
在《??Tekton系列之實踐篇-我的第一條Pipeline??》中我們已經(jīng)實現(xiàn)了第一條流水線,但是這條流水線還是比較簡單,完成了基礎(chǔ)的功能。這篇文章帶你怎么根據(jù)Jenkins的Jenkinsfile來定制自己的Tekton Pipeline。
首先我們來看看Jenkinsfile中是什么樣子,如下:
// 引入方法
def dingmes = new org.devops.sendDingTalk()
def BUILD_USER
def IS_IMAGE_PUSH
pipeline {
agent {
kubernetes {
label "jenkins-slave-${UUID.randomUUID().toString()}"
yaml """
apiVersion: v1
kind: Pod
spec:
nodeSelector:
kubernetes.io/hostname: node-2
containers:
- name: gradle
image: registry.cn-hangzhou.aliyuncs.com/coolops/builder-gradle:v2
command: ['cat']
tty: true
volumeMounts:
- name: caches
mountPath: /root/.gradle/caches/
- name: indocker
mountPath: /var/run/docker.sock
- name: helm
image: registry.cn-hangzhou.aliyuncs.com/coolops/helm3:3.2.4
command: ['cat']
tty: true
- name: sonar
image: registry.cn-hangzhou.aliyuncs.com/coolops/gradle:5.6.4-jdk11
command: ['cat']
tty: true
volumeMounts:
- name: sonarcache
mountPath: /root/.gradle/caches/
volumes:
- name: caches
hostPath:
path: "/data/jenkins-job/${JOB_NAME}/gradle/"
- name: indocker
hostPath:
path: "/var/run/docker.sock"
- name: sonarcache
hostPath:
path: "/data/jenkins-job/${JOB_NAME}/sonar/"
"""
}
}
environment {
APP_NAME = "${params.APP_NAME}"
DOCKER_CREDENTIAL_ID = 'dockerhub-token'
GIT_CREDENTIAL_ID = 'git-token'
SONAR_CREDENTIAL_ID = 'sonar-token'
KUBECONFIG_CREDENTIAL_ID = 'kubeconfig-token'
REGISTRY = 'registry.cn-hangzhou.aliyuncs.com'
DOCKERHUB_NAMESPACE = 'coolops'
CHART = 'coolops/rd'
CHART_USERNAME=xxx
CHART_PASSWORD=xxx
IMG_REPO = "$REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME"
IMG_TAG = "$GIT_COMMIT"
COMMON_ARGS = "--set image.repository=$IMG_REPO \
--set image.tag=$IMG_TAG \
--set ingress.hosts[0].paths[0]=/ "
}
parameters {
choice(description: '通過 Gradle --refresh-dependencies 參數(shù)進(jìn)行 Jar 包強(qiáng)制刷新', name: 'refresh', choices: ['false', 'true'])
}
options {
timeout(time: 30, unit: 'MINUTES')
}
stages {
stage('Checkout SCM') {
steps {
checkout(scm)
}
}
stage('Build & Push') {
steps {
container('gradle') {
withCredentials([usernamePassword(credentialsId: "$DOCKER_CREDENTIAL_ID", passwordVariable: 'DOCKER_PASSWORD', usernameVariable: 'DOCKER_USERNAME')]) {
sh 'echo "$DOCKER_PASSWORD" | docker login $REGISTRY -u "$DOCKER_USERNAME" --password-stdin'
sh '''
export EXIST_IMG=$(docker pull $IMG_REPO:$IMG_TAG &>/dev/null && echo true || echo false)
echo $EXIST_IMG
if [ $refresh == "true" -o $EXIST_IMG == "false" ]
then
echo "開始編譯并推送鏡像" ;
$refresh && gradle clean bootJar --configure-on-demand --build-cache --refresh-dependencies || gradle clean bootJar --configure-on-demand --build-cache
docker build -f Dockerfile -t $IMG_REPO:$IMG_TAG . ;
docker push $IMG_REPO:$IMG_TAG ;
else
echo "鏡像已存在,跳過編譯";
fi
'''
}
}
}
}
stage('helm3 add repo') {
steps {
container('helm') {
withCredentials([kubeconfigContent(credentialsId : 'kubeconfig-token' ,variable : 'kubconfig' ,)]) {
sh '''
set +x
mkdir ~/.kube/
echo "$kubconfig" > ~/.kube/config
'''
sh 'helm repo add coolops https://repomanage.rdc.aliyun.com/helm_repositories/66465-coolops --username=${CHART_USERNAME} --password=${CHART_PASSWORD}'
}
}
}
}
}
stage('Deploy To Dev') {
environment {
NAMESPACE = 'coolops-dev'
ENV = 'dev'
}
when {
expression {
return "$BRANCH_NAME".contains('dev')
}
}
steps {
container('helm') {
script {
stepsHelm()
}
}
}
}
stage('Deploy To test') {
environment {
NAMESPACE = 'coolops-test'
ENV = 'test'
}
when {
expression {
return "$BRANCH_NAME".contains('test')
}
}
steps {
container('helm') {
script {
stepsHelm()
}
}
}
}
stage('Deploy To Uat') {
environment {
NAMESPACE = 'coolops-uat'
ENV = 'uat'
}
when {
expression {
return "$BRANCH_NAME".contains('uat')
}
}
steps {
container('helm') {
script {
stepsHelm()
}
}
}
}
stage('Deploy To Pre') {
environment {
NAMESPACE = 'coolops-pre'
ENV = 'pre'
}
when {
expression {
return "$BRANCH_NAME".contains('pre')
}
}
steps {
container('helm') {
script {
stepsHelm()
}
}
}
}
stage('Deploy To Prod') {
environment {
NAMESPACE = 'coolops-prod'
ENV = 'prod'
}
when {
expression {
return "$BRANCH_NAME".contains('prod')
}
}
steps {
container('helm') {
script {
stepsHelm()
}
}
}
}
// 掃描
stage('Sonarqube Scanner') {
when {
expression {
return "$JOB_NAME".contains('skip')
}
}
steps {
timeout(time:20,unit:'MINUTES'){
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
container('sonar') {
sh 'gradle sonarqube \
-x test\
-Dsonar.host.url=http://sonar.coolops.cn \
-Dsonar.login=c17650fa820d985daf1f29d8a3f685d789e47e45'
}
}
}
}
}
}
}
整體的Jenkinsfile我做了一些刪減,但是整個流程是沒變的,咋一看是不是同樣很簡單?我將步驟整理如下:
- 從代碼倉庫拉取代碼。
- 編譯代碼并推送到倉庫。
- 根據(jù)不同的分支推送到不同的環(huán)境。
- 代碼掃描。
整體的流程和上一篇文章沒太大不同,區(qū)別在于:
- 多分支流水線發(fā)布。
- 由kubectl改成了helm chart。
- 新增了代碼掃描。
這里采用Helm Chart來部署應(yīng)用,我使用的是阿里云的Chart倉庫。不會使用的朋友可以通過阿里云-->云效DevOps-->研發(fā)-->私有倉庫進(jìn)行申請。
我們現(xiàn)在先創(chuàng)建Task,然后再組裝Pipeline。
使用Helm Chart發(fā)布應(yīng)用Task
我們在之前的文章中使用的是kubectl來發(fā)布應(yīng)用,由于在我實際的使用過程中,是使用的Helm來管理的,為了保持一致,這里先創(chuàng)建一個Helm發(fā)布應(yīng)用的Task。
在創(chuàng)建之前,我們先來看看有哪些地方是需要參數(shù)的:
- namespace:由于我是不同環(huán)境不同的namespace,所以在多分支發(fā)布的時候需要指定namespace。
- app_name:應(yīng)用名。
- chart_name:helm chart 名。
- args:helm chart 的其他參數(shù)。
所以我們定義的Task如下:
apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
name: helm-to-k8s
spec:
workspaces:
- name: source
- name: kubernetesconfig
mountPath: /root/.kube
params:
- name: IMAGE
- name: TAG
- name: NAMESPACE
- name: BRANCH_NAME
- name: CHART_NAME
- name: CHART_USERNAME
- name: CHART_PASSWORD
- name: APP_NAME
steps:
- name: run-helm
image: registry.cn-hangzhou.aliyuncs.com/coolops/helm3:3.2.4
workingDir: $(workspaces.source.path)
script: |
helm repo add coolops https://repomanage.rdc.aliyun.com/helm_repositories/66465-coolops --username=$(params.CHART_USERNAME) --password=$(params.CHART_PASSWORD)
common_args="--set image.repository=$(params.IMAGE) --set image.tag=$(params.TAG) --set ingress.hosts[0].paths[0]=/"
helm -n $(params.NAMESPACE) upgrade $(params.APP_NAME) $(params.CHART_NAME) ${common_args} || \
helm -n $(params.NAMESPACE) install $(params.APP_NAME) $(params.CHART_NAME) ${common_args}
代碼掃描Task
由于在Jenkins中使用了代碼掃描,所以這里加一個代碼掃描的Task,如下:
apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
name: sonar-scanner
spec:
workspaces:
- name: source
params:
- name: SONAR_USERNAME
- name: SONAR_PASSWORD
- name: SONAR_URL
- name: APP_NAME
steps:
- name: sonar-scanner
image: registry.cn-hangzhou.aliyuncs.com/coolops/sonar-scanner:2.2.0
workingDir: $(workspaces.source.path)
script: |
scanTime=`date +%F-%H-%M-%S`
sonar-scanner -Dsonar.host.url=$(params.SONAR_URL) \
-Dsonar.projectKey=$(params.APP_NAME) \
-Dsonar.projectName=$(params.APP_NAME) \
-Dsonar.projectVersion=${scanTime} \
-Dsonar.login=$(params.SONAR_USERNAME) \
-Dsonar.password=$(params.SONAR_PASSWORD) \
-Dsonar.projectDescription="$(workspaces.source.path)"
需要新增的Task就這兩個,接下來就是組裝Pipeline了,多分支發(fā)布也是在Pipeline中組裝。
整合Pipeline
在整合Pipeline之前,還是先來梳理一下流程:
- 拉代碼。
- 編譯構(gòu)建、推送鏡像。
- 發(fā)布應(yīng)用----多環(huán)境。
- 代碼掃描。
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: rd-pipeline
spec:
workspaces: # 聲明 workspaces
- name: rd-repo-pvc
- name: docker-config
- name: kubernetes-config
params:
# 定義代碼倉庫
- name: git_url
- name: revision
type: string
default: "master"
- name: gitInitImage
type: string
default: "registry.cn-hangzhou.aliyuncs.com/coolops/tekton-git-init:v0.29"
# 定義鏡像參數(shù)
- name: pathToDockerfile
description: The path to the build context, used by Kaniko - within the workspace
default: .
- name: imageUrl
description: Url of image repository
- name: imageTag
description: Tag to apply to the built image
default: latest
- name: chart_name
type: string
default: coolops/coolops-rd
- name: chart_username
type: string
- name: chart_password
type: string
- name: app_name
type: string
- name: namespace
type: string
default: default
# 定義代碼掃描
- name: sonar_username
type: string
default: admin
- name: sonar_password
type: string
default: admin
- name: sonar_url
type: string
tasks: # 添加task到流水線中
- name: clone
taskRef:
name: git-clone
workspaces:
- name: output
workspace: rd-repo-pvc
params:
- name: url
value: $(params.git_url)
- name: revision
value: $(params.revision)
- name: gitInitImage
value: $(params.gitInitImage)
- name: unit-test
workspaces: # 傳遞 workspaces
- name: source
workspace: rd-repo-pvc
taskRef:
name: unit-test
runAfter:
- clone
- name: build-push-image
params:
- name: pathToDockerfile
value: $(params.pathToDockerfile)
- name: imageUrl
value: $(params.imageUrl)
- name: imageTag
value: $(tasks.clone.results.commit)
taskRef:
name: build-push-image
runAfter:
- unit-test
workspaces: # 傳遞 workspaces
- name: source
workspace: rd-repo-pvc
- name: dockerconfig
workspace: docker-config
- name: deploy-to-dev
when:
- input: $(params.revision)
operator: in
values:
- dev
taskRef:
name: helm-to-k8s
params:
- name: IMAGE
value: $(params.imageUrl)
- name: TAG
value: $(tasks.clone.results.commit)
- name: BRANCH_NAME
value: $(params.revision)
- name: CHART_NAME
value: $(params.chart_name)
- name: CHART_USERNAME
value: $(params.<
本文名稱:Tekton系列之實踐篇-由Jenkins改成Tekton
URL網(wǎng)址:http://www.dlmjj.cn/article/dpsopcs.html


咨詢
建站咨詢
