二十二、DevOps:基于Tekton的云原生平台落地(三)
二十二、DevOps:基于Tekton的云原生平台落地(三)
文章目录
- 二十二、DevOps:基于Tekton的云原生平台落地(三)
- 1、Tekton概念及特性
- 1.1 Tekton初识
- 1.2 Tekton 核心功能
- 1.3 Tekton 核心资源
- 2、Tekton实践
- 2.1 Tekton部署
- 2.2 Tekton初体验
- 2.3 Pipelines初体验
- 2.4 常用Task
- 2.4.1 代码拉取Task
- 2.4.2 拉取私有仓库代码
- 2.4.3 自定义工作目录
- 2.4.4 初始化Task
- 2.4.5 结果存储results
- 2.4.6 串联多任务Pipelines
- 2.4.7 代码构建Task
- 2.4.8 镜像构建Task
- 2.4.9 服务发版Task
- 3、Tekton企业落地实战
- 3.1 GitLab 安装
- 3.1.1 关闭机器防火墙和 selinux
- 3.1.2 安装gitlab
- 3.1.3 创建项目
- 3.1.4 配置密钥
- 3.2 Harbor
- 3.2.1 安装docker
- 3.2.2 配置docker-compose
- 3.2.3 安装 Harbor
- 3.2.4 创建开机自启动脚本
- 3.2.5 docker 配置 insecure registry
- 3.2.6 Containerd 配置 insecure registry **(k8s节点)**
- 3.3 Tekton必备资源梳理
- 3.3.1 代码拉取Task
- 3.3.2 代码拉取 Secret
- 3.3.3 镜像仓库 Secret
- 3.3.4 资源部署 Secret
- 3.3.5 Tekton 必备资源
- 3.3.6 安装 Tekton 必备资源
- 3.4 Tekton自动化部署Java应用
- 3.4.1 创建 Java 测试用例
- 3.4.2 定义 Dockerfile
- 3.4.3 定义 Kubernetes 资源
- 3.4.4 PipelineRun 自动构建发版
- 3.5 Tekton自动化构建前端Vue应用
- 3.5.1 定义 Dockerfile
- 3.5.2 定义 Kubernetes 资源
- 3.5.3 PipelineRun 自动构建发版
- 3.6 Tekton自动化构建GO应用
- 3.6.1 定义 Dockerfile
- 3.6.2 定义 Kubernetes 资源
- 3.6.3 PipelineRun 自动构建发版
1、Tekton概念及特性
1.1 Tekton初识
Tekton 是一个云原生的 CI/CD 流水线解决方案,属于 Linux 基金会较为流行的开源项目之一。Tekton 以 Kubernetes 资源的形式部署在集群上,包含一组 Kubernetes 自定义资源共同构成了一个完整的生态系统。Tekton 的核心资源包括 StepAction、Task、TaskRun、Pipeline、PipelineRun 等,可以使用 Kubectl 管理 Tekton 的资源,或配置和执行流水线。
1.2 Tekton 核心功能
- 云原生:基于 Kubernetes 设计,所有任务均以容器运行,且按需创建和销毁
- 标准化:Tekton 运行在 Kubernetes 集群上,所有资源均以 CRD 定义,符合代码即基础设施
- 可移植性:基于标准 CRD 资源构建,可以一键式跨集群迁移
- 可扩展性:Tekton 随集群扩展,无需任何修改即可增加工作负载
- 事件驱动:支持事件驱动模式,可以接收外部 webhook 事件触发流水线
- 社区生态:具备社区和 Task Hub,可以选择已有 Task 集成各种工具
1.3 Tekton 核心资源
- StepAction:Tekton 提供的一种用于定义可复用工作单元的资源,一般用于定义具体的执行步骤,比如构建、扫描等
- Task:用于定义一系列有序的步骤,每个步骤用于调用特定的工具处理特定的任务,可以指定具体的命令,也可以绑定 StepActions
- Tekton Pipeline:Tekton Pipeline 为 Tekton 的基础,由多个 Task 组成,作为构建 CI/CD 流水线的基础模块
- Tekton Triggers:Tekton 事件触发组件,可以用于接收外部系统的事件,之后进行流水线的执行
- Tekton CLI:Tekton 提供的客户端工具,可以使用 tkn 与 Tekton 交互
- Tekton Dashboard:Tekton 提供的基于 Web 的图形界面
- TaskRun:用于实例化特定任务(Task)相当于调用 Task 执行任务
- PipelineRun:用于实例化特定流水线(Pipeline)相当于执行 Pipeline 中定义的任务
2、Tekton实践
2.1 Tekton部署
官方安装文档:
# 安装 Tekton:
[root@k8s-master01 ~]# curl -o tekton-release.yaml https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml
[root@k8s-master01 ~]# kubectl apply --filename tekton-release.yaml# 查看状态:
[root@k8s-master01 ~]# kubectl get po -n tekton-pipelines
NAME READY STATUS RESTARTS AGE
tekton-events-controller-99665746c-2nf6p 1/1 Running 0 8m4s
tekton-pipelines-controller-7595d6585d-hg9tc 1/1 Running 0 8m4s
tekton-pipelines-webhook-5967d74cc4-zsfls 1/1 Running 0 8m3s
# 安装 Tekton Dashboard:
[root@k8s-master01 ~]# curl -o dashboard-release.yaml https://storage.googleapis.com/tekton-releases/dashboard/latest/release.yaml
[root@k8s-master01 ~]# kubectl apply --filename dashboard-release.yaml# 查看状态:
[root@k8s-master01 ~]# kubectl get po -n tekton-pipelines
NAME READY STATUS RESTARTS AGE
tekton-dashboard-7d4499b584-ghmg9 1/1 Running 0 91s
等待所有 Pod 启动完成后,更改 Dashboard 的 Service 为 NodePort:
[root@k8s-master01 ~]# kubectl edit svc tekton-dashboard -n tekton-pipelines
sessionAffinity: Nonetype: NodePort[root@k8s-master01 ~]# kubectl get svc -n tekton-pipelines
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
tekton-dashboard NodePort 10.106.102.181 <none> 9097:31869/TCP 3m6s
tekton-events-controller ClusterIP 10.110.221.223 <none> 9090/TCP,8008/TCP,8080/TCP 11m
tekton-pipelines-controller ClusterIP 10.100.69.160 <none> 9090/TCP,8008/TCP,8080/TCP 11m
tekton-pipelines-webhook ClusterIP 10.104.253.49 <none> 9090/TCP,8008/TCP,443/TCP,8080/TCP 11m
之后通过 NodePort 访问 Tekton Dashboard:

2.2 Tekton初体验
# 创建一个 task:
[root@k8s-master01 ~]# vim 01-task-hello.yaml
[root@k8s-master01 ~]# cat 01-task-hello.yaml
apiVersion: tekton.dev/v1
kind: Task
metadata:name: hello
spec:steps:- name: echoimage: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/alpine:3.9-tomcatscript: |#!/bin/shecho "Hello World"[root@k8s-master01 ~]# kubectl create -f 01-task-hello.yaml
[root@k8s-master01 ~]# kubectl get task
NAME AGE
hello 4s# Task 是一种资源,不会真正的执行,执行需要使用 TaskRun 进行调度:
[root@k8s-master01 ~]# vim 01-taskrun-hello.yaml
[root@k8s-master01 ~]# cat 01-taskrun-hello.yaml
apiVersion: tekton.dev/v1
kind: TaskRun
metadata:name: hello-task-run # taskrun name
spec:taskRef:name: hello # task name[root@k8s-master01 ~]# kubectl create -f 01-taskrun-hello.yaml
[root@k8s-master01 ~]# kubectl get taskrun
NAME SUCCEEDED REASON STARTTIME COMPLETIONTIME
hello-task-run True Succeeded 2m11s 13s[root@k8s-master01 ~]# kubectl get po
NAME READY STATUS RESTARTS AGE
hello-task-run-pod 0/1 Completed 0 2m14s
[root@k8s-master01 ~]# kubectl logs -f hello-task-run-pod -c step-echo
Hello World
# 接着创建第二个 task,并使用 params 接收参数:
[root@k8s-master01 ~]# vim 02-task-hello.yaml
[root@k8s-master01 ~]# cat 02-task-hello.yaml
apiVersion: tekton.dev/v1
kind: Task
metadata:name: goodbye
spec:params: # 可以接收 taskRun 和 pipeline 的参数- name: usernametype: stringsteps:- name: goodbyeimage: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/alpine:3.9-tomcatscript: |#!/bin/shecho "Goodbye $(params.username)!"[root@k8s-master01 ~]# kubectl create -f 02-task-hello.yaml
[root@k8s-master01 ~]# kubectl get task
NAME AGE
goodbye 4s
hello 9m41s# 创建 TaskRun,并传递参数:
[root@k8s-master01 ~]# vim 02-taskrun-hello.yaml
[root@k8s-master01 ~]# cat 02-taskrun-hello.yaml
apiVersion: tekton.dev/v1
kind: TaskRun
metadata:name: goodbye-task-run # taskrun name
spec:taskRef:name: goodbye # task nameparams:- name: usernamevalue: "yunwei"[root@k8s-master01 ~]# kubectl create -f 02-taskrun-hello.yaml
[root@k8s-master01 ~]# kubectl get taskrun
NAME SUCCEEDED REASON STARTTIME COMPLETIONTIME
goodbye-task-run True Succeeded 7s 2s[root@k8s-master01 ~]# kubectl get po
NAME READY STATUS RESTARTS AGE
goodbye-task-run-pod 0/1 Completed 0 25s
[root@k8s-master01 ~]# kubectl logs -f goodbye-task-run-pod -c step-goodbye
Goodbye yunwei!
2.3 Pipelines初体验
接下来创建一个 Pipeline,包含上述两个 task:
[root@k8s-master01 ~]# vim 03-pipeline-hello-goodbye.yaml
[root@k8s-master01 ~]# cat 03-pipeline-hello-goodbye.yaml
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:name: hello-goodbye
spec:params: # 也可以接收 pipelineRun 的参数- name: usernametype: stringtasks:- name: hellotaskRef:name: hello- name: goodbyerunAfter: # 在上个 task 结束之后运行- hellotaskRef:name: goodbyeparams: # 传递参数- name: usernamevalue: $(params.username) # 参数来自 spec.params 下面的参数,也就是pipelineRun 传递的参数[root@k8s-master01 ~]# kubectl create -f 03-pipeline-hello-goodbye.yaml
[root@k8s-master01 ~]# kubectl get pipeline
NAME AGE
hello-goodbye 24s
Pipeline 和 task 一样,是一种资源定义,不会执行,需要创建一个 pipelineRun 进行调度和执行:
[root@k8s-master01 ~]# vim 03-pipelinerun-hello-goodbye.yaml
[root@k8s-master01 ~]# cat 03-pipelinerun-hello-goodbye.yaml
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:name: hello-goodbye-run
spec:pipelineRef:name: hello-goodbyeparams: # 传递参数- name: usernamevalue: "Tekton"# 创建 PipelineRun:
[root@k8s-master01 ~]# kubectl create -f 03-pipelinerun-hello-goodbye.yaml
[root@k8s-master01 ~]# kubectl get pipelinerun
NAME SUCCEEDED REASON STARTTIME COMPLETIONTIME
hello-goodbye-run True Succeeded 28s 18s# 此时的 PipelineRun 会创建两个 taskRun 进行任务的调度:
[root@k8s-master01 ~]# kubectl get taskrun
NAME SUCCEEDED REASON STARTTIME COMPLETIONTIME
...
hello-goodbye-run-goodbye True Succeeded 32s 27s
hello-goodbye-run-hello True Succeeded 37s 32s
...# 查看创建的 Pod:
[root@k8s-master01 ~]# kubectl get po
NAME READY STATUS RESTARTS AGE
...
hello-goodbye-run-goodbye-pod 0/1 Completed 0 41s
hello-goodbye-run-hello-pod 0/1 Completed 0 46s
...[root@k8s-master01 ~]# kubectl logs -f hello-goodbye-run-goodbye-pod -c step-goodbye
Goodbye Tekton![root@k8s-master01 ~]# kubectl logs -f hello-goodbye-run-hello-pod -c step-echo
Hello World
2.4 常用Task
2.4.1 代码拉取Task
比如想要拉取代码,可以使用 git-clone 这个 task:https://hub.tekton.dev/tekton/task/gitclone
# 接下来创建该 Task:
[root@k8s-master01 ~]# curl -o git-clone.yaml https://raw.githubusercontent.com/tektoncd/catalog/main/task/git-clone/0.6/git-clone.yaml[root@k8s-master01 ~]# kubectl apply -f git-clone.yaml
[root@k8s-master01 ~]# kubectl get task
NAME AGE
git-clone 4s
首先需要用到的 workspace 是 output,下载的代码会保存在该 workspace。接下来给 tekton
# 创建一个专用的用来存储代码及工作目录的 PVC:
[root@k8s-master01 ~]# vim tekton-workspace-pvc.yaml
[root@k8s-master01 ~]# cat tekton-workspace-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: tekton-workspacenamespace: defaultlabels: {}annotations: {}
spec:resources:requests:storage: 100GivolumeMode: FilesystemstorageClassName: nfs-csiaccessModes:- ReadWriteMany[root@k8s-master01 ~]# kubectl create -f tekton-workspace-pvc.yaml
[root@k8s-master01 ~]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
tekton-workspace Bound pvc-f9240e7f-e667-401c-b5fe-db6cf7cfce9a 100Gi RWX nfs-csi <unset> 8s
# 接下来创建 TaskRun 拉取代码,并保存至该 PVC:
[root@k8s-master01 ~]# vim 04-taskrun-git-clone.yaml
[root@k8s-master01 ~]# cat 04-taskrun-git-clone.yaml
apiVersion: tekton.dev/v1
kind: TaskRun
metadata:name: git-clone-run # taskrun name
spec:workspaces:- name: outputpersistentVolumeClaim:claimName: tekton-workspacetaskRef:name: git-clone # task nameparams:- name: urlvalue: "https://gitee.com/dukuan/krm.git"- name: gitInitImagevalue: "crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/git-init:v0.29.0"- name: revisionvalue: main[root@k8s-master01 ~]# kubectl create -f 04-taskrun-git-clone.yaml
[root@k8s-master01 ~]# kubectl get taskrun
NAME SUCCEEDED REASON STARTTIME COMPLETIONTIME
git-clone-run True Succeeded 75s 7s[root@k8s-master01 ~]# kubectl get po
NAME READY STATUS RESTARTS AGE
git-clone-run-pod 0/1 Completed 0 72s
# 在 PVC 中查看数据:
[root@habor ~]# ll /data/nfs/pvc-f9240e7f-e667-401c-b5fe-db6cf7cfce9a
total 112
-rw-r--r-- 1 root root 5632 Oct 25 15:19 deploy.md
-rw-r--r-- 1 root root 82769 Oct 25 15:19 image.png
drwxr-xr-x 2 root root 4096 Oct 25 15:19 images
-rw-r--r-- 1 root root 4726 Oct 25 15:19 krm.yaml
-rw-r--r-- 1 root root 1064 Oct 25 15:19 LICENSE
-rw-r--r-- 1 root root 2771 Oct 25 15:19 README.md
Tekton Dashboard上面可以看到拉取的日志

2.4.2 拉取私有仓库代码
如果需要拉取私有仓库的代码,需要配置 SSH 的私钥并挂载到 Task。
# 首先生成 SSH 的密钥:
[root@k8s-master01 ~]# ssh-keygen -t rsa -C "1773464408@qq.com"# 查看公钥:
[root@k8s-master01 ~]# cat .ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDJTvF8NDvX/SKxS1z7j/SdqInCB2A3kfuRsOn3c/j962H+yN/0SfRXShaSpHzvrVPNQMtiEr4gFQ4UKgpcWUyyDeaCyYRDrUxZ96IDoY2KoTser5o9dtfmnYaKeP7koewINFesPj59Ur2pATks7SYoT59o7UGKrShcedgo23dI0pvJmNaYKOlLeYocbaCY31g76SCZ44jVmv92smU9L+rVS15FT6hTjMO194vflbhLQ5p5nyaWRORYHuHxTbe5YHpMmEQquLnvMvhAr9ngzCdeMNyVtpQx2ZcbR9YmB6WiL6VsGqyPywkb2rU9G4I0qW8bg+aI1tTnjlXCEGKCNV7rxqNx3h0vRADTlYpKeeh1Ysrt+5+CibYJj3KNfY1dXLFOCCDc6YIFRX/0jFk/7RHe2r7knsqajc1ytt0BdDYb6GBeckDhIL4WGiKI3LtHI4LdXammTAf9wwIv7ZEEyuzAHd71AKx/JTKcA+jmGGy64j2i8Xzpk9UyWuhhxOwwJKc= 1773464408@qq.com
接下来把公钥导入到代码仓库的 SSH 公钥中:




# 创建 Secret 保存私钥,用于 Tekton 挂载:
[root@k8s-master01 ~]# kubectl create secret generic git-ssh-auth --from-file=id_rsa=/root/.ssh/id_rsa --dry-run=client -oyaml > git-secret.yaml# 编辑该 Secret 添加 config 字段:
[root@k8s-master01 ~]# vim git-secret.yaml
data:config: U3RyaWN0SG9zdEtleUNoZWNraW5nIG5vIApVc2VyS25vd25Ib3N0c0ZpbGUgL2Rldi9udWxsCg==
...# 创建 Secret:
[root@k8s-master01 ~]# kubectl create -f git-secret.yaml
[root@k8s-master01 ~]# kubectl get secret
NAME TYPE DATA AGE
git-ssh-auth Opaque 2 13s
创建 TaskRun,拉取私有仓库代码:
[root@k8s-master01 ~]# vim 04-taskrun-git-clone-private.yaml
[root@k8s-master01 ~]# cat 04-taskrun-git-clone-private.yaml
apiVersion: tekton.dev/v1
kind: TaskRun
metadata:name: git-clone-private-run # taskrun name
spec:workspaces:- name: outputpersistentVolumeClaim:claimName: tekton-workspace- name: ssh-directorysecret:secretName: git-ssh-authtaskRef:name: git-clone # task nameparams:- name: urlvalue: "git@192.168.200.55:kubernetes/test.git"- name: gitInitImagevalue: "crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/git-init:v0.29.0"- name: revisionvalue: main[root@k8s-master01 ~]# kubectl create -f 04-taskrun-git-clone-private.yaml
[root@k8s-master01 ~]# kubectl get taskrun
NAME SUCCEEDED REASON STARTTIME COMPLETIONTIME
git-clone-private-run True Succeeded 30s 23s[root@k8s-master01 ~]# kubectl get po
NAME READY STATUS RESTARTS AGE
git-clone-private-run-pod 0/1 Completed 0 32s
Tekton Dashboard上面可以看到拉取的日志

2.4.3 自定义工作目录
上述定义了工作目录 PVC,但是拉取代码时,全部下载到了同一个目录,此时多个任务同时处理时会产生冲突,所以不同服务或者不同任务的工作目录应该独立。
此时可以在 TaskRun 的 PVC 中指定 subPath:
[root@k8s-master01 ~]# vim 05-taskrun-git-clone-subpath.yaml
[root@k8s-master01 ~]# cat 05-taskrun-git-clone-subpath.yaml
apiVersion: tekton.dev/v1
kind: TaskRun
metadata:name: git-clone-run-subpath # taskrun name
spec:workspaces:- name: outputpersistentVolumeClaim:claimName: tekton-workspacesubPath: "git-clone-run-subpath" # 指定目录taskRef:name: git-clone # task nameparams:- name: urlvalue: "https://gitee.com/dukuan/krm.git"- name: gitInitImagevalue: "crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/git-init:v0.29.0"- name: revisionvalue: main
指定 subPath 后,代码会下载到 PVC 的 git-clone-run-subpath 目录:
[root@k8s-master01 ~]# kubectl create -f 05-taskrun-git-clone-subpath.yaml [root@habor ~]# ll /data/nfs/pvc-f9240e7f-e667-401c-b5fe-db6cf7cfce9a
total 8
drwxr-xr-x 4 root root 114 Oct 25 15:54 git-clone-run-subpath
-rw-r--r-- 1 root root 6154 Oct 25 15:48 README.md
除了上述手动指定工作目录,也可以使用 Tekton 的内置变量自动配置 subPath,比如使用
PipelineRun 和 TaskRun 的名字作为子目录,随后会在 PipelineRun 中演示,所有可用的变量可以在 https://tekton.dev/docs/pipelines/variables/#variables-available-in-a-pipeline 中获取。
2.4.4 初始化Task
下载代码后,可能需要进行一些初始化操作,比如获取 Commit 信息、生成镜像的 TAG 等。
此时可以单独创建一个用来初始化的 Task:
[root@k8s-master01 ~]# vim 06-init-task.yaml
[root@k8s-master01 ~]# cat 06-init-task.yaml
apiVersion: tekton.dev/v1
kind: Task
metadata:name: init
spec:description: "生成初始化信息"# 定义一个 workspace,后续需要把拉取代码的工作目录挂载到该 workspaceworkspaces:- name: sourcesteps:- name: readimage: registry.cn-beijing.aliyuncs.com/dotbalo/git-init:v0.29.0# 指定当前 task 的工作目录为 workspace 的路径workingDir: $(workspaces.source.path)script: |#!/usr/bin/env shlsln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime ; echo "Asia/Shanghai" > /etc/timezoneCUR_DATE=`TZ='Asia/Shanghai' date '+%Y%m%d-%H%M%S'`# 获取本次提交的 Commit 信息COMMIT_MESSAGE=`git log -1 --pretty=format:'%h : %an %s'`CUR_DATE=`date '+%Y%m%d-%H%M%S'`SHORT_COMMIT=`git log -n 1 --pretty=format:'%h'`TAG=`echo "${CUR_DATE}-${SHORT_COMMIT}"`echo $TAG[root@k8s-master01 ~]# kubectl create -f 06-init-task.yaml
[root@k8s-master01 ~]# kubectl get task
NAME AGE
...
init 5s
接下来创建一个 TaskRun 执行该 Task
[root@k8s-master01 ~]# vim 06-init-taskrun.yaml
[root@k8s-master01 ~]# cat 06-init-taskrun.yaml
apiVersion: tekton.dev/v1
kind: TaskRun
metadata:name: init-taskrun # taskrun name
spec:workspaces:- name: sourcepersistentVolumeClaim:claimName: tekton-workspacesubPath: "git-clone-run-subpath"taskRef:name: init # task name[root@k8s-master01 ~]# kubectl create -f 06-init-taskrun.yaml
[root@k8s-master01 ~]# kubectl get taskrun
NAME SUCCEEDED REASON STARTTIME COMPLETIONTIME
...
init-taskrun True Succeeded 52s 29s
创建该 TaskRun 后,查看该 Pod 的日志:
[root@k8s-master01 ~]# kubectl get po
NAME READY STATUS RESTARTS AGE
...
init-taskrun-pod 0/1 Completed 0 58s[root@k8s-master01 ~]# kubectl logs -f init-taskrun-pod -c step-read
LICENSE
README.md
deploy.md
image.png
images
krm.yaml
20251025-081930-a6629ac
2.4.5 结果存储results
有时候在一个 task 执行某个操作后,需要记录一下结果,然后根据这个结果去判定是否应
该继续执行,或者要使用这个结果去执行其它的动作。比如根据上个 task 生成的 tag 进行镜像的构建,此时由初始化生成的 tag 需要传递到构建镜像的 task,这个需求可以使用 results 去实现。
Results 一般用于存储各个过程产生的临时数据,比如由初始化 task 产生的数据,可以保留在 results 中,其他 task 可以通过 results 获取数据。
接下来修改初始化 Task,添加 results,把 tag 结果保存:
[root@k8s-master01 ~]# vim 06-init-task-res.yaml
[root@k8s-master01 ~]# cat 06-init-task-res.yaml
apiVersion: tekton.dev/v1
kind: Task
metadata:name: init
spec:description: "生成初始化信息"# 定义一个 workspace,后续需要把拉取代码的工作目录挂载到该 workspaceworkspaces:- name: sourceresults: # 添加tag- name: tagdescription: result for tagsteps:- name: readimage: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/git-init:v0.29.0# 指定当前 task 的工作目录为 workspace 的路径workingDir: $(workspaces.source.path)script: |#!/usr/bin/env shls# 获取本次提交的 Commit 信息COMMIT_MESSAGE=`git log -1 --pretty=format:'%h : %an %s'`CUR_DATE=`date '+%Y%m%d-%H%M%S'`SHORT_COMMIT=`git log -n 1 --pretty=format:'%h'`TAG=`echo "${CUR_DATE}-${SHORT_COMMIT}"`echo $TAG# 把 TAG 的值,写入到 results 中# tag 是结果的变量名,可以自定义# results 和 path 是固定格式echo $TAG | tee $(results.tag.path)[root@k8s-master01 ~]# kubectl replace -f 06-init-task-res.yaml
保存后的 results,可以在 Pipeline 中使用如下方式获取:
params:- name: tag# tasks 固定写法,init 为产生 result 的 task,tag 是 result 名字value: $(tasks.init.results.tag)
2.4.6 串联多任务Pipelines
接下来创建一个 Pipeline,结合上述测试的 task,进行联合工作,并且使用 results 传递数据。说先创建一个额外的 task,用来接收 tag 参数并展示:
[root@k8s-master01 ~]# vim 07-show-tag-task.yaml
[root@k8s-master01 ~]# cat 07-show-tag-task.yaml
apiVersion: tekton.dev/v1
kind: Task
metadata:name: show-tag
spec:description: Read and display TAG.# 通过 params 获取 pipeline 传递过来的 results 值params:- name: tagsteps:- name: readimage: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/alpine:3.9-tomcatscript: |#!/usr/bin/env shecho $(params.tag)[root@k8s-master01 ~]# kubectl create -f 07-show-tag-task.yaml
接下来创建一个 Pipeline,把各个 task 串在一起:
[root@k8s-master01 ~]# vim 07-pipeline-git-init-show.yaml
[root@k8s-master01 ~]# cat 07-pipeline-git-init-show.yaml
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:name: git-init-show
spec:description: |下载代码,初始化并存储数据.# 以下为 pipeline 可以接收的参数,使用 pipelineRun 可以进行传参params:- name: url # 用于接收代码地址type: stringdescription: The git repo URL to clone from.- name: gitInitImagetype: string# 配置一个默认值后续 Run 的时候就不需要再次传递default: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/git-init:v0.29.0# 定义 pipeline 的 workspaceworkspaces:- name: share-data # 配置一个 workspace 保留共享数据description: |This workspace contains the cloned repo files, so they can be readby the next task.# 拉取代码 ssh 配置- name: ssh-directorydescription: My ssh credentials# 定义该 pipeline 指定的 tasktasks:- name: fetch-sourcetaskRef:name: git-cloneworkspaces: # 把 pipeline 的 share-data workspace 挂载到 git-clone 的 output 的 workspace- name: outputworkspace: share-data# 把接收到的 ssh-directory 传递给 task 的 ssh-directory- name: ssh-directoryworkspace: ssh-directory# 传递给 task 的参数params:- name: urlvalue: $(params.url) # 从 pipeline 的 params 获取参数并传递- name: gitInitImagevalue: $(params.gitInitImage)- name: init# 等代码拉取 task 结束后执行初始化runAfter: ["fetch-source"]taskRef:name: initworkspaces:- name: sourceworkspace: share-data- name: show-tag# 等待 init 结束获取 tag 的值runAfter: ["init"]taskRef:name: show-tagparams:- name: tag# 通过$(tasks.生产 result 的 task 的名字.results.result 名字)获取 result 结果value: $(tasks.init.results.tag)[root@k8s-master01 ~]# kubectl create -f 07-pipeline-git-init-show.yaml
接下来创建 pipelineRun:
[root@k8s-master01 ~]# cat 07-pipelinerun-git-init-show.yaml
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:# 自动生成名字generateName: clone-and-init
spec:pipelineRef:name: git-init-show# 定义 workspaceworkspaces:# 把 K8s 的 PVC 挂载到 shared-data workspace- name: share-datapersistentVolumeClaim:claimName: tekton-workspace# 使用 pipelineRun 的名字作为子目录subPath: $(context.pipelineRun.name)# 把 K8s 的 secret 挂载到 git-credentials workspace- name: ssh-directorysecret:secretName: git-ssh-auth# 传递参数给 pipelineparams:- name: urlvalue: git@192.168.200.55:kubernetes/test.git- name: revisionvalue: "main"[root@k8s-master01 ~]# kubectl create -f 07-pipelinerun-git-init-show.yaml
# 查看该 pipelineRun 创建的 taskRun:
[root@k8s-master01 ~]# kubectl get taskrun | grep clone-and-init
clone-and-init8zwgv-fetch-source True Succeeded 2m3s 116s
clone-and-init8zwgv-init True Succeeded 116s 108s
clone-and-init8zwgv-show-tag True Succeeded 108s 102s# 查看创建的 Pod:
[root@k8s-master01 ~]# kubectl get po | grep clone-and-init
clone-and-init8zwgv-fetch-source-pod 0/1 Completed 0 2m15s
clone-and-init8zwgv-init-pod 0/1 Completed 0 2m8s
clone-and-init8zwgv-show-tag-pod 0/1 Completed 0 2m
Tekton Dashboard上面可以看到执行动作

2.4.7 代码构建Task
上述任务已经实现了代码下载、初始化和数据传递的功能,接下来再添加代码构建的 Task。需要注意构建任务,针对不同的语言需要的环境和命令是不同的,所以该 Task 需要从参数获取构建命令和构建的基础镜像:
[root@k8s-master01 ~]# vim 08-task-build.yaml
[root@k8s-master01 ~]# cat 08-task-build.yaml
apiVersion: tekton.dev/v1
kind: Task
metadata:name: build
spec:description: Code Buildworkspaces:- name: sourceparams: # 参数也可以大写- name: BUILD_COMMAND- name: BUILD_IMAGEsteps:- name: buildimage: $(params.BUILD_IMAGE)workingDir: $(workspaces.source.path)script: |#!/usr/bin/env shpwdlsecho $(params.BUILD_COMMAND)$(params.BUILD_COMMAND)[root@k8s-master01 ~]# kubectl create -f 08-task-build.yaml
接下来把该 Task 添加到 Pipeline 中:
[root@k8s-master01 ~]# vim 08-pipeline-git-init-build.yaml
[root@k8s-master01 ~]# cat 08-pipeline-git-init-build.yaml
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:name: git-init-build
spec:description: |下载代码,初始化并存储数据.# 以下为 pipeline 可以接收的参数,使用 pipelineRun 可以进行传参params:- name: url # 用于接收代码地址type: stringdescription: The git repo URL to clone from.- name: gitInitImagetype: string# 配置一个默认值后续 Run 的时候就不需要再次传递default: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/git-init:v0.29.0- name: BUILD_IMAGEtype: stringdefault: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/alpine:3.9-tomcat- name: BUILD_COMMANDtype: stringdefault: ls# 定义 workspaceworkspaces:- name: share-data # 配置一个 workspace 保留共享数据description: |This workspace contains the cloned repo files, so they can be read by the next task.# 拉取代码 ssh 配置- name: ssh-directorydescription: My ssh credentials# 定义改 pipeline 指定的 tasktasks:- name: fetch-sourcetaskRef:name: git-cloneworkspaces:- name: outputworkspace: share-data# 把接收到的 ssh-directory 传递给 task 的 ssh-directory- name: ssh-directoryworkspace: ssh-directory# 传递给 task 的参数params:- name: urlvalue: $(params.url) # 从 pipeline 的 params 获取参数并传递- name: gitInitImagevalue: $(params.gitInitImage)- name: init# 等代码拉取 task 结束后执行初始化runAfter: ["fetch-source"]taskRef:name: initworkspaces:- name: sourceworkspace: share-data- name: build # 代码下载后即可开始编译runAfter: ["fetch-source"]taskRef:name: buildworkspaces:- name: sourceworkspace: share-dataparams:- name: BUILD_COMMANDvalue: $(params.BUILD_COMMAND)- name: BUILD_IMAGEvalue: $(params.BUILD_IMAGE)[root@k8s-master01 ~]# kubectl create -f 08-pipeline-git-init-build.yaml
接下来创建 pipelineRun:
[root@k8s-master01 ~]# vim 08-pipelinerun-git-init-build.yaml
[root@k8s-master01 ~]# cat 08-pipelinerun-git-init-build.yaml
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:# 自动生成名字generateName: clone-and-init
spec:pipelineRef:name: git-init-build# 定义 workspaceworkspaces:- name: share-datapersistentVolumeClaim:claimName: tekton-workspace# 使用 pipelineRun 的名字作为子目录subPath: $(context.pipelineRun.name)# 把 K8s 的 secret 挂载到 git-credentials workspace- name: ssh-directorysecret:secretName: git-ssh-auth# 传递参数给 pipelineparams:- name: urlvalue: git@192.168.200.55:kubernetes/vue-project.git- name: revisionvalue: "master"- name: BUILD_IMAGEvalue: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/node:16.17.0-apline-cnpm- name: BUILD_COMMANDvalue: |-cnpm installnpm run buildlsls dist[root@k8s-master01 ~]# kubectl create -f 08-pipelinerun-git-init-build.yaml
Tekton Dashboard上面可以看到执行动作

2.4.8 镜像构建Task
上述已经执行了代码构建,并且生成了产物,接下来可以创建一个 Kaniko 的 Task,用于构建镜像和上传镜像,同时记录镜像地址。
首先创建 Secret 记录 docker 的配置文件:
[root@k8s-master01 ~]# docker login crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com
Usernam
Error: Non-null Username Required
[root@k8s-master01 ~]# docker login crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com
Username: ywb1108
Password: WARNING! Your credentials are stored unencrypted in '/root/.docker/config.json'.
Configure a credential helper to remove this warning. See
https://docs.docker.com/go/credential-store/Login Succeeded[root@k8s-master01 ~]# ls ~/.docker/config.json
/root/.docker/config.json# 创建 Secret:
[root@k8s-master01 ~]# kubectl create secret generic docker-credentials --from-file=/root/.docker/config.json
接下来创建一个 Kaniko Task:
[root@k8s-master01 ~]# vim 09-task-kaniko.yaml
[root@k8s-master01 ~]# cat 09-task-kaniko.yaml
apiVersion: tekton.dev/v1
kind: Task
metadata:name: kanikolabels:app.kubernetes.io/version: "0.6"annotations:tekton.dev/pipelines.minVersion: "0.17.0"tekton.dev/categories: Image Buildtekton.dev/tags: image-buildtekton.dev/displayName: "Build and upload container image using Kaniko"tekton.dev/platforms: "linux/amd64,linux/arm64,linux/ppc64le"
spec:description: >-This Task builds a simple Dockerfile with kaniko and pushes to a registry.This Task stores the image name and digest as results, allowing Tekton Chains to pick up that an image was built & sign it.params:- name: IMAGE_URLtype: string- name: DOCKERFILEdescription: Path to the Dockerfile to build.default: ./Dockerfile- name: CONTEXTdescription: The build context used by Kaniko.default: ./- name: EXTRA_ARGStype: arraydefault: []- name: BUILDER_IMAGEdescription: The image on which builds will run (default latest)default: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/executor:v1.22.0workspaces:- name: sourcedescription: Holds the context and Dockerfile# 挂载 docker 的配置文件,用于访问镜像仓库- name: docker-credentialsdescription: Includes a docker `config.json`optional: truemountPath: /kaniko/.dockerresults:- name: IMAGE_URLdescription: URL of the image just built.steps:- name: build-and-pushworkingDir: $(workspaces.source.path)image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/kaniko-executor:debugscript: |executor -c . --insecure --skip-tls-verify -d $(params.IMAGE_URL)securityContext:runAsUser: 0- name: write-urlimage: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/git-init:v0.29.1script: |set -eimage="$(params.IMAGE_URL)"echo -n "${image}" | tee "$(results.IMAGE_URL.path)"[root@k8s-master01 ~]# kubectl create -f 09-task-kaniko.yaml
接下来创建 Dockerfile,放置于代码根目录:

新建 Pipeline 添加镜像构建 Task:
[root@k8s-master01 ~]# vim 09-pipeline-git-init-build-kaniko.yaml
[root@k8s-master01 ~]# cat 09-pipeline-git-init-build-kaniko.yaml
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:name: git-init-build-kaniko
spec:description: |下载代码,初始化并存储数据.# 以下为 pipeline 可以接收的参数,使用 pipelineRun 可以进行传参params:- name: url # 用于接收代码地址type: stringdescription: The git repo URL to clone from.- name: revisiontype: string- name: gitInitImagetype: string# 配置一个默认值后续 Run 的时候就不需要再次传递default: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/git-init:v0.29.0- name: BUILD_IMAGEtype: stringdefault: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/alpine:3.9-tomcat- name: BUILD_COMMANDtype: stringdefault: ls# 添加用于镜像的参数- name: DOCKERFILEtype: stringdefault: ./Dockerfile- name: REGISTRYtype: string- name: REPOSTORYtype: string- name: IMAGE_NAMEtype: string# 定义 workspaceworkspaces:- name: share-data # 配置一个 workspace 保留共享数据description: |This workspace contains the cloned repo files, so they can be read by the next task.# 拉取代码 ssh 配置- name: ssh-directorydescription: My ssh credentials# 添加 docker 认证- name: docker-credentialsdescription: docker credentials# 定义改 pipeline 指定的 tasktasks:- name: fetch-sourcetaskRef:name: git-cloneworkspaces:- name: outputworkspace: share-data# 把接收到的 ssh-directory 传递给 task 的 ssh-directory- name: ssh-directoryworkspace: ssh-directory# 传递给 task 的参数params:- name: urlvalue: $(params.url) # 从 pipeline 的 params 获取参数并传递- name: gitInitImagevalue: $(params.gitInitImage)- name: revisionvalue: $(params.revision)- name: init# 等代码拉取 task 结束后执行初始化runAfter: ["fetch-source"]taskRef:name: initworkspaces:- name: sourceworkspace: share-data- name: buildrunAfter: ["fetch-source"]taskRef:name: buildworkspaces:- name: sourceworkspace: share-dataparams:- name: BUILD_COMMANDvalue: $(params.BUILD_COMMAND)- name: BUILD_IMAGEvalue: $(params.BUILD_IMAGE)# 添加 kaniko task- name: kanikorunAfter: ["build"]taskRef:name: kanikoworkspaces:- name: sourceworkspace: share-data- name: docker-credentialsworkspace: docker-credentialsparams:- name: IMAGE_URLvalue: $(params.REGISTRY)/$(params.REPOSTORY)/$(params.IMAGE_NAME):$(tasks.init.results.tag)[root@k8s-master01 ~]# kubectl create -f 09-pipeline-git-init-build-kaniko.yaml
创建 PipelineRun 执行构建:
[root@k8s-master01 ~]# vim 09-pipelinerun-git-init-build-kaniko.yaml
[root@k8s-master01 ~]# cat 09-pipelinerun-git-init-build-kaniko.yaml
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:# 自动生成名字generateName: build-push
spec:pipelineRef:name: git-init-build-kaniko# 定义 workspaceworkspaces:- name: share-datapersistentVolumeClaim:claimName: tekton-workspace# 使用 pipelineRun 的名字作为子目录subPath: $(context.pipelineRun.name)# 把 K8s 的 secret 挂载到 git-credentials workspace- name: ssh-directorysecret:secretName: git-ssh-auth- name: docker-credentialssecret:secretName: docker-credentials# 传递参数给 pipelineparams:- name: urlvalue: git@192.168.200.55:kubernetes/vue-project.git- name: revisionvalue: "tekton"- name: BUILD_IMAGEvalue: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/node:16.17.0-apline-cnpm- name: BUILD_COMMANDvalue: |-cnpm installnpm run buildlsls dist- name: REGISTRYvalue: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com- name: REPOSTORYvalue: ywb01- name: IMAGE_NAMEvalue: vue-project[root@k8s-master01 ~]# kubectl create -f 09-pipelinerun-git-init-build-kaniko.yaml
Tekton Dashboard上面可以看到执行动作

阿里云镜像平台
![![image.png-236.2kB][12]](https://i-blog.csdnimg.cn/direct/d5f8f2a70f9e494faa7b11713f8e1caf.png)
2.4.9 服务发版Task
最后就可以通过一个发版的 Task,把最新的镜像发布到 Kubernetes。
首先创建一个 kubeconfig 的 secret:
[root@k8s-master01 ~]# kubectl create secret generic kubeconfig --from-file=study-kubeconfig=/root/.kube/config
接下来创建一个测试的 Deployment:
[root@k8s-master01 ~]# kubectl create deploy vue-project --image=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/vue-project:20251025-135923-e929446
接下创建一个用于部署的 Task:
[root@k8s-master01 ~]# vim 10-task-deploy.yaml
[root@k8s-master01 ~]# cat 10-task-deploy.yaml
apiVersion: tekton.dev/v1
kind: Task
metadata:name: deploy
spec:description: deploy to kubernetes by kubectlworkspaces:- name: kubeconfigmountPath: /mnt/kubeconfigparams:- name: IMAGE_URLtype: string- name: NAMESPACEtype: stringdefault: default- name: DEPLOY_NAMEtype: string- name: CONTAINER_NAMEtype: string- name: KUBECONFIG_PATHtype: stringsteps:- name: deployimage: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/kubectl:devopsscript: |pwdls /mnt/kubeconfigecho "Deploy version: $(params.IMAGE_URL)"echo "kubectl --kubeconfig /mnt/kubeconfig/$(params.KUBECONFIG_PATH) -n $(params.NAMESPACE) set image deploy $(params.DEPLOY_NAME) $(params.CONTAINER_NAME)=$(params.IMAGE_URL)"kubectl --kubeconfig /mnt/kubeconfig/$(params.KUBECONFIG_PATH) -n $(params.NAMESPACE) set image deploy $(params.DEPLOY_NAME) $(params.CONTAINER_NAME)=$(params.IMAGE_URL)kubectl --kubeconfig /mnt/kubeconfig/$(params.KUBECONFIG_PATH) -n $(params.NAMESPACE) get po[root@k8s-master01 ~]# kubectl create -f 10-task-deploy.yaml
Pipeline 添加发版的 Task:
[root@k8s-master01 ~]# vim 10-pipeline-git-init-build-deploy.yaml
[root@k8s-master01 ~]# cat 10-pipeline-git-init-build-deploy.yaml
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:name: deploy
spec:description: |下载代码,初始化并存储数据.# 以下为 pipeline 可以接收的参数,使用 pipelineRun 可以进行传参params:- name: url # 用于接收代码地址type: stringdescription: The git repo URL to clone from.- name: revisiontype: string- name: gitInitImagetype: string# 配置一个默认值后续 Run 的时候就不需要再次传递default: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/git-init:v0.29.0- name: BUILD_IMAGEtype: stringdefault: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/alpine:3.9-tomcat- name: BUILD_COMMANDtype: stringdefault: ls# 添加用于镜像的参数- name: DOCKERFILEtype: stringdefault: ./Dockerfile- name: REGISTRYtype: string- name: REPOSTORYtype: string- name: IMAGE_NAMEtype: string- name: NAMESPACEtype: stringdefault: default- name: DEPLOY_NAMEtype: string- name: CONTAINER_NAMEtype: string- name: KUBECONFIG_PATHtype: string# 定义 workspaceworkspaces:- name: share-data # 配置一个 workspace 保留共享数据description: |This workspace contains the cloned repo files, so they can be read by the next task.# 拉取代码 ssh 配置- name: ssh-directorydescription: My ssh credentials# 添加 docker 认证- name: docker-credentialsdescription: docker credentials- name: kubeconfigdescription: kubernetes kubeconfig# 定义改 pipeline 指定的 tasktasks:- name: fetch-sourcetaskRef:name: git-cloneworkspaces:- name: outputworkspace: share-data# 把接收到的 ssh-directory 传递给 task 的 ssh-directory- name: ssh-directoryworkspace: ssh-directory# 传递给 task 的参数params:- name: urlvalue: $(params.url) # 从 pipeline 的 params 获取参数并传递- name: gitInitImagevalue: $(params.gitInitImage)- name: revisionvalue: $(params.revision)- name: init# 等代码拉取 task 结束后执行初始化runAfter: ["fetch-source"]taskRef:name: initworkspaces:- name: sourceworkspace: share-data- name: buildrunAfter: ["fetch-source"]taskRef:name: buildworkspaces:- name: sourceworkspace: share-dataparams:- name: BUILD_COMMANDvalue: $(params.BUILD_COMMAND)- name: BUILD_IMAGEvalue: $(params.BUILD_IMAGE)# 添加 kaniko task- name: kanikorunAfter: ["build"]taskRef:name: kanikoworkspaces:- name: sourceworkspace: share-data- name: docker-credentialsworkspace: docker-credentialsparams:- name: IMAGE_URLvalue: $(params.REGISTRY)/$(params.REPOSTORY)/$(params.IMAGE_NAME):$(tasks.init.results.tag)# 添加 deploy task- name: deployrunAfter: ["build"]taskRef:name: deployworkspaces:- name: kubeconfigworkspace: kubeconfigparams:- name: IMAGE_URLvalue: $(params.REGISTRY)/$(params.REPOSTORY)/$(params.IMAGE_NAME):$(tasks.init.results.tag)- name: NAMESPACEvalue: $(params.NAMESPACE)- name: DEPLOY_NAMEvalue: $(params.DEPLOY_NAME)- name: CONTAINER_NAMEvalue: $(params.CONTAINER_NAME)- name: KUBECONFIG_PATHvalue: $(params.KUBECONFIG_PATH)[root@k8s-master01 ~]# kubectl create -f 10-pipeline-git-init-build-deploy.yaml
最后创建 pipelineRun 实现自动发版:
[root@k8s-master01 ~]# vim 10-pipelinerun-git-init-build-deploy.yaml
[root@k8s-master01 ~]# cat 10-pipelinerun-git-init-build-deploy.yaml
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:# 自动生成名字generateName: deploy
spec:pipelineRef:name: deploy# 定义 workspaceworkspaces:- name: share-datapersistentVolumeClaim:claimName: tekton-workspace# 使用 pipelineRun 的名字作为子目录subPath: $(context.pipelineRun.name)# 把 K8s 的 secret 挂载到 git-credentials workspace- name: ssh-directorysecret:secretName: git-ssh-auth- name: docker-credentialssecret:secretName: docker-credentials- name: kubeconfigsecret:secretName: kubeconfig# 传递参数给 pipelineparams:- name: urlvalue: git@192.168.200.55:kubernetes/vue-project.git- name: revisionvalue: "tekton"- name: BUILD_IMAGEvalue: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/node:16.17.0-apline-cnpm- name: BUILD_COMMANDvalue: |-cnpm installnpm run buildlsls dist- name: REGISTRYvalue: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com- name: REPOSTORYvalue: ywb01- name: IMAGE_NAMEvalue: vue-project- name: NAMESPACEvalue: default- name: DEPLOY_NAMEvalue: vue-project- name: CONTAINER_NAMEvalue: vue-project- name: KUBECONFIG_PATHvalue: study-kubeconfig[root@k8s-master01 ~]# kubectl create -f 10-pipelinerun-git-init-build-deploy.yaml
Tekton Dashboard上面可以看到执行动作

3、Tekton企业落地实战
3.1 GitLab 安装
GitLab 在企业内经常用于代码的版本控制,也是 DevOps 平台中尤为重要的一个工具。
3.1.1 关闭机器防火墙和 selinux
# 关闭防火墙
[root@gitlab ~]# systemctl disable --now firewalld
[root@gitlab ~]# systemctl disable --now dnsmasq# 关闭selinux
[root@gitlab ~]# setenforce 0
[root@gitlab ~]# sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/sysconfig/selinux
[root@gitlab ~]# sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config
3.1.2 安装gitlab
[root@gitlab ~]# wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el9/gitlab-ce-17.9.8-ce.0.el9.x86_64.rpm
[root@gitlab ~]# yum install gitlab-ce-17.9.8-ce.0.el9.x86_64.rpm -y
# 修改配置
[root@gitlab ~]# vim /etc/gitlab/gitlab.rb
[root@gitlab ~]# sed -n "32p;2346p" /etc/gitlab/gitlab.rb
external_url 'http://192.168.200.55' # 将 external_url 更改为自己的发布地址,可以是服务器的 IP,也可以是一个可被解析的域名
prometheus['enable'] = false # 关闭 Prometheus 插件(可选)# 更改完成后需要重新加载配置文件
[root@gitlab ~]# gitlab-ctl reconfigure
....
Notes:
Default admin account has been configured with following details:
Username: root
Password: You didn't opt-in to print initial root password to STDOUT.
Password stored to /etc/gitlab/initial_root_password. This file will be cleaned up in first reconfigure run after 24 hours.NOTE: Because these credentials might be present in your log files in plain text, it is highly recommended to reset the password following https://docs.gitlab.com/ee/security/reset_user_password.html#reset-your-root-password.gitlab Reconfigured!
之后可以通过 浏览器访 问 GitLab,账号 root,默认密码在/etc/gitlab/initial_root_password:

登录后,开启 import 功能,可以从外部仓库导入代码到 Gitlab:


最后记得点击保存

3.1.3 创建项目
1、创建一个测试项目,进行一些简单的测试。首先创建一个组:


组名为 kubernetes,类型为 Private,之后点击 Create group 即可:

之后在该组下创建一个 Project:

选择创建一个空的项目:

输入项目名称,然后点击 Create project 即可:

3.1.4 配置密钥
之后可以将 k8s-master 服务器(任意机器均可)的 key 导入到 GitLab
# 首先生成密钥(如有可以无需生成):
[root@k8s-master01 ~]# ssh-keygen -t rsa -C "1773464408@qq.com"# 将公钥的内容放在 GitLab 中即可:
[root@k8s-master01 ~]# cat .ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDJTvF8NDvX/SKxS1z7j/SdqInCB2A3kfuRsOn3c/j962H+yN/0SfRXShaSpHzvrVPNQMtiEr4gFQ4UKgpcWUyyDeaCyYRDrUxZ96IDoY2KoTser5o9dtfmnYaKeP7koewINFesPj59Ur2pATks7SYoT59o7UGKrShcedgo23dI0pvJmNaYKOlLeYocbaCY31g76SCZ44jVmv92smU9L+rVS15FT6hTjMO194vflbhLQ5p5nyaWRORYHuHxTbe5YHpMmEQquLnvMvhAr9ngzCdeMNyVtpQx2ZcbR9YmB6WiL6VsGqyPywkb2rU9G4I0qW8bg+aI1tTnjlXCEGKCNV7rxqNx3h0vRADTlYpKeeh1Ysrt+5+CibYJj3KNfY1dXLFOCCDc6YIFRX/0jFk/7RHe2r7knsqajc1ytt0BdDYb6GBeckDhIL4WGiKI3LtHI4LdXammTAf9wwIv7ZEEyuzAHd71AKx/JTKcA+jmGGy64j2i8Xzpk9UyWuhhxOwwJKc= 1773464408@qq.com
在 GitLab 找到 Profile:

之后在 SSH Keys 添加公钥:



添加后就可以在服务器上拉取代码:
[root@k8s-master01 ~]# yum install git -y
[root@k8s-master01 ~]# git config --global user.email 1773464408@qq.com
[root@k8s-master01 ~]# git config --global user.name "yunwei"
[root@k8s-master01 ~]# git clone git@192.168.200.55:kubernetes/test.git
3.2 Harbor
3.2.1 安装docker
# 添加docker的yum源配置文件
[root@harbor ~]# yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo# 安装docker
[root@harbor ~]# yum install docker-ce docker-ce-cli -y# 启动docker
[root@harbor ~]# systemctl daemon-reload && systemctl enable --now docker
3.2.2 配置docker-compose
# 设置软连接
[root@harbor ~]# ln -s /usr/libexec/docker/cli-plugins/docker-compose /usr/local/bin/[root@harbor ~]# docker-compose -v
Dcurl -L https://github.com/docker C/compose version v2.36.2# 批量停止harbor实例
docker-compose down
# 批量启动harbor实例
docker-compose up -d
3.2.3 安装 Harbor
# 下载到本地
[root@harbor ~]# wget https://github.com/goharbor/harbor/releases/download/v2.13.1/harbor-offline-installer-v2.13.1.tgz# 解压tar包
[root@harbor ~]# tar xf harbor-offline-installer-v2.13.1.tgz
[root@harbor ~]# cd harbor# 加载配置
[root@harbor harbor]# docker load -i harbor.v2.13.1.tar.gz # 修改 Harbor 默认配置文件
[root@harbor harbor]# cp harbor.yml.tmpl harbor.yml
[root@harbor harbor]# vim harbor.yml[root@harbor harbor]# sed -n "5p;10p;13,18p;47p;66p" harbor.yml
hostname: 192.168.200.53 port: 80
# https:# https port for harbor, default is 443# port: 443# The path of cert and key files for nginx# certificate: /your/certificate/path# private_key: /your/private/key/path
harbor_admin_password: Harbor12345
data_volume: /data/harbor
- hostname:Harbor 的访问地址,可以是域名或者 IP,生产推荐使用域名,并且带有证书
- https:域名证书的配置,生产环境需要配置权威证书供 Harbor 使用,否则需要添加
insecure-registry配置,由于是学习环境,所以本示例未配置证书- harbor_admin_password:账号密码按需修改即可,默认为 admin:Harbor12345
- data_volume:Harbor 的数据目录
# 创建 Harbor 数据目录并进行预配置:
[root@harbor harbor]# mkdir /data/harbor -p# 加载配置启动
[root@harbor harbor]# ./prepare# 执行安装:
[root@harbor harbor]# ./install.sh
web界面访问

登录后,创建一个项目

3.2.4 创建开机自启动脚本
[root@harbor harbor]# vim /etc/systemd/system/harbor.service
[root@harbor harbor]# cat /etc/systemd/system/harbor.service
[Unit]
Description=Harbor Service
After=docker.service
Requires=docker.service[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/usr/local/harbor
ExecStart=/usr/local/bin/docker-compose up -d
ExecStop=/usr/local/bin/docker-compose down
User=root[Install]
WantedBy=multi-user.target# 加上执行权限
[root@harbor harbor]# chmod +x /etc/systemd/system/harbor.service # 设置开机自启动
[root@harbor harbor]# systemctl daemon-reload
[root@harbor harbor]# systemctl enable harbor
3.2.5 docker 配置 insecure registry
如果配置不是 https 协议,所有的 Kubernetes 节点的 Docker 都需要添加 insecure-registries 配置
[root@harbor harbor]# vim /etc/docker/daemon.json
[root@harbor harbor]# cat /etc/docker/daemon.json
{"registry-mirrors": ["https://9upbt3ho.mirror.aliyuncs.com"],"insecure-registries": ["192.168.200.53"]
}
[root@harbor harbor]# systemctl daemon-reload
[root@harbor harbor]# systemctl restart docker
3.2.6 Containerd 配置 insecure registry (k8s节点)
如果 Kubernetes 集群采用的是 Containerd 作为的 Runtime,那么 Containerd 也需要配置 insecure registry。
首先生成 Containerd 的配置(如果已经生成过,请勿执行):
# containerd config default > /etc/containerd/config.toml
# 修改配置(所有k8s节点都要执行)
[root@k8s-master01 ~]# vim /etc/containerd/config.toml
[root@k8s-master01 ~]# sed -n "170,172p" /etc/containerd/config.toml [plugins."io.containerd.grpc.v1.cri".registry.mirrors][plugins."io.containerd.grpc.v1.cri".registry.mirrors."192.168.200.53"]endpoint = ["http://192.168.200.53"]# 重启服务
[root@k8s-master01 ~]# systemctl restart containerd# 需要把K8s所有的节点都需要进行更改
# config.toml并不是直接给ctr命令去使用的
# docker拉取的镜像和containerd没有任何关系
3.3 Tekton必备资源梳理
首先清理之前的测试数据:
[root@k8s-master01 ~]# kubectl delete -f .
[root@k8s-master01 ~]# kubectl delete pr --all
[root@k8s-master01 ~]# kubectl delete tr --all
3.3.1 代码拉取Task
比如想要拉取代码,可以使用 git-clone 这个 task:https://hub.tekton.dev/tekton/task/gitclone
# 接下来创建该 Task:
[root@k8s-master01 ~]# curl -o git-clone.yaml https://raw.githubusercontent.com/tektoncd/catalog/main/task/git-clone/0.6/git-clone.yaml[root@k8s-master01 ~]# kubectl apply -f git-clone.yaml
3.3.2 代码拉取 Secret
# 创建 Secret 保存私钥,用于 Tekton 挂载:
[root@k8s-master01 ~]# kubectl create secret generic git-ssh-auth --from-file=id_rsa=/root/.ssh/id_rsa --dry-run=client -oyaml > git-secret.yaml# 编辑该 Secret 添加 config 字段:
[root@k8s-master01 ~]# vim git-secret.yaml
data:config: U3RyaWN0SG9zdEtleUNoZWNraW5nIG5vIApVc2VyS25vd25Ib3N0c0ZpbGUgL2Rldi9udWxsCg==
...# 创建 Secret:
[root@k8s-master01 ~]# kubectl create -f git-secret.yaml
3.3.3 镜像仓库 Secret
# 首先登录 Harbor 仓库,已登录请忽略:
[root@k8s-master01 ~]# docker login 192.168.200.53# 创建镜像仓库认证的 Secret:
[root@k8s-master01 ~]# kubectl delete secret docker-credentials
[root@k8s-master01 ~]# kubectl create secret generic docker-credentials --from-file=/root/.docker/config.json
3.3.4 资源部署 Secret
# 之后创建一个 kubeconfig 的 secret:
[root@k8s-master01 ~]# kubectl create secret generic kubeconfig --from-file=study-kubeconfig=/root/.kube/config
3.3.5 Tekton 必备资源
接下来部署必需的 Task、Pipeline、PVC 等资源:
1、创建用于缓存的 PVC:
[root@k8s-master01 ~]# vim tekton-pvc.yaml
[root@k8s-master01 ~]# cat tekton-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: tekton-workspacenamespace: defaultlabels: {}annotations: {}
spec:resources:requests:storage: 100GivolumeMode: FilesystemstorageClassName: nfs-csiaccessModes:- ReadWriteMany
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: tekton-cachenamespace: defaultlabels: {}annotations: {}
spec:resources:requests:storage: 100GivolumeMode: FilesystemstorageClassName: nfs-csiaccessModes:- ReadWriteMany
2、初始化Task
[root@k8s-master01 ~]# vim init-task.yaml
[root@k8s-master01 ~]# cat init-task.yaml
apiVersion: tekton.dev/v1
kind: Task
metadata:name: init
spec:description: "生成初始化信息"# 定义一个 workspace,后续需要把拉取代码的工作目录挂载到该 workspaceworkspaces:- name: sourceresults: # 添加tag- name: tagdescription: result for tagsteps:- name: readimage: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/git-init:v0.29.0# 指定当前 task 的工作目录为 workspace 的路径workingDir: $(workspaces.source.path)script: |#!/usr/bin/env shls# 获取本次提交的 Commit 信息COMMIT_MESSAGE=`git log -1 --pretty=format:'%h : %an %s'`CUR_DATE=`date '+%Y%m%d-%H%M%S'`SHORT_COMMIT=`git log -n 1 --pretty=format:'%h'`TAG=`echo "${CUR_DATE}-${SHORT_COMMIT}"`echo $TAG# 把 TAG 的值,写入到 results 中# tag 是结果的变量名,可以自定义# results 和 path 是固定格式echo $TAG | tee $(results.tag.path)
3、把 Task 添加到 Pipeline 中,修改 Pipeline 添加缓存目录
[root@k8s-master01 ~]# vim pipeline-deploy.yaml
[root@k8s-master01 ~]# cat pipeline-deploy.yaml
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:name: deploy
spec:description: |下载代码,初始化并存储数据.# 以下为 pipeline 可以接收的参数,使用 pipelineRun 可以进行传参params:- name: url # 用于接收代码地址type: stringdescription: The git repo URL to clone from.- name: revisiontype: string- name: gitInitImagetype: string# 配置一个默认值后续 Run 的时候就不需要再次传递default: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/git-init:v0.29.0- name: BUILD_IMAGEtype: stringdefault: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/alpine:3.9-tomcat- name: BUILD_COMMANDtype: stringdefault: ls# 添加用于镜像的参数- name: DOCKERFILEtype: stringdefault: ./Dockerfile- name: REGISTRYtype: string- name: REPOSTORYtype: string- name: IMAGE_NAMEtype: string- name: NAMESPACEtype: stringdefault: default- name: DEPLOY_NAMEtype: string- name: CONTAINER_NAMEtype: string- name: KUBECONFIG_PATHtype: string- name: CACHE_DIRtype: stringdefault: /root/.m2# 定义 workspaceworkspaces:- name: share-data # 配置一个 workspace 保留共享数据description: |This workspace contains the cloned repo files, so they can be read by the next task.# 拉取代码 ssh 配置- name: ssh-directorydescription: My ssh credentials# 添加 docker 认证- name: docker-credentialsdescription: docker credentials- name: kubeconfigdescription: kubernetes kubeconfig# 定义改 pipeline 指定的 tasktasks:- name: fetch-sourcetaskRef:name: git-cloneworkspaces:- name: outputworkspace: share-data# 把接收到的 ssh-directory 传递给 task 的 ssh-directory- name: ssh-directoryworkspace: ssh-directory# 传递给 task 的参数params:- name: urlvalue: $(params.url) # 从 pipeline 的 params 获取参数并传递- name: gitInitImagevalue: $(params.gitInitImage)- name: revisionvalue: $(params.revision)- name: init# 等代码拉取 task 结束后执行初始化runAfter: ["fetch-source"]taskRef:name: initworkspaces:- name: sourceworkspace: share-data- name: buildrunAfter: ["fetch-source"]taskRef:name: buildworkspaces:- name: sourceworkspace: share-dataparams:- name: BUILD_COMMANDvalue: $(params.BUILD_COMMAND)- name: BUILD_IMAGEvalue: $(params.BUILD_IMAGE)- name: CACHE_DIRvalue: $(params.CACHE_DIR)# 添加 kaniko task- name: kanikorunAfter: ["build"]taskRef:name: kanikoworkspaces:- name: sourceworkspace: share-data- name: docker-credentialsworkspace: docker-credentialsparams:- name: IMAGE_URLvalue: $(params.REGISTRY)/$(params.REPOSTORY)/$(params.IMAGE_NAME):$(tasks.init.results.tag)# 添加 deploy task- name: deployrunAfter: ["build"]taskRef:name: deployworkspaces:- name: kubeconfigworkspace: kubeconfigparams:- name: IMAGE_URLvalue: $(params.REGISTRY)/$(params.REPOSTORY)/$(params.IMAGE_NAME):$(tasks.init.results.tag)- name: NAMESPACEvalue: $(params.NAMESPACE)- name: DEPLOY_NAMEvalue: $(params.DEPLOY_NAME)- name: CONTAINER_NAMEvalue: $(params.CONTAINER_NAME)- name: KUBECONFIG_PATHvalue: $(params.KUBECONFIG_PATH)
4、代码构建Task
[root@k8s-master01 ~]# vim task-build.yaml
[root@k8s-master01 ~]# cat task-build.yaml
apiVersion: tekton.dev/v1
kind: Task
metadata:name: build
spec:description: Code Buildworkspaces:- name: sourceparams: # 参数也可以大写- name: BUILD_COMMAND- name: BUILD_IMAGE- name: CACHE_DIRdefault: "/root/.m2"steps:- name: buildimage: $(params.BUILD_IMAGE)workingDir: $(workspaces.source.path)volumeMounts:- name: cache-volumemountPath: $(params.CACHE_DIR)script: |#!/usr/bin/env shpwdlsecho $(params.BUILD_COMMAND)$(params.BUILD_COMMAND)volumes:- name: cache-volumepersistentVolumeClaim:claimName: tekton-cache
5、创建一个 Kaniko Task
[root@k8s-master01 ~]# vim task-kaniko.yaml
[root@k8s-master01 ~]# cat task-kaniko.yaml
apiVersion: tekton.dev/v1
kind: Task
metadata:name: kanikolabels:app.kubernetes.io/version: "0.6"annotations:tekton.dev/pipelines.minVersion: "0.17.0"tekton.dev/categories: Image Buildtekton.dev/tags: image-buildtekton.dev/displayName: "Build and upload container image using Kaniko"tekton.dev/platforms: "linux/amd64,linux/arm64,linux/ppc64le"
spec:description: >-This Task builds a simple Dockerfile with kaniko and pushes to a registry.This Task stores the image name and digest as results, allowing Tekton Chains to pick up that an image was built & sign it.params:- name: IMAGE_URLtype: string- name: DOCKERFILEdescription: Path to the Dockerfile to build.default: ./Dockerfile- name: CONTEXTdescription: The build context used by Kaniko.default: ./- name: EXTRA_ARGStype: arraydefault: []- name: BUILDER_IMAGEdescription: The image on which builds will run (default latest)default: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/executor:v1.22.0workspaces:- name: sourcedescription: Holds the context and Dockerfile# 挂载 docker 的配置文件,用于访问镜像仓库- name: docker-credentialsdescription: Includes a docker `config.json`optional: truemountPath: /kaniko/.dockerresults:- name: IMAGE_URLdescription: URL of the image just built.steps:- name: build-and-pushworkingDir: $(workspaces.source.path)image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/kaniko-executor:debugscript: |executor -c . --insecure --skip-tls-verify -d $(params.IMAGE_URL)securityContext:runAsUser: 0- name: write-urlimage: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/git-init:v0.29.1script: |set -eimage="$(params.IMAGE_URL)"echo -n "${image}" | tee "$(results.IMAGE_URL.path)"
6、用于部署的 Task
[root@k8s-master01 ~]# vim task-deploy.yaml
[root@k8s-master01 ~]# cat task-deploy.yaml
apiVersion: tekton.dev/v1
kind: Task
metadata:name: deploy
spec:description: deploy to kubernetes by kubectlworkspaces:- name: kubeconfigmountPath: /mnt/kubeconfigparams:- name: IMAGE_URLtype: string- name: NAMESPACEtype: stringdefault: default- name: DEPLOY_NAMEtype: string- name: CONTAINER_NAMEtype: string- name: KUBECONFIG_PATHtype: stringsteps:- name: deployimage: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/kubectl:devopsscript: |pwdls /mnt/kubeconfigecho "Deploy version: $(params.IMAGE_URL)"echo "kubectl --kubeconfig /mnt/kubeconfig/$(params.KUBECONFIG_PATH) -n $(params.NAMESPACE) set image deploy $(params.DEPLOY_NAME) $(params.CONTAINER_NAME)=$(params.IMAGE_URL)"kubectl --kubeconfig /mnt/kubeconfig/$(params.KUBECONFIG_PATH) -n $(params.NAMESPACE) set image deploy $(params.DEPLOY_NAME) $(params.CONTAINER_NAME)=$(params.IMAGE_URL)kubectl --kubeconfig /mnt/kubeconfig/$(params.KUBECONFIG_PATH) -n $(params.NAMESPACE) get po
3.3.6 安装 Tekton 必备资源
[root@k8s-master01 ~]# kubectl create -f .# 查看必备的 Task:
[root@k8s-master01 ~]# kubectl get task
NAME AGE
build 13s # 代码构建 Task
deploy 12s # 服务部署 Task
git-clone 12s # 代码下载 Task
init 13s # 初始化 Task
kaniko 12s # 镜像制作 Task# 查看必备的 Pipeline:
[root@k8s-master01 ~]# kubectl get pipeline
NAME AGE
deploy 25s # 贯穿各个 Task 的统一 Pipeline
3.4 Tekton自动化部署Java应用
3.4.1 创建 Java 测试用例
示例项目可以从 https://gitee.com/dukuan/spring-boot-project.git 找到该项目(也可以使用公司的 Java 项目也是一样的)。
接下来将该项目导入到自己的 GitLab 中。首先找到之前创建的 Kubernetes 组

然后点击 New Project:

选择 Import Project:

点击 Repo by URL,在 Git repository URL 输入示例地址,然后点击 Create Project 即可:


导入后,如下所示:

3.4.2 定义 Dockerfile
在执行流水线过程时,需要将代码的编译产物做成镜像。而本次示例是 Java 项目,只需要把 Jar 包放在有 Jre 环境的镜像中,然后启动该 Jar 包即可:
# 基础镜像可以按需修改,可以更改为公司自有镜像
FROM crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/jre:8u211-data
# jar 包名称改成实际的名称,本示例为 spring-cloud-eureka-0.0.1-SNAPSHOT.jar
COPY target/spring-cloud-eureka-0.0.1-SNAPSHOT.jar ./
# 启动 Jar 包
CMD java -jar spring-cloud-eureka-0.0.1-SNAPSHOT.jar
该该 Dockerfile 放置于代码的根目录即可。

3.4.3 定义 Kubernetes 资源
本示例在 GitLab 创建的 Group 为 kubernetes,可以将其认为是一个项目,同一个项目可以
部署至 Kubernetes 集群中同一个 Namespace 中,本示例为 kubernetes 命名空间。由于使用的是私有仓库,因此也需要先配置拉取私有仓库镜像的密钥:
[root@k8s-master01 ~]# kubectl create ns kubernetes[root@k8s-master01 ~]# kubectl create secret docker-registry harborkey --docker-server=192.168.200.53 --docker-username=admin --docker-password=Harbor12345 --docker-email=1773464408@qq.com -n kubernetes
配置该应用的 Deployment:
[root@k8s-master01 ~]# vim spring-boot-project.yaml
[root@k8s-master01 ~]# cat spring-boot-project.yaml
---
apiVersion: v1
kind: Service
metadata:creationTimestamp: nulllabels:app: spring-boot-projectname: spring-boot-projectnamespace: kubernetes
spec:ports: # 端口按照实际情况进行修改- name: webport: 8761protocol: TCPtargetPort: 8761selector:app: spring-boot-projectsessionAffinity: Nonetype: ClusterIP
status:loadBalancer: {}
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:creationTimestamp: nullname: spring-boot-projectnamespace: kubernetes
spec:rules:- host: spring-boot-project.test.comhttp:paths:- backend:service:name: spring-boot-projectport:number: 8761path: /pathType: ImplementationSpecific
status:loadBalancer: {}
---
apiVersion: apps/v1
kind: Deployment
metadata:creationTimestamp: nulllabels:app: spring-boot-project # Deployment 标签,和流水线的 set -l 一致name: spring-boot-project # Deployment 名称namespace: kubernetes
spec:replicas: 1selector:matchLabels:app: spring-boot-project # Pod 的标签strategy:rollingUpdate:maxSurge: 1maxUnavailable: 0type: RollingUpdatetemplate:metadata:creationTimestamp: nulllabels:app: spring-boot-project # Pod 的标签spec:affinity:podAntiAffinity:preferredDuringSchedulingIgnoredDuringExecution:- podAffinityTerm:labelSelector:matchExpressions:- key: appoperator: Invalues:- spring-boot-projecttopologyKey: kubernetes.io/hostnameweight: 100containers:- env:- name: TZvalue: Asia/Shanghai- name: LANGvalue: C.UTF-8name: spring-boot-project # 容器的名称,需要和流水线 set 命令的容器名称一致image: nginx # 此处使用的 nginx 作为原始的镜像,通过 Jenkins 构建并发版后,变成 Java 应用的镜像ports:- containerPort: 8761 # 端口号和健康检查按照实际情况进行修改name: webprotocol: TCPimagePullPolicy: IfNotPresentlifecycle: {}livenessProbe:failureThreshold: 2initialDelaySeconds: 30periodSeconds: 10successThreshold: 1tcpSocket:port: 8761 # 端口号和健康检查按照实际情况进行修改timeoutSeconds: 2readinessProbe:failureThreshold: 2initialDelaySeconds: 30periodSeconds: 10successThreshold: 1tcpSocket:port: 8761timeoutSeconds: 2resources: # 资源请求按照实际情况修改limits:cpu: 994mmemory: 1170Mirequests:cpu: 10mmemory: 55MidnsPolicy: ClusterFirstimagePullSecrets:- name: harborkey # Harbor 仓库密钥,需要和上述创建的 Secret 一致restartPolicy: AlwayssecurityContext: {}serviceAccountName: default
# 创建资源(Pod 无法启动请忽略):
[root@k8s-master01 ~]# kubectl create -f spring-boot-project.yaml
[root@k8s-master01 ~]# kubectl get po -n kubernetes
NAME READY STATUS RESTARTS AGE
spring-boot-project-57f695f949-wsk76 0/1 ImagePullBackOff 0 51s
3.4.4 PipelineRun 自动构建发版
接下来创建 PipelineRun 实现 Java 应用的自动发版:
[root@k8s-master01 ~]# vim java-pipelinerun.yaml
[root@k8s-master01 ~]# cat java-pipelinerun.yaml
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:# 自动生成名字generateName: spring-boot-project
spec:pipelineRef:name: deploy# 定义 workspaceworkspaces:- name: share-datapersistentVolumeClaim:claimName: tekton-workspace# 按照项目-服务名字-环境当做 workspacesubPath: spring-boot-project-dev# 把 K8s 的 secret 挂载到 git-credentials workspace- name: ssh-directorysecret:secretName: git-ssh-auth- name: docker-credentialssecret:secretName: docker-credentials- name: kubeconfigsecret:secretName: kubeconfig# 传递参数给 pipelineparams:- name: urlvalue: git@192.168.200.55:kubernetes/spring-boot-project.git- name: revisionvalue: "master"- name: BUILD_IMAGEvalue: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/maven:3.5.3- name: BUILD_COMMANDvalue: |-mvn clean install -DskipTestsls target/*- name: REGISTRYvalue: 192.168.200.53- name: REPOSTORYvalue: kubernetes- name: IMAGE_NAMEvalue: spring-boot-project- name: NAMESPACEvalue: kubernetes- name: DEPLOY_NAMEvalue: spring-boot-project- name: CONTAINER_NAMEvalue: spring-boot-project- name: KUBECONFIG_PATHvalue: study-kubeconfig- name: CACHE_DIRvalue: "/root/.m2"
创建该资源:
[root@k8s-master01 ~]# kubectl create -f java-pipelinerun.yaml
Tekton Dashboard上面可以看到执行动作

3.5 Tekton自动化构建前端Vue应用
本节介绍自动化构建 Vue/H5 应用,其构建方式和自动化构建 Java 基本相同,重点是更改 Deployment、Jenkinsfile 和 Dockerfile 即可。
前端应用测试项目地址:https://gitee.com/dukuan/vue-project.git,可以参考 Java 小节的方式,导入前端项目到 GitLab 中,当然也可以使用公司自己的项目。
3.5.1 定义 Dockerfile
前端应用构建后一般会在 dist 文件下产生 html 文件,只需要拷贝到 nginx 的根目录下即可:
FROM crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:1.15
COPY dist/* /usr/share/nginx/html/

3.5.2 定义 Kubernetes 资源
[root@k8s-master01 ~]# vim vue-project.yaml
[root@k8s-master01 ~]# cat vue-project.yaml
apiVersion: v1
kind: Service
metadata:creationTimestamp: nulllabels:app: vue-projectname: vue-projectnamespace: kubernetes
spec:ports:- name: webport: 80protocol: TCPtargetPort: 80selector:app: vue-projectsessionAffinity: Nonetype: ClusterIP
status:loadBalancer: {}
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:creationTimestamp: nullname: vue-projectnamespace: kubernetes
spec:ingressClassName: nginxrules:- host: vue-project.test.comhttp:paths:- backend:service:name: vue-projectport:number: 80path: /pathType: ImplementationSpecific
status:loadBalancer: {}
---
apiVersion: apps/v1
kind: Deployment
metadata:creationTimestamp: nulllabels:app: vue-projectname: vue-projectnamespace: kubernetes
spec:replicas: 1selector:matchLabels:app: vue-projectstrategy:rollingUpdate:maxSurge: 1maxUnavailable: 0type: RollingUpdatetemplate:metadata:creationTimestamp: nulllabels:app: vue-projectspec:affinity:podAntiAffinity:preferredDuringSchedulingIgnoredDuringExecution:- podAffinityTerm:labelSelector:matchExpressions:- key: appoperator: Invalues:- vue-projecttopologyKey: kubernetes.io/hostnameweight: 100containers:- env:- name: TZvalue: Asia/Shanghai- name: LANGvalue: C.UTF-8image: nginximagePullPolicy: IfNotPresentlifecycle: {}livenessProbe:failureThreshold: 2initialDelaySeconds: 30periodSeconds: 10successThreshold: 1tcpSocket:port: 80timeoutSeconds: 2name: vue-projectports:- containerPort: 80name: webprotocol: TCPreadinessProbe:failureThreshold: 2initialDelaySeconds: 30periodSeconds: 10successThreshold: 1tcpSocket:port: 80timeoutSeconds: 2resources:limits:cpu: 994mmemory: 1170Mirequests:cpu: 10mmemory: 55MidnsPolicy: ClusterFirstimagePullSecrets:- name: harborkeyrestartPolicy: AlwayssecurityContext: {}serviceAccountName: default
# 创建资源(Pod 无法启动请忽略):
[root@k8s-master01 ~]# kubectl create -f vue-project.yaml
3.5.3 PipelineRun 自动构建发版
接下来创建 PipelineRun 实现 Java 应用的自动发版:
[root@k8s-master01 ~]# vim vue-project-pipelinerun.yaml
[root@k8s-master01 ~]# cat vue-project-pipelinerun.yaml
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:# 自动生成名字generateName: vue-project
spec:pipelineRef:name: deploy# 定义 workspaceworkspaces:- name: share-datapersistentVolumeClaim:claimName: tekton-workspace# 按照项目-服务名字-环境当做 workspacesubPath: vue-project-dev# 把 K8s 的 secret 挂载到 git-credentials workspace- name: ssh-directorysecret:secretName: git-ssh-auth- name: docker-credentialssecret:secretName: docker-credentials- name: kubeconfigsecret:secretName: kubeconfig# 传递参数给 pipelineparams:- name: urlvalue: git@192.168.200.55:kubernetes/vue-project.git- name: revisionvalue: "master"- name: BUILD_IMAGEvalue: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/node:lts- name: BUILD_COMMANDvalue: |-npm install --registry=https://registry.npmmirror.com/npm run build- name: REGISTRYvalue: 192.168.200.53- name: REPOSTORYvalue: kubernetes- name: IMAGE_NAMEvalue: vue-project- name: NAMESPACEvalue: kubernetes- name: DEPLOY_NAMEvalue: vue-project- name: CONTAINER_NAMEvalue: vue-project- name: KUBECONFIG_PATHvalue: study-kubeconfig- name: CACHE_DIRvalue: "/go/pkg/"
创建该资源:
[root@k8s-master01 ~]# kubectl create -f vue-project-pipelinerun.yaml
Tekton Dashboard上面可以看到执行动作

3.6 Tekton自动化构建GO应用
上述演示了 Java 和前端应用的自动化,接下来演示一下对于 Golang 的自动化构建,本次示例的代码地址:https://gitee.com/dukuan/go-project.git。
3.6.1 定义 Dockerfile
和之前不一样的地方是,Golang 编译后生成的是一个二进制文件,可以直接执行,所以底
层镜像设置为 alpine 或者其它的小镜像即可:
FROM crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/alpine-glibc:alpine-3.9
# 如果定义了单独的配置文件,可能需要拷贝到镜像中
# COPY conf/ ./conf
# 包名按照实际情况进行修改
COPY ./go-project ./
# 启动该应用
ENTRYPOINT [ "./go-project"]

3.6.2 定义 Kubernetes 资源
[root@k8s-master01 ~]# vim go-project.yaml
[root@k8s-master01 ~]# cat go-project.yaml
apiVersion: v1
kind: Service
metadata:creationTimestamp: nulllabels:app: go-projectname: go-projectnamespace: kubernetes
spec:ports:- name: webport: 8080protocol: TCPtargetPort: 8080selector:app: go-projectsessionAffinity: Nonetype: ClusterIP
status:loadBalancer: {}
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:creationTimestamp: nullname: go-projectnamespace: kubernetes
spec:ingressClassName: nginxrules:- host: go-project.test.comhttp:paths:- backend:service:name: go-projectport:number: 8080path: /pathType: ImplementationSpecific
status:loadBalancer: {}
---
apiVersion: apps/v1
kind: Deployment
metadata:creationTimestamp: nulllabels:app: go-projectname: go-projectnamespace: kubernetes
spec:replicas: 1selector:matchLabels:app: go-projectstrategy:rollingUpdate:maxSurge: 1maxUnavailable: 0type: RollingUpdatetemplate:metadata:creationTimestamp: nulllabels:app: go-projectspec:affinity:podAntiAffinity:preferredDuringSchedulingIgnoredDuringExecution:- podAffinityTerm:labelSelector:matchExpressions:- key: appoperator: Invalues:- go-projecttopologyKey: kubernetes.io/hostnameweight: 100containers:- env:- name: TZvalue: Asia/Shanghai- name: LANGvalue: C.UTF-8image: nginximagePullPolicy: IfNotPresentlifecycle: {}livenessProbe:failureThreshold: 2initialDelaySeconds: 30periodSeconds: 10successThreshold: 1tcpSocket:port: 8080timeoutSeconds: 2name: go-projectports:- containerPort: 8080name: webprotocol: TCPreadinessProbe:failureThreshold: 2initialDelaySeconds: 30periodSeconds: 10successThreshold: 1tcpSocket:port: 8080timeoutSeconds: 2resources:limits:cpu: 994mmemory: 1170Mirequests:cpu: 10mmemory: 55MidnsPolicy: ClusterFirstimagePullSecrets:- name: harborkeyrestartPolicy: AlwayssecurityContext: {}serviceAccountName: default
# 创建资源(Pod 无法启动请忽略):
[root@k8s-master01 ~]# kubectl create -f go-project.yaml
3.6.3 PipelineRun 自动构建发版
接下来创建 PipelineRun 实现 Java 应用的自动发版:
[root@k8s-master01 ~]# vim go-project-pipelinerun.yaml
[root@k8s-master01 ~]# cat go-project-pipelinerun.yaml
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:# 自动生成名字generateName: go-project
spec:pipelineRef:name: deploy# 定义 workspaceworkspaces:- name: share-datapersistentVolumeClaim:claimName: tekton-workspace# 按照项目-服务名字-环境当做 workspacesubPath: go-project-dev# 把 K8s 的 secret 挂载到 git-credentials workspace- name: ssh-directorysecret:secretName: git-ssh-auth- name: docker-credentialssecret:secretName: docker-credentials- name: kubeconfigsecret:secretName: kubeconfig# 传递参数给 pipelineparams:- name: urlvalue: git@192.168.200.55:kubernetes/go-project.git- name: revisionvalue: "master"- name: BUILD_IMAGEvalue: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/golang:1.15- name: BUILD_COMMANDvalue: |-export GO111MODULE=onexport CGO_ENABLED=0go env -w GOPROXY=https://goproxy.cn,directgo build- name: REGISTRYvalue: 192.168.200.53- name: REPOSTORYvalue: kubernetes- name: IMAGE_NAMEvalue: go-project- name: NAMESPACEvalue: kubernetes- name: DEPLOY_NAMEvalue: go-project- name: CONTAINER_NAMEvalue: go-project- name: KUBECONFIG_PATHvalue: study-kubeconfig- name: CACHE_DIRvalue: "/go/pkg/"
创建该资源:
[root@k8s-master01 ~]# kubectl create -f go-project-pipelinerun.yaml
Tekton Dashboard上面可以看到执行动作

