Tekton系列之实践篇-由Jenkins改成Tekton

Tekton系列之实践篇-由Jenkins改成Tekton

作者:乔克 2022-03-21 09:40:48

云计算

云原生 从Jenkins迁移到Tekton,主要就是Pipeline的改写,但是从整体来看并不复杂,因为Jenkins中的过程都是定义好的,我们只需要按它的步骤改造成Tekton适配的语法即可。

在《​​Tekton系列之实践篇-我的第一条Pipeline​​》中我们已经实现了第一条流水线,但是这条流水线还是比较简单,完成了基础的功能。这篇文章带你怎么根据Jenkins的Jenkinsfile来定制自己的Tekton Pipeline。

首先我们来看看Jenkinsfile中是什么样子,如下:

// 引入方法
defdingmes=neworg.devops.sendDingTalk()
defBUILD_USER
defIS_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 参数进行 Jar 包强制刷新', 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'''
exportEXIST_IMG=$(dockerpull$IMG_REPO:$IMG_TAG&>/dev/null&&echotrue||echofalse)
echo$EXIST_IMG
if [ $refresh=="true"-o$EXIST_IMG=="false" ]
then
echo"开始编译并推送镜像" ;
$refresh&&gradlecleanbootJar--configure-on-demand--build-cache--refresh-dependencies||gradlecleanbootJar--configure-on-demand--build-cache
dockerbuild-fDockerfile-t$IMG_REPO:$IMG_TAG . ;
dockerpush$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我做了一些删减,但是整个流程是没变的,咋一看是不是同样很简单?我将步骤整理如下:

  • 从代码仓库拉取代码。
  • 编译代码并推送到仓库。
  • 根据不同的分支推送到不同的环境。
  • 代码扫描。

整体的流程和上一篇文章没太大不同,区别在于:

  • 多分支流水线发布。
  • 由kubectl改成了helm chart。
  • 新增了代码扫描。

这里采用Helm Chart来部署应用,我使用的是阿里云的Chart仓库。不会使用的朋友可以通过阿里云–>云效DevOps–>研发–>私有仓库进行申请。

我们现在先创建Task,然后再组装Pipeline。

使用Helm Chart发布应用Task

我们在之前的文章中使用的是kubectl来发布应用,由于在我实际的使用过程中,是使用的Helm来管理的,为了保持一致,这里先创建一个Helm发布应用的Task。

在创建之前,我们先来看看有哪些地方是需要参数的:

  • namespace:由于我是不同环境不同的namespace,所以在多分支发布的时候需要指定namespace。
  • app_name:应用名。
  • chart_name:helm chart 名。
  • args:helm chart 的其他参数。

所以我们定义的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: |
helmrepoaddcoolopshttps://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了,多分支发布也是在Pipeline中组装。

整合Pipeline

在整合Pipeline之前,还是先来梳理一下流程:

  • 拉代码。
  • 编译构建、推送镜像。
  • 发布应用—-多环境。
  • 代码扫描。
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"
#定义镜像参数
-name: pathToDockerfile
description: Thepathtothebuildcontext, usedbyKaniko-withintheworkspace
default: .
-name: imageUrl
description: Urlofimagerepository
-name: imageTag
description: Tagtoapplytothebuiltimage
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.chart_username)
-name: CHART_PASSWORD
value: $(params.chart_password)
-name: APP_NAME
value: $(params.app_name)
-name: NAMESPACE
value: coolops-dev
workspaces:
-name: source
workspace: rd-repo-pvc
-name: kubernetesconfig
workspace: kubernetes-config
runAfter:
-build-push-image
-name: deploy-to-test
when:
-input: $(params.revision)
operator: in
values:
-test
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.chart_username)
-name: CHART_PASSWORD
value: $(params.chart_password)
-name: APP_NAME
value: $(params.app_name)
-name: NAMESPACE
value: coolops-test
workspaces:
-name: source
workspace: rd-repo-pvc
-name: kubernetesconfig
workspace: kubernetes-config
runAfter:
-build-push-image
-name: deploy-to-pre
when:
-input: $(params.revision)
operator: in
values:
-pre
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.chart_username)
-name: CHART_PASSWORD
value: $(params.chart_password)
-name: APP_NAME
value: $(params.app_name)
-name: NAMESPACE
value: coolops-pre
workspaces:
-name: source
workspace: rd-repo-pvc
-name: kubernetesconfig
workspace: kubernetes-config
runAfter:
-build-push-image
-name: deploy-to-prod
when:
-input: $(params.revision)
operator: in
values:
-prod
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.chart_username)
-name: CHART_PASSWORD
value: $(params.chart_password)
-name: APP_NAME
value: $(params.app_name)
-name: NAMESPACE
value: coolops-prod
workspaces:
-name: source
workspace: rd-repo-pvc
-name: kubernetesconfig
workspace: kubernetes-config
runAfter:
-build-push-image
-name: sonar-scanner
when:
-input: $(params.revision)
operator: in
values:
-test
taskRef:
name: sonar-scanner
runAfter:
-clone
params:
-name: SONAR_USERNAME
value: $(params.sonar_username)
-name: SONAR_PASSWORD
value: $(params.sonar_password)
-name: SONAR_URL
value: $(params.sonar_url)
-name: APP_NAME
value: $(params.app_name)
workspaces:
-name: source
workspace: rd-repo-pvc

编排一个PipelineRun运行一下,如下:

apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: test-hello-world-pipeline-run
spec:
pipelineRef:
name: rd-pipeline
params:
-name: revision
value: test
-name: git_url
value: https://gitee.com/coolops/devops-hello-world.git
-name: imageUrl
value: registry.cn-hangzhou.aliyuncs.com/coolops/devops-hello-world
-name: imageTag
value: latest
-name: pathToDockerfile
value: Dockerfile
-name: chart_username
value: username
-name: chart_password
value: password
-name: app_name
value: hello-world
-name: sonar_username
value: username
-name: sonar_password
value: password
-name: sonar_url
value: http://sonarqube.coolops.cn
workspaces:
-name: rd-repo-pvc
volumeClaimTemplate:
spec:
accessModes:
-ReadWriteOnce
storageClassName: openebs-hostpath
resources:
requests:
storage: 1Gi
-name: docker-config
secret:
secretName: docker-config
-name: kubernetes-config
secret:
secretName: kubernetes-config
serviceAccountName: tekton-build-sa

运行效果如下:

上面只是把应用部署到同一个集群得不同namespace下,在实际情况下可能有多个集群,我们只需要指定不同的kubernetes-config即可,当然, 需保证Tekton所在的集群能与其他集群相通。

sonar上的扫描结果如下:

总结

从Jenkins迁移到Tekton,主要就是Pipeline的改写,但是从整体来看并不复杂,因为Jenkins中的过程都是定义好的,我们只需要按它的步骤改造成Tekton适配的语法即可。

文章来源网络,作者:运维,如若转载,请注明出处:https://shuyeidc.com/wp/274191.html<

(0)
运维的头像运维
上一篇2025-05-09 15:08
下一篇 2025-05-09 15:10

相关推荐

  • 个人主题怎么制作?

    制作个人主题是一个将个人风格、兴趣或专业领域转化为视觉化或结构化内容的过程,无论是用于个人博客、作品集、社交媒体账号还是品牌形象,核心都是围绕“个人特色”展开,以下从定位、内容规划、视觉设计、技术实现四个维度,详细拆解制作个人主题的完整流程,明确主题定位:找到个人特色的核心主题定位是所有工作的起点,需要先回答……

    2025-11-20
    0
  • 社群营销管理关键是什么?

    社群营销的核心在于通过建立有温度、有价值、有归属感的社群,实现用户留存、转化和品牌传播,其管理需贯穿“目标定位-内容运营-用户互动-数据驱动-风险控制”全流程,以下从五个维度展开详细说明:明确社群定位与目标社群管理的首要任务是精准定位,需明确社群的核心价值(如行业交流、产品使用指导、兴趣分享等)、目标用户画像……

    2025-11-20
    0
  • 香港公司网站备案需要什么材料?

    香港公司进行网站备案是一个涉及多部门协调、流程相对严谨的过程,尤其需兼顾中国内地与香港两地的监管要求,由于香港公司注册地与中国内地不同,其网站若主要服务内地用户或使用内地服务器,需根据服务器位置、网站内容性质等,选择对应的备案路径(如工信部ICP备案或公安备案),以下从备案主体资格、流程步骤、材料准备、注意事项……

    2025-11-20
    0
  • 如何企业上云推广

    企业上云已成为数字化转型的核心战略,但推广过程中需结合行业特性、企业痛点与市场需求,构建系统性、多维度的推广体系,以下从市场定位、策略设计、执行落地及效果优化四个维度,详细拆解企业上云推广的实践路径,精准定位:明确目标企业与核心价值企业上云并非“一刀切”的方案,需先锁定目标客户群体,提炼差异化价值主张,客户分层……

    2025-11-20
    0
  • PS设计搜索框的实用技巧有哪些?

    在PS中设计一个美观且功能性的搜索框需要结合创意构思、视觉设计和用户体验考量,以下从设计思路、制作步骤、细节优化及交互预览等方面详细说明,帮助打造符合需求的搜索框,设计前的规划明确使用场景:根据网站或APP的整体风格确定搜索框的调性,例如极简风适合细线条和纯色,科技感适合渐变和发光效果,电商类则可能需要突出搜索……

    2025-11-20
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注