tekton
从knative的build中演进而来,属于k8s的扩展
组件
- pipeline:最核心组件,由一组CRD和相关operator、webhook组成。需要部署运行在k8s集群上,作为k8s扩展
- trigger:触发器,可触发pipeline的实例化,可选组件。可直接从gitlab接收事件
- cli:命令行客户端,与tekton交互
- dashboard:tekton管道的基于web的图形化界面,可选组件
- catalog:社区贡献的tekton构建块(building blocks),有现成的清单文件可以拿来用:https://github.com/tektoncd/catalog
- hub:访问catalog的web图形,类似hub仓库:https://hub.tekton.dev/
- tokton operator
核心概念
CRD资源
pipeline
- 由1组task组成,可串行、并行、DAG(任意)
- 由1个task的输出,再给其他task引用
task
- 对应Jenkins的stage
- 对应1个pod,由1组step组成的序列,安装定义的顺序依次允许在同一个pod不同容器中(每个step都是1个容器,1个step容器结束运行下1个step容器)
- 可共享1组环境变量、存储卷
steps
属于task,一个task中定义多个steps,这些steps组合成task
cicd工作流的1个具体操作,如py web app的单元测试,或javaj程序编译操作
每个step都在pod的1个容器中运行
pipelineRun
运行pipeline模板,一个pipielineRun中由多个pipeline、TaskRun组成
pipeline使用k8s注解跟踪pipeline的状态,给每个step相关的容器注入entrypoint程序,此程序执行step定义的内容
运行流程
- 定义pipelinerun,传参、调用的pipeline
- 定义pipeline,声明参数、调用task、传参task
- 定义task,声明参数,定义step
taskRun
运行task模板,一个taskRun中,由多个tasks组成。taskrun代表task的1次执行过程,pipelinerun也是类似
每个taskrun运行在1个独立的pod中,内部每个step分别运行在不同容器中
输入和输出资源
每个task或pipeline都有input和output,都可称为input resources和output resources
如:某task以git仓库为input,output为容器镜像。该task会从git仓库中克隆代码、运行、测试、构建打包为镜像容器
注:input和output现由Parameters替代,参考后面的parameters
支持的资源:
- git仓库
- pull请求:git仓库上的pr请求
- image:容器镜像
- cluster:k8s集群
- storage:blob存储中的对象或目录
- cloudevent
taskRun和pipelineRun
taskrun代表task的1次执行过程,pipelinerun也是类似。具体运行时,task和pipeline连接到配置的resource上,再创建出taskrun和pipelinerun
taskrun和pipelinerun可手动创建、trigger自动触发,创建过程中可进行参数赋值(parameters)
运行流程
- 定义pipelinerun,传参、调用的pipeline
- 定义pipeline,声明参数、调用task、传参task
- 定义task,声明参数,定义step
taskrun和step
每个taskrun运行在1个独立的pod中,内部每个step分别运行在容器中
状态跟踪:pipeline组件使用k8s注解跟踪pipeline的状态,给每个step相关的容器注入entrypoint程序,此程序执行step定义的内容、监视文件
每个step容器会在自己的注解中报告前一个容器执行结果(此结果是一个文件),查看文件,结果是运行成功,才运行当前容器的entrypoint
parameters
是task和pipeline资源定于模板,类似ansible的变量使用方式,需要先声明,然后在引用,运行的时候再传参,或者以代码中形参与实参的关系理解
使用场景:在ci管道中定义git仓库时,可以在task中直接定义1个仓库变量,后续的step中引用这个变量即可,这样实现模板化
parameters变量引用
变量引用(参数)方式:
$(params.变量名) #字符串类型,获取从params字段定义的变量名的值
$(params.变量名.k1) #数组类型,获取变量名下的k1的值
$(params.flags[*]) #获取数组中所有值
数据共享
pipeline和task上可能会存在数据共享的需要,如:
- 1个task的多个step之间,前1个step生成的结果交给后1个step引用
- 1个pipeline的多个task间,前1个task的结果交给后1个task引用
解决方案:
- results
- workspace
workspace
为task的各step提供工作目录,在task声明,且需要taskrun中提供运行时的文件系统
在k8s中对应为存储卷,也就是:
- cm、secret:只读workspace
- pvc:支持跨task共享数据的工作空间
- emptyDir:临时工作目录,step间可共享数据,task间不行
注:emptyDir的生命周期和pod相同,因此只能在1个taskrun的各step间共享数据,如果要跨task共享数据,则使用pvc
功能
- 跨task共享数据(定义在pipeline的workspace)
- 借助secret加载秘密数据
- 借助cm加载配置数据
- 持久化存储数据
- 为task提供缓存加速构建过程。定义在task上的workspace,也可用于sidecat共享数据
建议:
- 同一task内,使用emptyDir
- 同一pipeline内,使用VolumeClaimTemplate
- 跨pipeline,使用静态pvc或直接用存储卷
定义:
参考各资源的.spec.workspaces
字段
变量引用
$(workspaces.名称.path) #挂载路径。可选项打开时,且taskrun未声明时为空
$(workspaces.名称.bound) #布尔值,是否已经已经绑定。可选项关闭时,始终为true
$(workspaces.名称.claim) #使用pvc时的名称,非pvc则为空
$(workspaces.名称.volume) #存储卷名称
results
由tekton的results api负责实现,在task声明,用于让task及step保存执行结果,可以在同一pipeline中的后续task调用此结果
task将会为每个results条目自动创建1个文件进行保存,这些文件统一放在:/tekton/results目录
每个results条目的相关值,需要在step中进行生成并保存,且task不会对相关数据进行任何多余的操作,然后后面的step就可以访问此路径,获取数据
注:仅用于共享小于4096字节的数据,更多时小于1024字节
变量引用
step中引用
$(results.名称.path) #结果文件中的内容
task中引用
results.名称.path
results['名称'].path
results["名称"].path
pipeline中引用
task.task名称.results.名称
task.task名称.results['名称']
task.task名称.results["名称"]
volumes
允许在steps间挂载,共享挂载的卷数据,此配置是静态配置,也就是在task定义时就必须指定好,配置方法参考task.spec.volumes
与task.spec.steps.volumeMounts
字段,与pod配置存储卷一样
不再需要workspace传递路径
CRD配置
运行方法:
- 定义Tasks,各task中定义step完成各步骤
- 定义pipeline,引用Task,并指定各task的运行顺序
- 定义pipelineRun,手动触发pipeline运行
- 定义Trigger,基于事件监听自动触发pipeline执行
task资源
命令
tkn task start hello --showlog
tkn task start logger --showlog -p text=123
语法
文档:https://tekton.dev/docs/pipelines/tasks/
注意:在script命令中,如果对results赋值,如果用echo输出,一定要使用:echo -n
(不换行模式),否则有大坑(别的任务引用结果的时候,有一大串空空白符,识别起来部分有问题)
apiVersion: tekton.dev/v1 # or tekton.dev/v1beta1
kind: Task
metadata:
name: example-task-name
spec:
params: #声明参数
- name: 变量名
type: 类型
#str
#arry
description: 变量描述或|k
default: 默认值 #空变量就赋值此默认的
description: >- #task描述信息,">-"表示开启多行模式,与"|"符号一样
steps: #步骤,必须项,本质上与定义pod的容器没有区别
- name: 步骤名
image: 镜像 #在此步骤中需要基于此镜像执行相关内容
args: [str] #传参
command: [str] #cmd命令,与script互斥
script: | #默认以sh为执行shell,与command互斥。在linux容器执行shell,win容器执行powershell,win使用执行器:#!win powershell.exe -File,或#!win pwsh.exe -File
#!/usr/bin/env bash
脚本内容
workingDir: 工作目录 #可用workspaces变量获取
timeout: 秒 #步骤执行超时时间,超时就中断退出
onError: 条件 #忽略错误条件,查看错误命令:kubectl get tr po名 -o json | jq .status
#stopAndFail,遇到错误就停止并中断
#continue ,忽略错误,继续执行后续步骤
volumentMounts: #存储卷挂载,与pod使用方法一样
- name: 名称
mountPath: 路径
computeResources: #参考容器资源限制
requests:
memory: 1Gi
cpu: 500m
limits:
memory: 2Gi
cpu: 800m
workspaces: #卷路径
- name: 名称
description: 描述
readOnly: false #默认读写
optional: false #是否为可选,默认false
mountPath: 挂载路径 #step容器中挂载路径,默认为:/workspace/名称
results: #执行结果
- name: 名称 #结果名称
description: 描述
volumes: #存储卷,step间共享此卷数据,与pod使用一样
- name: 名称
emptyDir: {}
stepTemplate: #所有step的基础容器步骤定义
sidecars: #注入step的容器
示例
例1:
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: hello
spec:
steps:
- name: say-hello
image: alpine:3.15
command: ['/bin/sh']
args: ['-c', 'echo Hello World']
例2:
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: multiple
spec:
steps:
- name: first
image: alpine:3.15
command:
- /bin/sh
args: ['-c', 'echo First Step']
- name: second
image: alpine:3.15
command:
- /bin/sh
args: ['-c', 'echo Second Step']
例4:
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: logger
spec:
params:
- name: text
type: string
description: something to log
default: "-"
steps:
- name: log
image: alpine:3.15
script: |
#/bin/sh
sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories
apk add -q tzdata
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
DATETIME=$(date "+%F %T")
echo [$DATETIME] - $(params.text)
taskrun资源
语法
文档: https://tekton.dev/docs/pipelines/taskruns/
apiVersion: tekton.dev/v1
kind: TaskRun
metadata:
name: my-taskrun
spec:
taskRef: #指定运行的task
name: my-task
taskSpec: #直接在此处定义task,类似deploy中定义pod模板
inputs:
params:
- name: param1
value: value1
- name: param2
value: value2
serviceAccountName: sa名
params: #task传参
timeout: 1h #taskrun执行超时时间
podTemplate: #定义pod模板
workspaces: #task声明的物理卷
- name: 名
debug: #task调试
stepOverrides: #覆盖task中step的配置
sidecarOverrides: #step注入容器的配置
示例
apiVersion: tekton.dev/v1
kind: TaskRun
metadata:
name: hello-run-00001
spec:
taskRef:
kind: Task
name: hello
注解中标识报告前一个任务已经运行完成,有这个注解后,再继续执行当前step
通过注入的entrypoint,传入参数,等待前一个任务执行完成(查看前一个step执行完成后输出的文件结果,没问题则执行当前step),来实现依次运行
pipeline资源
命令
tkn pipeline ls
tkn pipeline start pipeline-demo --showlog
tkn pipeline start pipeline-with-params --showlog -p text=123
语法
文档:https://tekton.dev/docs/pipelines/pipelines/
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
spec:
params: #声明参数
- name: k
type: string|array
value: v
description: 描述
default: xx
workspaces: #工作目录,声明工作目录
- name: 名称
tasks: #需要运行的task
- name: 名称 #用于上下文调用名称
displayName: 名称 #用于显示名称
description: 描述
taskRef: #引用task
name: 名称
taskSpec: #直接在此处定义task
runAfter: #指定某task在其他task后面执行,不指定时默认并行
- name: 名称
retries: int #task重试执行次数
when: #条件为真才执行task
- input: str #字符串、变量或运行结果,默认为空
value: str #字符串、变量、运行结果或数组(非空数组/列表),必须定义且不能为空
operator: 操作符
#in,input获取的内容存在于value中
#notin,input的内容不存在与value中
timeout: 秒
params:
- name: k
type: string|array
value: v #如果需要pipelinerun传参,则值为:$(params.k)
description: 描述
default: xx
workspaces: #task的工作空间
- name: 名称 #定义名称,task模板中使用此名称
workspace: 名称 #引用spec.workspaces中定义的
matrix:
results: #管道执行结果
- name: 名称
description: 描述
displayName: 名称 #管道显示名称
description: 描述
finally: #指定在所有任务完成后执行的task,与普通task一样配置。一般用于发送通知、清理资源、终止任务等
- name: 名称 #用于上下文调用名称
displayName: 名称 #用于显示名称
description: 描述
taskRef: #引用task
taskSpec: #直接在此处定义task
runAfter: #指定某task在其他task后面执行
retries: int #task重试执行次数
when: 条件 #条件为真才执行task
timeout: 秒
params:
workspaces: #task的工作空间
matrix:
示例
例1:
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
name: pipeline-demo
spec:
tasks:
- name: first-task
taskRef:
name: hello
- name: second-task
taskRef:
name: multiple
runAfter:
- first-task
例2:
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
name: pipeline-with-params
spec:
params:
- name: text
type: string
tasks:
- name: task-one
taskRef:
name: hello
- name: task-two
taskRef:
name: logger
params:
- name: text
value: $(params.text)
例3:
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: pipeline-task-ordering
spec:
tasks:
- name: task-a
taskRef:
name: logger
params:
- name: text
value: "task-A executed"
- name: task-b
taskRef:
name: logger
params:
- name: text
value: "Executed after task-A"
runAfter: ["task-a"]
- name: task-c
taskRef:
name: logger
params:
- name: text
value: "Executed after task-A"
runAfter: ["task-a"]
- name: task-d
taskRef:
name: logger
params:
- name: text
value: "Executed after task-B and task-C"
runAfter: ["task-b", "task-c"]
pipelinerun资源
语法
文档:https://tekton.dev/docs/pipelines/pipelineruns/
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
spec:
pipelineRef: #引用管道
name: 名称
resolver: 解析资源 #启用解析特性,允许声明参数中解析oci资源、远程资源
#bundles,如docker镜像,在参数中的value字段直接使用镜像
#git,解析git仓库,参数中value字段直接使用git仓库
pipelineSpec: #定义管道,与上面互斥
tasks:
params:
- name: k
value: v #传参、声明参数都可以这么用
k1: v1 #上面赋值,或这种赋值,2选一
k2: v2
serviceAccountName: sa #所有task使用此sa的权限,与taskRunSpecs.serviceAccountName字段互斥
status: #取消管道运行的选项
taskRunTemplate: #taskrun模板
serviceAccountName: sa #sa的名称,可为task单独指定sa
podTemplate: #为task中容器指定单独内容,与pod资源一样使用
securityContext:
runAsNonRoot: true
runAsUser: 1001
volumes:
- name: my-cache
persistentVolumeClaim:
claimName: my-volume-claim
taskRunSpecs: #指定PipelineRunTaskSpec的列表,允许为每个任务设置sa、Pod模板和Metadata。可覆盖整个Pipeline设置的Pod模板
- pipelineTaskName: pipeline中task名称
serviceAccountName: sa #为task单独指定sa
computeResources:
requests:
cpu: 2
podTemplate:
nodeSelector:
disktype: ssd
metadata:
annotations:
timeouts: 秒
podTemplate: #定义task的基础pod模板,全局生效
workspaces: #定义工作目录
- name: 名称
volumeClaimTemplate: #申请pvc,与pvc使用一致,但需要提前准备存储类
spec:
accessMode:
- 模式
...
subPath: 路径 #可定义挂载子路径。可以是绝对值:workspaces[].subPath,也可以引用pipelineRun上下文变量,例如 $(context.pipelineRun.name) 或 $(context.pipelineRun.uid)
示例
例1:
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: pipeline-demo-run-xxxxx
namespace: default
spec:
pipelineRef:
name: pipeline-demo
serviceAccountName: default
timeout: 1h0m0s
例2:
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: pipeline-with-params-run-xxxxx
namespace: default
spec:
params:
- name: target
value: "one"
- name: text
value: "two"
pipelineRef:
name: pipeline-with-params
serviceAccountName: default
timeout: 10m0s
综合案例
例1:多steps间共享数据(使用wokrspace)
1)创建task
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: ws-demo
spec:
params:
- name: target
type: string
default: 123456
steps:
- name: alpine-img
image: alpine
script: |
set -xe
if [ $(workspaces.msg.bound) == true ]; then
#实际路径为:/data/msg
echo hello $(params.target) > $(workspaces.mgs.path)/msg
fi
echo "mount path: $(workspaces.mgs.path)"
echo "volume name: $(workspaces.msg.volume)"
workspaces:
- name: msg
description: "信息记录文件"
optional: true
mountPath: /data #挂载到/data,
2)运行
tkn task start --showlog ws-demo -p target="hj" -w name=msg,emptyDir=""
例2:多steps间共享数据(使用result)
注:保存results变量时,一定不能加换行符,否则后面任务识别有问题(换行有坑)
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: generate-buildid
spec:
params:
- name: version
description: The version of the application
type: string
default: "v0.9"
results:
- name: datetime
description: The current date and time
- name: buildId
description: The build ID
steps:
- name: generate-datetime
image: ikubernetes/admin-box:v1.2
script: |
#!/usr/bin/env bash
datetime=`date +%Y%m%d-%H%M%S`
echo -n ${datetime} | tee $(results.datetime.path)
- name: generate-buildid
image: ikubernetes/admin-box:v1.2
script: |
#!/usr/bin/env bash
buildDatetime=`cat $(results.datetime.path)`
buildId=$(params.version)-${buildDatetime}
echo -n ${buildId} | tee $(results.buildId.path)
例3:pipelinerun对task传参
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: hello-task-1
spec:
params:
- name: target
type: string
description: one number
default: 123456
steps:
- name: alpine-1
image: alpine
script: |
echo hello $(params.target)
---
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
name: pipeline-demo
spec:
params:
- name: target
type: string
default: 654321
tasks:
- name: task1
taskRef:
name: hello-task-1
params:
- name: target
value: $(params.target) #获取Pipeline.spec.params.target的内容
---
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: pipelinerun-demo
spec:
params:
- name: target #为pipeline-demo传参
value: hj
pipelineRef:
name: pipeline-demo
例4:简单代码克隆、构建
1)创建任务与流水线
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: make-code-task
spec:
params:
- name: git-url #声明变量
type: string
workspaces:
- name: code #声明工作目录
steps:
- name: clone-code
image: alpine/git:2.40.1
script: |
sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories
apk add tzdata git curl
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
echo "Asia/Shanghai" > /etc/timezone
git clone -v --depth 1 $(params.git-url) $(workspaces.code.path)/code
- name: build
image: maven:3.8.7-openjdk-18-slim
workingDir: $(workspaces.code.path)/code
script: |
sed -i -e '/\/mirrors/i\ <mirror>' \
-e '/\/mirrors/i\ <id>aliyunmaven</id>' \
-e '/\/mirrors/i\ <mirrorOf>*</mirrorOf>' \
-e '/\/mirrors/i\ <name>阿里云公共仓库</name>' \
-e '/\/mirrors/i\ <url>https://maven.aliyun.com/repository/public</url>' \
-e '/\/mirrors/i\ </mirror>' \
/usr/share/maven/conf/settings.xml
mvn clean test install
#以下全部都是需要使用pvc,手动或使用nfs-csi都可
volumeMounts:
- name: mvn-cache
mountPath: /root/.m2
volume:
- name: mvn-cache
persistentVolumeClaim:
claimName: mvn-cache
---
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
name: make-code
spec:
params: #重新声明参数,为task声明的
- name: git-url
type: string
workspaces: #声明工作目录,为task声明的,后面与task的关联
- name: code-dir
tasks:
- name: build-java
params:
- name: git-url
value: $(params.git-url) #传参给task的变量
workspaces:
- name: code #task中对应的工作目录
workspace: code-dir #赋值给task的工作目录
taskRef:
name: make-code-task
2)运行
tkn pipeline start make-code --showlog -p git-url='https://gitee.com/mageedu/spring-boot-helloWorld.git' -w name=code-dir,emptyDir=""
例5:基于例3并加上动静态pvc实现
1)创建存储类
使用nfs-csi存储驱动,nfs-csi部署参考:nfs-csi驱动部署
kubectl apply -f - <<eof
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-csi
provisioner: nfs.csi.k8s.io
parameters:
server: nfs-server.default.svc.cluster.local
share: /
reclaimPolicy: Delete
volumeBindingMode: Immediate
mountOptions:
- nfsvers=4.1
eof
2)创建pvc
kubectl apply -f - <<eof
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mvn-cache
spec:
storageClassName: nfs-csi
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi
eof
3)创建任务
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: make-code-task
spec:
params:
- name: git-url
type: string
workspaces:
- name: code
steps:
- name: clone-code
image: alpine/git:2.40.1
script: |
sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories
apk add tzdata git curl
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
echo "Asia/Shanghai" > /etc/timezone
git clone -v --depth 1 $(params.git-url) $(workspaces.code.path)
- name: build
image: maven:3.8.7-openjdk-18-slim
workingDir: $(workspaces.code.path)
script: |
sed -i -e '/\/mirrors/i\ <mirror>' \
-e '/\/mirrors/i\ <id>aliyunmaven</id>' \
-e '/\/mirrors/i\ <mirrorOf>*</mirrorOf>' \
-e '/\/mirrors/i\ <name>阿里云公共仓库</name>' \
-e '/\/mirrors/i\ <url>https://maven.aliyun.com/repository/public</url>' \
-e '/\/mirrors/i\ </mirror>' \
/usr/share/maven/conf/settings.xml
mvn clean test install
volumeMounts:
- name: mvn-cache
mountPath: /root/.m2
volumes:
- name: mvn-cache
persistentVolumeClaim:
claimName: mvn-cache
---
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
name: make-code
spec:
params:
- name: git-url
type: string
workspaces:
- name: code-dir
tasks:
- name: build-java
params:
- name: git-url
value: $(params.git-url)
workspaces:
- name: code
workspace: code-dir
taskRef:
name: make-code-task
4)创建流水线运行任务
kubectl apply -f - <<eof
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: make-code
spec:
params:
- name: git-url
value: https://gitee.com/mageedu/spring-boot-helloWorld.git
pipelineRef:
name: make-code
workspaces:
- name: code-dir
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Mi
storageClassName: nfs-csi
eof
浏览器查看时,可以看到流水线已经执行完成
例6:cicd流水线
k8s中,容器中构建镜像的方法有2种:
- dink(docker-in-docker):挂载宿主机docker套接字,使用宿主机docker完成
- kaniko:无任何依赖,直接容器中构建镜像
1)配置镜像仓库登录信息
docker信息文件可以在命令行登录后,自动生成,也可以手动创建:
# 将账号密码做编码转换
# echo 账号:密码 |base64
upw=`echo 账号:密码 |base64`
cat > docker-user.json <<eof
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "$upw"
},
"registry.cn-hangzhou.aliyuncs.com": {
"auth": "$upw"
}
}
}
eof
创建secret资源
#docker login -u suyanhj https://hub.docker.com/
#此处登录阿里云
docker login -u 那是你的猫 registry.cn-hangzhou.aliyuncs.com
kubectl create secret generic docker-config --from-file=/root/.docker/config.json
2)创建集群部署管理账号
给kubectl命令访问api-server的权限,运行创建资源
kubectl apply -f - <<eof
apiVersion: v1
kind: ServiceAccount
metadata:
name: helloworld-admin
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: helloworld-admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: helloworld-admin
namespace: default
eof
3)创建代码克隆任务
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: git-clone
spec:
description: Clone the code repository to the workspace.
params:
- name: url
type: string
description: git url to clone
default: ""
- name: branch
type: string
description: git branch to checkout
default: "main"
workspaces:
- name: source
description: The git repo will be cloned onto the volume backing this workspace
steps:
- name: git-clone
image: alpine/git:2.40.1
script: |
sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories
apk add tzdata git curl
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
echo "Asia/Shanghai" > /etc/timezone
git clone -b $(params.branch) -v $(params.url) $(workspaces.source.path)
4)创建代码编译打包任务
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: build-to-pkg
spec:
description: build application and package the files to image
workspaces:
- name: source
description: The git repo that cloned onto the volume backing this workspace
steps:
- name: build
image: maven:3.8.7-openjdk-18-slim
workingDir: $(workspaces.source.path)
script: |
sed -i -e '/\/mirrors/i\ <mirror>' \
-e '/\/mirrors/i\ <id>aliyunmaven</id>' \
-e '/\/mirrors/i\ <mirrorOf>*</mirrorOf>' \
-e '/\/mirrors/i\ <name>阿里云公共仓库</name>' \
-e '/\/mirrors/i\ <url>https://maven.aliyun.com/repository/public</url>' \
-e '/\/mirrors/i\ </mirror>' \
/usr/share/maven/conf/settings.xml
mvn clean install
volumeMounts:
- name: mvn-cache
mountPath: /root/.m2
volumes:
- name: mvn-cache
persistentVolumeClaim:
claimName: mvn-cache
5)创建容器镜像版本号生成任务
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: generate-build-id
spec:
params:
- name: version
description: The version of the application
type: string
results:
- name: datetime
description: The current date and time
- name: buildId
description: The build ID
steps:
- name: generate-datetime
image: busybox
script: |
#!/bin/sh
datetime=`date +%Y%m%d-%H%M%S`
echo -n ${datetime} | tee $(results.datetime.path)
- name: generate-buildid
image: busybox
script: |
#!/bin/sh
buildDatetime=`cat $(results.datetime.path)`
buildId=$(params.version)-${buildDatetime}
echo -n ${buildId} | tee $(results.buildId.path)
6)创建容器镜像构建任务
方法1:使用kaniko,直接在容器中构建镜像
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: img-build
spec:
description: package the application files to image
params:
- name: dockerfile
description: The path to the dockerfile to build (relative to the context)
default: Dockerfile
- name: image-url
description: Url of image repository
- name: image-tag
description: Tag to apply to the built image
default: latest
workspaces:
- name: source
- name: dockerconfig
#将docker账号信息,挂载到kaniko容器中,用于推送镜像到仓库
mountPath: /kaniko/.docker
steps:
- name: build-and-push-img
image: m.daocloud.io/gcr.io/kaniko-project/executor:debug
securityContext:
runAsUser: 0
command:
- /kaniko/executor
args:
#选项解释:https://github.com/GoogleContainerTools/kaniko#additional-flags
- --dockerfile=$(params.dockerfile) #dockefile文件名
- --context=$(workspaces.source.path) #构建镜像时的工作目录
- --destination=$(params.image-url):$(params.image-tag) #镜像上传路径与标签
#- --build-arg
#- --cache
#- --cache-dir
#- --cache-repo
#- --cache-copy-layers
#- --cache-run-layers
#- --cache-ttl duration
#- --cleanup
#- --compressed-caching
#- --context-sub-path
#- --custom-platform
#- --digest-file
#- --force
#- --git
#- --image-name-with-digest-file
#- --image-name-tag-with-digest-file
#- --insecure
#- --insecure-pull
#- --insecure-registry
#- --label
#- --log-format
#- --log-timestamp
#- --oci-layout-path
#- --push-retry
#- --registry-certificate
#- --registry-client-cert
#- --registry-mirror #镜像下载加速地址,不需要写访问协议,只需写域名
#- --skip-default-registry-fallback
#- --reproducible
#- --single-snapshot
#- --skip-tls-verify
#- --skip-push-permission-check
#- --skip-tls-verify-pull
#- --skip-tls-verify-registry
#- --skip-unused-stages
#- --snapshot-mode
#- --tar-path
#- --target
#- --use-new-run
#- --verbosity
#- --ignore-var-run
#- --ignore-path
#- --image-fs-extract-retry
#- --image-download-retry
方法2:使用dind(需要安装docker并挂载套接字)
kind: Task
...
spec:
params:
- name: dockerfileName
type: string
description: The name of the Dockerfile
default: Dockerfile
- name: image
type: string
description: The image to build and push
workspaces:
- name: source
steps:
- name: dockerfile-build
image: gcr.io/cloud-builders/docker
workingDir: "$(workspaces.source.path)"
args:
[
"build",
"--no-cache",
"--tag",
"$(params.image)",
"--file",
"$(params.dockerfileName)",
".",
]
volumeMounts:
- name: docker-socket
mountPath: /var/run/docker.sock
- name: dockerfile-push
image: gcr.io/cloud-builders/docker
args: ["push", "$(params.image)"]
volumeMounts:
- name: docker-socket
mountPath: /var/run/docker.sock
volumes:
- name: docker-socket
hostPath:
path: /var/run/docker.sock
type: Socket
7)创建应用部署于集群任务
pod与k8s处于同一个集群时,sa就可以保障api-server可以访问,只有跨集群时,需要配置远程集群的kubeconfig文件
注:部署时要考虑是否在部署清单中配置拉镜像的仓库登录账号(取决于仓库公开/私有)
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: deploy-using-kubectl
spec:
workspaces:
- name: source
description: The git repo
params:
- name: deploy-config-file
description: The path to the yaml file to deploy within the git source
- name: image-url
description: Image name including repository
- name: image-tag
description: Image tag
steps:
- name: update-yaml
image: alpine:3.16
command: ["sed"]
args:
- "-i"
- "-e"
- "s@__IMAGE__@$(params.image-url):$(params.image-tag)@g"
- "$(workspaces.source.path)/deploy/$(params.deploy-config-file)"
- name: run-kubectl
image: lachlanevenson/k8s-kubectl
command: ["kubectl"]
args:
#当前部署的集群与kubectl相同集群,所以不需要传递kubeconfig
- "apply"
- "-f"
- "$(workspaces.source.path)/deploy/$(params.deploy-config-file)"
8)创建流水线,编排任务
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
name: source-to-img
spec:
params:
- name: git-url
- name: pathToContext
description: The path to the build context, used by Kaniko - within the workspace
default: .
- name: image-url
description: Url of image repository
- name: deploy-config-file
default: all-in-one.yaml
- name: version
description: The version of the application
type: string
default: "v0.9"
workspaces:
- name: codebase
- name: docker-config
tasks:
- name: git-clone
taskRef:
name: git-clone
params:
- name: url
value: "$(params.git-url)"
workspaces:
- name: source
workspace: codebase
- name: build-to-pkg
taskRef:
name: build-to-pkg
workspaces:
- name: source
workspace: codebase
runAfter:
- git-clone
- name: generate-build-id
taskRef:
name: generate-build-id
params:
- name: version
value: "$(params.version)"
runAfter:
- git-clone
- name: img-build-push
taskRef:
name: img-build
params:
- name: image-url
value: "$(params.image-url)"
- name: image-tag
value: "$(tasks.generate-build-id.results.buildId)"
workspaces:
- name: source
workspace: codebase
- name: dockerconfig
workspace: docker-config
runAfter:
- build-to-pkg
- generate-build-id
- name: deploy-to-cluster
taskRef:
name: deploy-using-kubectl
workspaces:
- name: source
workspace: codebase
params:
- name: deploy-config-file
value: $(params.deploy-config-file)
- name: image-url
value: $(params.image-url)
- name: image-tag
value: "$(tasks.generate-build-id.results.buildId)"
runAfter:
- img-build-push
10)创建流水线运行任务,执行应用部署
kubectl apply -f - <<eof
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: deploy-java
spec:
#serviceAccountName: default
taskRunSpecs:
- pipelineTaskName: deploy-to-cluster
serviceAccountName: helloworld-admin
pipelineRef:
name: source-to-img
params:
- name: git-url
value: https://gitee.com/mageedu/spring-boot-helloWorld.git
- name: image-url
value: registry.cn-hangzhou.aliyuncs.com/suyanhj/spring-boot-helloworld
#value: suyanhj/spring-boot-helloworld
- name: version
value: v0.9.2
workspaces:
- name: docker-config
secret:
secretName: docker-config
- name: codebase
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Mi
storageClassName: nfs-csi
eof
11)测试
pod_ip=`kubectl get po -o wide |awk '/helloworld/{print $6}'`
curl $pod_ip ;echo