Tekton系列之实践篇-由Jenkins改成Tekton
微信公众号:运维开发故事,作者:乔克
在《Tekton系列之实践篇-我的第一条Pipeline》中我们已经实现了第一条流水线,但是这条流水线还是比较简单,完成了基础的功能。这篇文章带你怎么根据Jenkins的Jenkinsfile来定制自己的Tekton Pipeline。
首先我们来看看Jenkinsfile中是什么样子,如下:
// 引入方法
def dingmes = new org.devops.sendDingTalk()
def BUILD_USER
def IS_IMAGE_PUSHpipeline {agent {kubernetes {label "jenkins-slave-${UUID.randomUUID().toString()}"yaml """
apiVersion: v1
kind: Pod
spec:nodeSelector:kubernetes.io/hostname: node-2containers:- name: gradleimage: registry.cn-hangzhou.aliyuncs.com/coolops/builder-gradle:v2command: ['cat']tty: truevolumeMounts:- name: cachesmountPath: /root/.gradle/caches/- name: indockermountPath: /var/run/docker.sock- name: helmimage: registry.cn-hangzhou.aliyuncs.com/coolops/helm3:3.2.4 command: ['cat']tty: true - name: sonarimage: registry.cn-hangzhou.aliyuncs.com/coolops/gradle:5.6.4-jdk11command: ['cat']tty: truevolumeMounts:- name: sonarcachemountPath: /root/.gradle/caches/volumes:- name: cacheshostPath:path: "/data/jenkins-job/${JOB_NAME}/gradle/"- name: indockerhostPath:path: "/var/run/docker.sock"- name: sonarcachehostPath: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=xxxCHART_PASSWORD=xxxIMG_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 '''export EXIST_IMG=$(docker pull $IMG_REPO:$IMG_TAG &>/dev/null && echo true || echo false)echo $EXIST_IMGif [ $refresh == "true" -o $EXIST_IMG == "false" ]thenecho "开始编译并推送镜像" ;$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 ;elseecho "镜像已存在,跳过编译";fi'''}}}}stage('helm3 add repo') {steps {container('helm') {withCredentials([kubeconfigContent(credentialsId : 'kubeconfig-token' ,variable : 'kubconfig' ,)]) {sh '''set +xmkdir ~/.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: kubernetesconfigmountPath: /root/.kubeparams:- name: IMAGE- name: TAG- name: NAMESPACE- name: BRANCH_NAME- name: CHART_NAME- name: CHART_USERNAME- name: CHART_PASSWORD- name: APP_NAMEsteps:- name: run-helmimage: registry.cn-hangzhou.aliyuncs.com/coolops/helm3:3.2.4workingDir: $(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: sourceparams:- name: SONAR_USERNAME- name: SONAR_PASSWORD- name: SONAR_URL- name: APP_NAMEsteps:- name: sonar-scannerimage: registry.cn-hangzhou.aliyuncs.com/coolops/sonar-scanner:2.2.0workingDir: $(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-configparams:# 定义代码仓库- name: git_url- name: revisiontype: stringdefault: "master"- name: gitInitImagetype: stringdefault: "registry.cn-hangzhou.aliyuncs.com/coolops/tekton-git-init:v0.29"# 定义镜像参数- name: pathToDockerfiledescription: The path to the build context, used by Kaniko - within the workspacedefault: .- name: imageUrldescription: Url of image repository- name: imageTagdescription: Tag to apply to the built imagedefault: latest- name: chart_nametype: stringdefault: coolops/coolops-rd- name: chart_usernametype: string- name: chart_passwordtype: string- name: app_nametype: string- name: namespacetype: stringdefault: default# 定义代码扫描- name: sonar_usernametype: stringdefault: admin- name: sonar_passwordtype: stringdefault: admin- name: sonar_urltype: stringtasks: # 添加task到流水线中- name: clonetaskRef:name: git-cloneworkspaces:- name: outputworkspace: rd-repo-pvcparams:- name: urlvalue: $(params.git_url)- name: revisionvalue: $(params.revision)- name: gitInitImagevalue: $(params.gitInitImage)- name: unit-testworkspaces: # 传递 workspaces- name: sourceworkspace: rd-repo-pvctaskRef:name: unit-testrunAfter:- clone- name: build-push-imageparams:- name: pathToDockerfilevalue: $(params.pathToDockerfile)- name: imageUrlvalue: $(params.imageUrl)- name: imageTagvalue: $(tasks.clone.results.commit)taskRef:name: build-push-imagerunAfter:- unit-testworkspaces: # 传递 workspaces- name: sourceworkspace: rd-repo-pvc- name: dockerconfigworkspace: docker-config- name: deploy-to-devwhen:- input: $(params.revision)operator: invalues:- devtaskRef:name: helm-to-k8sparams:- name: IMAGEvalue: $(params.imageUrl)- name: TAGvalue: $(tasks.clone.results.commit)- name: BRANCH_NAMEvalue: $(params.revision)- name: CHART_NAMEvalue: $(params.chart_name)- name: CHART_USERNAMEvalue: $(params.chart_username)- name: CHART_PASSWORDvalue: $(params.chart_password)- name: APP_NAMEvalue: $(params.app_name)- name: NAMESPACEvalue: coolops-devworkspaces:- name: sourceworkspace: rd-repo-pvc- name: kubernetesconfigworkspace: kubernetes-configrunAfter:- build-push-image- name: deploy-to-testwhen:- input: $(params.revision)operator: invalues:- testtaskRef:name: helm-to-k8sparams:- name: IMAGEvalue: $(params.imageUrl)- name: TAGvalue: $(tasks.clone.results.commit)- name: BRANCH_NAMEvalue: $(params.revision)- name: CHART_NAMEvalue: $(params.chart_name)- name: CHART_USERNAMEvalue: $(params.chart_username)- name: CHART_PASSWORDvalue: $(params.chart_password)- name: APP_NAMEvalue: $(params.app_name)- name: NAMESPACEvalue: coolops-testworkspaces:- name: sourceworkspace: rd-repo-pvc- name: kubernetesconfigworkspace: kubernetes-configrunAfter:- build-push-image- name: deploy-to-prewhen:- input: $(params.revision)operator: invalues:- pretaskRef:name: helm-to-k8sparams:- name: IMAGEvalue: $(params.imageUrl)- name: TAGvalue: $(tasks.clone.results.commit)- name: BRANCH_NAMEvalue: $(params.revision)- name: CHART_NAMEvalue: $(params.chart_name)- name: CHART_USERNAMEvalue: $(params.chart_username)- name: CHART_PASSWORDvalue: $(params.chart_password)- name: APP_NAMEvalue: $(params.app_name)- name: NAMESPACEvalue: coolops-preworkspaces:- name: sourceworkspace: rd-repo-pvc- name: kubernetesconfigworkspace: kubernetes-configrunAfter:- build-push-image- name: deploy-to-prodwhen:- input: $(params.revision)operator: invalues:- prodtaskRef:name: helm-to-k8sparams:- name: IMAGEvalue: $(params.imageUrl)- name: TAGvalue: $(tasks.clone.results.commit)- name: BRANCH_NAMEvalue: $(params.revision)- name: CHART_NAMEvalue: $(params.chart_name)- name: CHART_USERNAMEvalue: $(params.chart_username)- name: CHART_PASSWORDvalue: $(params.chart_password)- name: APP_NAMEvalue: $(params.app_name)- name: NAMESPACEvalue: coolops-prodworkspaces:- name: sourceworkspace: rd-repo-pvc- name: kubernetesconfigworkspace: kubernetes-configrunAfter:- build-push-image- name: sonar-scannerwhen:- input: $(params.revision)operator: invalues:- testtaskRef:name: sonar-scannerrunAfter:- cloneparams:- name: SONAR_USERNAMEvalue: $(params.sonar_username)- name: SONAR_PASSWORDvalue: $(params.sonar_password)- name: SONAR_URLvalue: $(params.sonar_url)- name: APP_NAMEvalue: $(params.app_name)workspaces:- name: sourceworkspace: rd-repo-pvc
编排一个PipelineRun运行一下,如下:
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:name: test-hello-world-pipeline-run
spec:pipelineRef:name: rd-pipelineparams:- name: revisionvalue: test- name: git_urlvalue: https://gitee.com/coolops/devops-hello-world.git - name: imageUrlvalue: registry.cn-hangzhou.aliyuncs.com/coolops/devops-hello-world- name: imageTagvalue: latest- name: pathToDockerfilevalue: Dockerfile- name: chart_usernamevalue: username- name: chart_passwordvalue: password- name: app_namevalue: hello-world- name: sonar_usernamevalue: username- name: sonar_passwordvalue: password- name: sonar_urlvalue: http://sonarqube.coolops.cnworkspaces:- name: rd-repo-pvcvolumeClaimTemplate:spec:accessModes:- ReadWriteOncestorageClassName: openebs-hostpathresources:requests:storage: 1Gi- name: docker-configsecret:secretName: docker-config- name: kubernetes-configsecret:secretName: kubernetes-configserviceAccountName: tekton-build-sa
运行效果如下:
上面只是把应用部署到同一个集群得不同namespace下,在实际情况下可能有多个集群,我们只需要指定不同的kubernetes-config
即可,当然, 需保证Tekton所在的集群能与其他集群相通。
sonar上的扫描结果如下:
总结
从Jenkins迁移到Tekton,主要就是Pipeline的改写,但是从整体来看并不复杂,因为Jenkins中的过程都是定义好的,我们只需要按它的步骤改造成Tekton适配的语法即可。
最后,求关注。如果你还想看更多优质原创文章,欢迎关注我们的公众号「运维开发故事」。
如果我的文章对你有所帮助,还请帮忙点赞、在看、转发一下,你的支持会激励我输出更高质量的文章,非常感谢!
你还可以把我的公众号设为「星标」,这样当公众号文章更新时,你会在第一时间收到推送消息,避免错过我的文章更新。
我是 乔克,《运维开发故事》公众号团队中的一员,一线运维农民工,云原生实践者,这里不仅有硬核的技术干货,还有我们对技术的思考和感悟,欢迎关注我们的公众号,期待和你一起成长!
Tekton系列之实践篇-由Jenkins改成Tekton相关推荐
- Tekton系列之实践篇-如何用Jenkins来管理Tekton
微信公众号:运维开发故事,作者:乔克 在<Tekton系列之实践篇-由Jenkins改成Tekton>中,我们可以将Jenkinsfile改成Tekton Pipeline,但是Tekto ...
- Tekton系列之实践篇-使用Tekton Trigger让Tekton使用更简单
微信公众号:运维开发故事,作者:乔克 在<Tekton实践篇-如何用Jenkins来管理Tekton>我们介绍了如何使用Jenkins来管理Tekton,这种方式是运维主动式管理,也就是需 ...
- Tekton系列之实践篇-我的第一条Pipeline
作者 | 乔克 博客 | https://www.coolops.cn 公众号 | 运维开发故事((ID:mygsdcsf)) 前面已经完成了Tekton的安装和理论知识的介绍,如果你认真的看完了文章 ...
- 三菱A系列程序改成Q系列程序,实例说明 包含原程序与改后的程序,方便对照
三菱A系列程序改成Q系列程序,实例说明 包含原程序与改后的程序,方便对照 程序里包含模数和数模转换模块,通信模块的应用 控制上包含模拟量控制和简单的PID控制,顺序结构 现工厂PLC升级换代,尤其是A ...
- Jenkins由英文界面改成中文界面
今天安装了个Jenkins,但发现是英文界面,对于我这英文大部分还给老师的人来说,不太友好,为了方便操作,我将界面改成了中文版,这里记录下操作内容 界面本来是上图这样的,那我们要将英文版改成中文版怎么 ...
- 一点就分享系列(实践篇3-中篇)— 虽迟但到!全网首发?yolov5之“baseline修改小结“+“CV领域展开-Involutiontransformercnn”
一点就分享系列(实践篇3-中篇)- yolov5之"修改总结以及baseline算子的分享" 说明 上篇有很多朋友照搬了我的yaml结构,这里抱歉下也有原因是我的工作偏工程,真的研 ...
- 一点就分享系列(实践篇3-上篇)— 修改YOLOV5 之”魔刀小试“+ Trick心得分享+V5精髓部分源码解读
一点就分享系列(实践篇3-上篇)-修改YOLOV5 魔刀小试+ Trick心得分享 DL部署大热,而我觉得回归原理和源码更加重要!正如去年,我也提倡部署工程化,眼争上班工作我这里也是以搬砖产出为主.但 ...
- 一点就分享系列(实践篇6——上篇)【迟到补发_详解yolov8】Yolo-high_level系列融入YOLOv8 旨在研究和兼容使用【3月份开始持续补更】
一点就分享系列(实践篇5-补更篇)[迟到补发]-Yolo系列算法开源项目融入V8旨在研究和兼容使用[持续更新] 题外话 [最近一直在研究开放多模态泛化模型的应用事情,所以这部分内容会更新慢一些,文章和 ...
- 六、Git多人开发: 把同一文件改成了不同的文件名如何处理?
@Author:Runsen 把同一文件改成了不同的文件名如何处理? 我们接着上面的话题,如果把同一文件改成了不同的文件名,如何处理? 小A和小B首先对使用git pull命令同步下.小Auser.h ...
最新文章
- 查看LINUX发行版的名称及其版本号
- 19 java程序员面试宝典视频课程之正则表达式
- SDOD:基于depth的实时3D检测与分割
- sourcetree 回滚
- pypthon3精要(16)-enumerate
- android初学之退出应用程序
- js声明变量的三种方式
- some understanding of《Improved Use of Continuous Attributes in C4.5》
- WordPress主题制作全过程(二):主题文件构成
- jsp购物车和mysql_用jsp和数据库做的购物车的源程序
- xp精简版安装iis
- 笔记本电脑计算机恢复出厂设置密码,笔记本电脑怎么恢复出厂设置?
- 离线 维基百科 android,维基百科离线版(Kiwix)
- 在Windows Server 2012中搭建WEB服务器,附ASP配置方法
- Java 导出 PDF之固定模板导出
- Opencv学习笔记 常用函数、基础知识二
- 通过高德api获取经纬度
- SYN, FIN, ACK, PSH, RST, URG
- 平板win10 android哪个耗电,您会为平板电脑选择win10还是Android?
- Car-eye 车辆管理系统API设计