tekton
部署
部署crd和pipline服务:
https://tekton.dev/docs/getting-started/tasks/ kubectl apply -f https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml
查看:
~]# kubectl api-resources --api-group=tekton.dev NAME SHORTNAMES APIVERSION NAMESPACED KIND clustertasks tekton.dev/v1beta1 false ClusterTask pipelineresources tekton.dev/v1alpha1 true PipelineResource(已废弃) pipelineruns pr,prs tekton.dev/v1beta1 true PipelineRun pipelines tekton.dev/v1beta1 true Pipeline runs tekton.dev/v1alpha1 true Run taskruns tr,trs tekton.dev/v1beta1 true TaskRun tasks tekton.dev/v1beta1 true Task
部署dashboard:
https://tekton.dev/docs/dashboard/install/ kubectl apply -f https://storage.googleapis.com/tekton-releases/dashboard/latest/tekton-dashboard-release.yaml
部署问题:
{"severity":"fatal","timestamp":"2022-09-22T03:55:15.673Z","logger":"tekton-pipelines-controller","caller":"sharedmain/main.go:326","message":"Version check failed","commit":"9221ac3-dirty","error":"kubernetes version \"1.18.20\" is not compatible, need at least \"1.22.0-0\" (this can be overridden with the env var \"KUBERNETES_MIN_VERSION\")","stacktrace":"knative.dev/pkg/injection/sharedmain.CheckK8sClientMinimumVersionOrDie\n\tknative.dev/pkg@v0.0.0-20220818004048-4a03844c0b15/injection/sharedmain/main.go:326\nknative.dev/pkg/injection/sharedmain.MainWithConfig\n\tknative.dev/pkg@v0.0.0-20220818004048-4a03844c0b15/injection/sharedmain/main.go:228\nmain.main\n\tgithub.com/tektoncd/pipeline/cmd/controller/main.go:106\nruntime.main\n\truntime/proc.go:250"}解决方法:
]# kubectl edit deployments.apps -n tekton-pipelines tekton-pipelines-controller ]# kubectl edit deployments.apps -n tekton-pipelines tekton-pipelines-webhook ... env: - name: KUBERNETES_MIN_VERSION value: v1.17.0+k3s.1 ...
暴露dashboard:这里使用ingressgateway的方式进行暴露服务,需要安装istio。用ingress也行,istio并非必要。
--- apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: tekton-dashboard namespace: tekton-pipelines spec: host: tekton-dashboard trafficPolicy: tls: mode: DISABLE --- apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: tekton-dashboard-gateway namespace: istio-system spec: selector: app: istio-ingressgateway servers: - port: number: 80 name: http protocol: HTTP hosts: - "tekton.ops.net" - "ci.ops.net" --- apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: tekton-dashboard-virtualservice namespace: tekton-pipelines spec: hosts: - "tekton.ops.net" - "ci.ops.net" gateways: - istio-system/tekton-dashboard-gateway http: - match: - uri: prefix: / route: - destination: host: tekton-dashboard port: number: 9097 ---
自建集群需要在istio-ingressgateway的svc上配置externalIPs:然后将域名解析到这个IP。
spec: externalIPs: - 192.168.0.88
部署的服务:
~]# kubectl get pods -n tekton-pipelines NAME READY STATUS RESTARTS AGE tekton-dashboard-6c97f9bdd5-kj4l8 1/1 Running 0 20d tekton-pipelines-controller-5556479b76-252hn 1/1 Running 0 20d tekton-pipelines-webhook-785478f957-7jt7t 1/1 Running 0 20d
部署CLI:
https://github.com/tektoncd/cli/releases rpm -i https://github.com/tektoncd/cli/releases/download/v0.25.0/tektoncd-cli-0.25.0_Linux-64bit.rpm
常用命令:
tkn task list tkn taskrun list tkn pipeline list tkn pipelinerun list tkn task delete --all tkn taskrun delete --all
Task,TaskRun
task示例:简单输出
apiVersion: tekton.dev/v1beta1 kind: task metadata: name: world spec: steps: - name: say-hello image: alpine:3.15 command: ['/bin/sh'] args: ['-c', 'echo hello'] # 输出hello - name: say-world image: alpine:3.15 command: ['/bin/sh'] args: ['-c', 'echo world'] # 输出world,多step情况下第一个结束才运行第二个,按顺序执行 --- apiVersion: tekton.dev/v1beta1 kind: TaskRun metadata: name: world-run-00001 spec: taskRef: kind: Task name: world --- ]# tkn taskrun logs world-run-00001 [say-hello] hello [say-world] world
task引用参数:
apiVersion: tekton.dev/v1beta1 kind: Task metadata: name: hello-params spec: params: - name: target #参数名称 type: string # 参数类型 description: name of somebody # 参数功能描述 default: scriptjc.com # 参数默认值 steps: - name: say-hello image: alpine:3.15 command: - /bin/sh args: ['-c','echo hello $(params.target)'] # $(params.target) 引用变量的方式
命令启动task任务:
]# tkn task start hello-params --showlog ? Value for param `target` of type `string`? (Default is `scriptjc.com`) scriptjc.com # 可以手动输入参数,不输入则使用默认值 TaskRun started: hello-params-run-9lk2n Waiting for logs to be available... [say-hello] hello scriptjc.com
命令行直接传参:-p选项可以传参,避免进入交互式界面
]# tkn task start hello-params --showlog -p target=www.scriptjc.com TaskRun started: hello-params-run-q7p6d Waiting for logs to be available... [say-hello] hello www.scriptjc.com
task运行脚本:
apiVersion: tekton.dev/v1beta1 kind: Task metadata: name: script spec: steps: - name: step-with-script image: alpine:3.15 script: | #!/bin/sh echo "step with script" apk add curl curl -s www.scriptjc.com && echo "success" || echo "fail" echo "All done"
task在脚本中引用参数:
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 apk add -q tzdata cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime # 获取本地时间 DATETIME=$(date "+%F %T") echo [$DATETIME] - $(params.text)
pipeline
定义task运行顺序:
apiVersion: tekton.dev/v1beta1 kind: Pipeline metadata: name: pipeline-demo spec: tasks: - name: first-task taskRef: name: world - name: second-task taskRef: name: logger runAfter: - first-task # 定义了second-task 必须在first-task 运行完成之后再运行
查看详细信息:
]# tkn pipeline describe pipeline-demo Name: pipeline-demo Namespace: default Tasks NAME TASKREF RUNAFTER TIMEOUT PARAMS ∙ first-task world --- --- ∙ second-task logger first-task --- --- PipelineRuns NAME STARTED DURATION STATUS ∙ pipeline-demo-run-j8wlq 2 minutes ago 16s Succeeded
pipeline给task传参:
apiVersion: tekton.dev/v1beta1 kind: Pipeline metadata: name: pipeline-with-params spec: params: # 定义参数,给task传值用的 - name: height type: string tasks: - name: task-one taskRef: name: hello-params - name: task-two taskRef: name: logger params: # 给logger传参 - name: text value: $(params.height) # 引用了上面定义的名为height的参数
启动pipelineRun:
]# tkn pipeline start pipeline-with-params -p height=1111 --showlog PipelineRun started: pipeline-with-params-run-rln26 Waiting for logs to be available... [task-one : say-hello] hello scriptjc.com [task-two : log] [2022-08-16 14:36:40] - 1111
workspaces
Results:只能传递小于4096的数据
Workspace:工作空间、文件系统
$(workspace.<name>.path) 挂载路径
$(workspace.<name>.bound) 是否绑定
$(workspace.<name>.claim) pvc名称
$(workspace.<name>.volume) 卷名称
引用方法:
/workspaces/<name> 默认挂载路径,自定义情况下访问不了
$(workspaces.<name>.path) 默认挂载路径和自定义挂载路径都可以访问到
task中使用workspace:
apiVersion: tekton.dev/v1beta1 kind: Task metadata: name: workspace-demo spec: params: - name: target type: string default: scriptjc.com steps: - name: write-message image: alpine:3.15 script: | #!/bin/sh set -xe if [ "$(workspaces.message.bound)" == "true" ]; then # 如果已近绑定了PVC echo "hello $(params.target)" > $(workspaces.message.path)/message # 将信息写入到message文件中 fi echo "Mount Path: $(workspaces.message.path)" echo "Volume Name: $(workspaces.message.volume)" echo "Claim Name: $(workspaces.message.claim)" workspaces: - name: message description: | 如果写入成功 message 文件里面应该有信息 optional: true mountPath: /data
-w name=message,emptyDir="" 意思是名为message的workspace提供一个emptyDir的存储卷。
]# tkn task start workspace-demo --showlog -p target="scriptjc.com" -w name=message,emptyDir="" TaskRun started: workspace-demo-run-hl6cw Waiting for logs to be available... [write-message] + '[' true '==' true ] [write-message] + echo 'hello scriptjc.com' [write-message] + echo 'Mount Path: /data' [write-message] + echo 'Volume Name: ws-27mms' [write-message] Mount Path: /data [write-message] Volume Name: ws-27mms [write-message] Claim Name: [write-message] + echo 'Claim Name: '
task中多个steps共享workspaces:
apiVersion: tekton.dev/v1beta1 kind: Task metadata: name: source-lister spec: params: - name: git-repo type: string description: Git repo to be cloned workspaces: - name: source steps: - name: git-clone image: alpine/git:v2.36.1 script: git clone -v $(params.git-repo) $(workspaces.source.path)/source - name: list-files image: alpine:3.15 command: - /bin/sh args: - '-c' - 'ls $(workspaces.source.path)/source'
运行:
]# tkn task start --showlog source-lister -w name=source,emptyDir="" -p git-repo=https://gitee.com/mageedu/spring-boot-helloWorld.git TaskRun started: source-lister-run-qf9b9 Waiting for logs to be available... [git-clone] Cloning into '/workspace/source/source'... [git-clone] POST git-upload-pack (175 bytes) [git-clone] POST git-upload-pack (367 bytes) [list-files] Dockerfile [list-files] Jenkinsfile [list-files] LICENSE [list-files] README.md [list-files] deploy [list-files] pom.xml [list-files] src
pipeline中使用workspaces和传参:
apiVersion: tekton.dev/v1beta1 kind: Pipeline metadata: name: pipeline-source-lister spec: workspaces: - name: codebase params: - name: git-url type: string description: Git repo url to be cloned tasks: - name: git-clone taskRef: name: source-lister # 引用的是那个task workspaces: - name: source workspace: codebase # 给这个task的workspace赋值 params: - name: git-repo value: $(params.git-url) # 给task中的这个参数赋值
启动任务:
]# tkn pipeline start --showlog pipeline-source-lister -w name=codebase,emptyDir="" -p git-url=https://gitee.com/mageedu/spring-boot-helloWorld.git PipelineRun started: pipeline-source-lister-run-pm28l Waiting for logs to be available... [git-clone : git-clone] Cloning into '/workspace/source/source'... [git-clone : git-clone] POST git-upload-pack (175 bytes) [git-clone : git-clone] POST git-upload-pack (367 bytes) [git-clone : list-files] Dockerfile [git-clone : list-files] Jenkinsfile [git-clone : list-files] LICENSE [git-clone : list-files] README.md [git-clone : list-files] deploy [git-clone : list-files] pom.xml [git-clone : list-files] src
使用pvc启动pipelineRun:
apiVersion: tekton.dev/v1beta1 kind: PipelineRun metadata: name: pipeline-source-lister-run-00001 spec: pipelineRef: name: pipeline-source-lister params: - name: git-url value: https://gitee.com/mageedu/spring-boot-helloWorld.git workspaces: - name: codebase volumeClaimTemplate: spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 1Gi storageClassName: managed-nfs-storage
pipeline编译maven项目:
apiVersion: tekton.dev/v1beta1 kind: Pipeline metadata: name: source-2-package spec: params: # pipeline级别的参数 - name: git-url type: string workspaces: # pipeline级别的工作空间 - name: codebase tasks: # 在pipeline中直接写入task字段 - name: fetch-from-source # task1 params: # 定义 task1 用到的参数 - name: url value: $(params.git-url) workspaces: # 定义 task1 用到的工作空间 - name: source workspace: codebase taskSpec: workspaces: - name: source params: - name: url steps: - name: git-clone image: alpine/git:v2.36.1 script: git clone -v $(params.url) $(workspaces.source.path)/source - name: build # task 2 workspaces: # task2用到的工作空间 - name: source workspace: codebase runAfter: # 定义task2的运行顺序 - fetch-from-source taskSpec: workspaces: # 定义用到的工作空间 - name: source steps: - name: build image: maven:3.8-openjdk-11-slim workingDir: $(workspaces.source.path)/source script: | mvn clean install --- apiVersion: tekton.dev/v1beta1 kind: PipelineRun metadata: name: source-to-build-run-00001 spec: pipelineRef: name: source-2-package params: - name: git-url value: https://gitee.com/mageedu/spring-boot-helloWorld.git workspaces: - name: codebase volumeClaimTemplate: spec: storageClassName: managed-nfs-storage accessModes: - ReadWriteOnce resources: requests: storage: 1Gi
固定的volume:支持夸pipelineRun共享(生命周期同pipeline)。workspace不支持夸pipelinerun共享(生命周期同pipelineRun)。
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: maven-cache # 这个pvc是做缓存用的,在task里直接引用,而不是在pipelineRun里引用,需要手动创建 spec: storageClassName: managed-nfs-storage accessModes: - ReadWriteMany resources: requests: storage: 5Gi --- apiVersion: tekton.dev/v1beta1 kind: Pipeline metadata: name: source-2-package spec: params: - name: git-url type: string workspaces: - name: codebase tasks: - name: fetch-from-source params: - name: url value: $(params.git-url) taskSpec: workspaces: - name: source params: - name: url steps: - name: git-clone image: alpine/git:v2.36.1 script: git clone -v $(params.url) $(workspaces.source.path)/source workspaces: - name: source workspace: codebase - name: build-package runAfter: - fetch-from-source taskSpec: steps: - name: build image: maven:3.8-openjdk-11-slim workingDir: $(workspaces.source.path)/source volumeMounts: - name: m2 # 挂载使用 mountPath: /root/.m2 script: mvn clean install workspaces: - name: source volumes: - name: m2 persistentVolumeClaim: claimName: maven-cache # 和pipeline绑定在一起,作为缓存使用,多个pipelineRun可共享多路读写 workspaces: - name: source workspace: codebase --- apiVersion: tekton.dev/v1beta1 kind: PipelineRun metadata: name: source-2-package-run-002 spec: pipelineRef: name: source-2-package params: - name: git-url value: https://gitee.com/mageedu/spring-boot-helloWorld.git workspaces: - name: codebase volumeClaimTemplate: spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: managed-nfs-storage
Results
可在steps之间、在tasks之间共享数据。
$(results.<result_name>.path) 保存result的文件路径。
取值方法:
script: |
RET=$(cat /tekton/results/<result_name>)
tasks中引用:results.<result_name>.path
跨tasks引用:tasks.<taskName>.results.<result_name>
跨step使用:
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: generate-buildid
spec:
params:
- name: version
type: string
description: the version of application
default: "v0.9"
results:
- name: datetime
description: The current datetime
- 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) # 将结果存入 results.datetime
- name: generate-buildid
image: ikubernetes/admin-box:v1.2
script: |
#!/usr/bin/env bash
buildDatetime=`cat $(results.datetime.path)` # 使用 results.datetime 的值
buildId=$(params.version)-${buildDatetime}
echo -n ${buildId} | tee $(results.buildId.path) # 将结果存入 results.buildId其他语句
when:执行条件
conditions(已弃用):when代替
timeout:超时时长
runAfter:定义执行顺序
finally:最终任务
retries:定义重试次数
when、input、operator:
tasks: - name: first-create-file when: - input: "$(params.path)" operator: in # 只有in和notin两种值 values: ["README.md"] taskRef: name: first-create-file --- tasks: - name: echo-file-exists when: - input: "$(tasks.check-file.results.exists)" operator: in values: ["yes"] taskRef: name: echo-file-exists --- tasks: - name: deploy-in-blue when: - input: "blue" operator: in values: ["$(params.deployment[*])"] taskRef: name: deployment --- tasks: - name: manual-approval runAfter: - tests when: - input: $(params.git-action) operator: in values: ['merge'] taskRef: name: manual-approval - name: build-image when: - input: $(oarams.git-action) operator: in values: ['merge'] runAfter: - manual-approval taskRef: name: build-image - name: deploy-image when: - input: $(params.git-action) operator: in values: ['merge'] runAfter: - build-image taskRef: name: deploy-image - name: slack-msg params: - name: approver value: $(tasks.manual-approval.results.approver) taskRef: name: slack-msg
finally:
finally: - name: taskRef: taskSpec:
示例:
spec: workspaces: - name: shared-workspace tasks: - name: clone-app-source taskRef: name: clone-app-repo-to-workspace workspaces: - name: shared-workspace workspace: shared-workspace finally: - name: cleanup-workspace taskRef: name: cleanup-workspace workspaces: - name: shared-workspace workspace: shared-workspace
构建镜像
打镜像并推送:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: maven-cache # 这个pvc是做缓存用的,在task里直接引用,而不是在pipelineRun里引用,需要手动创建
spec:
storageClassName: managed-nfs-storage
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
---
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: git-clone
spec:
description: "克隆代码到工作空间"
params:
- name: url
type: string
description: "仓库地址"
default: ""
- name: branch
type: string
description: "代码分支"
default: "main"
workspaces:
- name: source
description: "代码下载到挂载的工作空间磁盘上"
steps:
- name: git-clone
image: alpine/git:v2.36.1
script: git clone -b $(params.branch) -v $(params.url) $(workspaces.source.path)/source
---
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: build-to-package
spec:
description: "编译"
workspaces:
- name: source
description: "代码下载目录"
steps:
- name: build
image: maven:3.8-openjdk-11-slim
workingDir: $(workspaces.source.path)/source
volumeMounts:
- name: m2
mountPath: /root/.m2
script: mvn clean install
volumes:
- name: m2
persistentVolumeClaim:
claimName: maven-cache # 这个pvc是做缓存用的,在task里直接引用,而不是在pipelineRun里引用,需要手动创建
---
# 镜像版本号和日期后缀
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: generate-build-id
spec:
params:
- name: version
type: string
description: "应用版本号"
results:
- name: datetime
description: "当前时间"
- name: buildId
description: "构建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)
---
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: image-build
spec:
description: "打镜像"
params:
- name: dockerfile
description: "dockerfile 文件"
default: Dockerfile
- name: image-url
description: "镜像地址"
- name: image-tag
description: "image tag"
default: latest
workspaces:
- name: source
- name: dockerconfig # docker登陆信息的配置文件config.json
mountPath: /kaniko/.docker # config.json挂载目录
steps:
- name: build-and-push-image
image: gcr.io/kaniko-project/executor:debug # 用于在docker中打镜像的镜像
securityContext:
runAsUser: 0
env:
- name: DOCKER_CONFIG
value: /kaniko/.docker
command:
- /kaniko/executor
args:
- --dockerfile=$(params.dockerfile) # dockerfile文件位置
- --context=$(workspaces.source.path)/source # 上下文,也就是构建需要的文件,如代码文件等
- --destination=$(params.image-url):$(params.image-tag) # 构建出来的镜像直接推送,要给出推送的地址
#- --no-push # 打镜像,但不推送
---
# pipeline 把前面的task都串起来
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: source-to-image
spec:
params:
- name: git-url
- name: pathToContext
description: "workspace中构建镜像的路径,默认就 ."
default: .
- name: image-url
description: "image url"
- name: version
default: "v0.9"
type: string
description: "image version"
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-package
taskRef:
name: build-to-package
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: image-build
taskRef:
name: image-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-package
- generate-build-id
---
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: s2i-image-push-run-00010
spec:
pipelineRef:
name: source-to-image
params:
- name: git-url
value: https://gitee.com/mageedu/spring-boot-helloWorld.git
- name: image-url
value: zhuqiyang/spring-boot-helloworld
- name: version
value: v0.9.2
workspaces:
- name: codebase
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: managed-nfs-storage
- name: docker-config
secret:
secretName: docker-config # push镜像用的配置文件,账号和密码等信息,默认位置 /root/.docker/config.json
# 创建命令 kubectl create secret generic docker-config --from-file=/root/.docker/config.json打镜像并推送并部署到集群:
---
# ServiceAccount 和 ClusterRoleBinding 是为了将资源文件部署到k8s使用的
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
---
# 这个pvc是做缓存用的,在task里直接引用,而不是在pipelineRun里引用,需要手动创建
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: maven-cache
spec:
storageClassName: managed-nfs-storage
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
---
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: git-clone
spec:
description: "克隆代码到工作空间"
params:
- name: url
type: string
description: "仓库地址"
default: ""
- name: branch
type: string
description: "代码分支"
default: "main"
workspaces:
- name: source
description: "代码下载到挂载的工作空间磁盘上"
steps:
- name: git-clone
image: alpine/git:v2.36.1
script: git clone -b $(params.branch) -v $(params.url) $(workspaces.source.path)/source
---
# 打包
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: build-to-package
spec:
description: "编译"
workspaces:
- name: source
description: "代码下载目录"
steps:
- name: build
image: maven:3.8-openjdk-11-slim
workingDir: $(workspaces.source.path)/source
volumeMounts:
- name: m2
mountPath: /root/.m2
script: mvn clean install
volumes:
- name: m2
persistentVolumeClaim:
claimName: maven-cache # 这个pvc是做缓存用的,在task里直接引用,而不是在pipelineRun里引用,需要手动创建
---
# 镜像版本号和日期后缀
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: generate-build-id
spec:
params:
- name: version
type: string
description: "应用版本号"
results:
- name: datetime
description: "当前时间"
- name: buildId
description: "构建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)
---
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: image-build
spec:
description: "打镜像"
params:
- name: dockerfile
description: "dockerfile 文件"
default: Dockerfile
- name: image-url
description: "镜像地址"
- name: image-tag
description: "image tag"
default: latest
workspaces:
- name: source
- name: dockerconfig # docker登陆信息的配置文件config.json
mountPath: /kaniko/.docker # config.json挂载目录
steps:
- name: build-and-push-image
image: gcr.io/kaniko-project/executor:debug # 用于在docker中打镜像的镜像
securityContext:
runAsUser: 0
env:
- name: DOCKER_CONFIG
value: /kaniko/.docker
command:
- /kaniko/executor
args:
- --dockerfile=$(params.dockerfile) # dockerfile文件位置
- --context=$(workspaces.source.path)/source # 上下文,也就是构建需要的文件,如代码文件等
- --destination=$(params.image-url):$(params.image-tag) # 构建出来的镜像直接推送,要给出推送的地址
#- --no-push # 打镜像,但不推送
---
# 上面的 ServiceAccount 和 ClusterRoleBinding 就是为这里定义的
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: deploy-using-kubectl
spec:
workspaces:
- name: source
description: "git仓库的工作空间,里面有deployment部署文件"
params:
- name: deploy-config-file
description: "deployment部署文件路径"
- name: image-url
description: "镜像地址"
- name: image-tag
description: "镜像标签"
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)/source/deploy/$(params.deploy-config-file)"
- name: run-kubectl
image: lachlanevenson/k8s-kubectl # 这个镜像有kubectl命令
command: ["kubectl"]
args:
- "apply"
- "-f"
- "$(workspaces.source.path)/source/deploy/$(params.deploy-config-file)"
---
# pipeline 把前面的task都串起来
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: source-to-image
spec:
params:
- name: git-url
- name: pathToContext
description: "workspace中构建镜像的路径,默认就 ."
default: .
- name: deploy-config-file
description: "yaml文件名称"
default: all-in-one.yaml
- name: image-url
description: "image url"
- name: version
default: "v0.9"
type: string
description: "image version"
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-package
taskRef:
name: build-to-package
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: image-build
taskRef:
name: image-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-package
- 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:
- image-build
---
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: s2i-image-push-run-00015
spec:
serviceAccountName: default # 默认其他task的运行用户,默认可不写
taskRunSpecs:
- pipelineTaskName: deploy-to-cluster # 特指某个task,这个名称是pipeline中任务的名称,不是task名称
taskServiceAccountName: helloworld-admin # 指定task使用的账号
pipelineRef:
name: source-to-image
params:
- name: git-url
value: https://gitee.com/mageedu/spring-boot-helloWorld.git
- name: image-url
value: zhuqiyang/spring-boot-helloworld
- name: version
value: v0.9.2
workspaces:
- name: codebase
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: managed-nfs-storage
- name: docker-config
secret:
secretName: docker-config # push镜像用的配置文件,账号和密码等信息,默认位置 /root/.docker/config.json
# 创建命令 kubectl create secret generic docker-config --from-file=/root/.docker/config.json部署trigger
interceptor:对特定平台的事件源进行处理,处理完了给trigger,是个crd资源。
trigger:监控推送等事件,触发pipeline执行,会起个pod叫xx-event-listener。
triggerBinding:将事件中的值提取出并赋值给tiggerTemplate。
tiggerTemplate:pipelinerun的模板,模板的值就是triggerBinding传过来的。
Trigger部署文件:
kubectl apply -f https://storage.googleapis.com/tekton-releases/triggers/latest/release.yaml
部署事件源interceptor:
kubectl apply -f https://storage.googleapis.com/tekton-releases/triggers/latest/interceptors.yaml
查看资源:
]# kubectl api-resources --api-group=triggers.tekton.dev NAME SHORTNAMES APIGROUP NAMESPACED KIND clusterinterceptors ci triggers.tekton.dev false ClusterInterceptor clustertriggerbindings ctb triggers.tekton.dev false ClusterTriggerBinding eventlisteners el triggers.tekton.dev true EventListener triggerbindings tb triggers.tekton.dev true TriggerBinding triggers tri triggers.tekton.dev true Trigger triggertemplates tt triggers.tekton.dev true TriggerTemplate ]# kubectl get ClusterInterceptors NAME AGE bitbucket 3d21h cel 3d21h github 3d21h gitlab 3d21h
暴露事件接收服务 el-gitlab-event-listener:用来接收gitlab发来的事件,通过ingress或nodeport方式都可。
default el-gitlab-event-listener-65d4c47f8d-tfztp 1/1 Running 0 28m el-gitlab-event-listener ClusterIP 10.43.238.123 <none> 8080/TCP,9000/TCP 34m
暴露服务文件:每个流水线都要新建一个event listener,每个event listener都要去暴露。
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: el-gitlab-event-listener.ops.net namespace: default spec: rules: - host: el-gitlab-event-listener.ops.net http: paths: - backend: serviceName: el-gitlab-event-listener servicePort: 8080
在gitlab中设置webhook:


事件body:这些值可以在pipeline中引用。
{
"object_kind": "push",
"event_name": "push",
"before": "95790bf891e76fee5e1747ab589903a6a1f80f22",
"after": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
"ref": "refs/heads/master",
"checkout_sha": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
......
"project":{
"id": 15,
"name":"Diaspora",
"description":"",
"web_url":"http://example.com/mike/diaspora",
"avatar_url":null,
"git_ssh_url":"git@example.com:mike/diaspora.git",
"git_http_url":"http://example.com/mike/diaspora.git",
...
},
"repository":{
"name": "Diaspora",
"url": "git@example.com:mike/diaspora.git",
"description": "",
"homepage": "http://example.com/mike/diaspora",
"git_http_url":"http://example.com/mike/diaspora.git",
"git_ssh_url":"git@example.com:mike/diaspora.git",
"visibility_level":0
},
"commits": [
{
"id": "b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327",
"message": "Update Catalan translation to e38cb41.\n\nSee https://gitlab.com/gitlab-org/gitlab for more information",
"title": "Update Catalan translation to e38cb41.",
......
"added": ["CHANGELOG"],
"modified": ["app/controller/application.rb"],
"removed": []
}
],
"total_commits_count": 4
}流水线脚本:
apiVersion: v1
kind: Secret
metadata:
name: gitlab-webhook-token
type: Opaque
stringData:
# Generated by command "openssl rand -base64 12"
webhookToken: "DXeqvozMlTA67aQB" # 这个值就是在gitlab中webhook中要填写的secret令牌
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: tekton-triggers-gitlab-sa
secrets:
- name: gitlab-webhook-token
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: tekton-triggers-gitlab-minimal
rules:
# Permissions for every EventListener deployment to function
- apiGroups: ["triggers.tekton.dev"]
resources: ["eventlisteners", "triggerbindings", "triggertemplates"]
verbs: ["get"]
- apiGroups: [""]
# secrets are only needed for Github/Gitlab interceptors, serviceaccounts only for per trigger authorization
resources: ["configmaps", "secrets", "serviceaccounts"]
verbs: ["get", "list", "watch"]
# Permissions to create resources in associated TriggerTemplates
- apiGroups: ["tekton.dev"]
resources: ["pipelineruns", "pipelineresources", "taskruns"]
verbs: ["create"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: tekton-triggers-gitlab-binding
subjects:
- kind: ServiceAccount
name: tekton-triggers-gitlab-sa
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: tekton-triggers-gitlab-minimal
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: tekton-triggers-gitlab-minimal
rules:
- apiGroups: ["triggers.tekton.dev"]
resources: ["clusterinterceptors"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: tekton-triggers-gitlab-binding
subjects:
- kind: ServiceAccount
name: tekton-triggers-gitlab-sa
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: tekton-triggers-gitlab-minimal
---
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
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: maven-cache
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
storageClassName: managed-nfs-storage
volumeMode: Filesystem
---
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: git-clone
spec:
description: Clone the code repository to the workspace.
params:
- name: git-repo-url
type: string
description: git repository url to clone
- name: git-revision
type: string
description: git revision to checkout (branch, tag, sha, ref)
workspaces:
- name: source
description: The git repo will be cloned onto the volume backing this workspace
steps:
- name: git-clone
image: alpine/git:v2.36.1
script: |
git clone -v $(params.git-repo-url) $(workspaces.source.path)/source
cd $(workspaces.source.path)/source && git reset --hard $(params.git-revision)
---
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: build-to-package
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-openjdk-11-slim
workingDir: $(workspaces.source.path)/source
volumeMounts:
- name: m2
mountPath: /root/.m2
script: mvn clean install
volumes:
- name: m2
persistentVolumeClaim:
claimName: maven-cache
---
apiVersion: tekton.dev/v1beta1
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: 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)
---
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: image-build-and-push
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
workspaces:
- name: source
- name: dockerconfig
mountPath: /kaniko/.docker
steps:
- name: image-build-and-push
image: gcr.io/kaniko-project/executor:debug
securityContext:
runAsUser: 0
env:
- name: DOCKER_CONFIG
value: /kaniko/.docker
command:
- /kaniko/executor
args:
- --dockerfile=$(params.dockerfile)
- --context=$(workspaces.source.path)/source
- --destination=$(params.image-url):$(params.image-tag)
---
apiVersion: tekton.dev/v1beta1
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)/source/deploy/$(params.deploy-config-file)"
- name: run-kubectl
image: lachlanevenson/k8s-kubectl
command: ["kubectl"]
args:
- "apply"
- "-f"
- "$(workspaces.source.path)/source/deploy/$(params.deploy-config-file)"
---
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: source-to-image
spec:
params:
- name: git-repo-url
type: string
description: git repository url to clone
- name: git-revision
type: string
description: git revision to checkout (branch, tag, sha, ref)
default: main
- name: image-build-context
description: The path to the build context, used by Kaniko - within the workspace
default: .
- name: image-url
description: Url of image repository
- name: version
description: The version of the application
type: string
default: "v0.9"
- name: deploy-config-file
description: The path to the yaml file to deploy within the git source
default: all-in-one.yaml
#results:
# - name: datetime
# description: The current date and time
# - name: buildId
# description: The build ID
workspaces:
- name: codebase
- name: docker-config
tasks:
- name: git-clone
taskRef:
name: git-clone
params:
- name: git-repo-url
value: "$(params.git-repo-url)"
- name: git-revision
value: "$(params.git-revision)"
workspaces:
- name: source
workspace: codebase
- name: build-to-package
taskRef:
name: build-to-package
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: image-build-and-push
taskRef:
name: image-build-and-push
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:
- generate-build-id
- build-to-package
- 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:
- image-build-and-push
---
apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerBinding # 这里的值会传给TriggerTemplate,不需要传递值则可省略TriggerTemplate
metadata:
name: s2i-binding
spec:
params:
- name: git-revision
value: $(body.checkout_sha) # 这里的值引用的就是上面列出的事件body中的值
- name: git-repo-url
value: $(body.repository.git_http_url)
- name: image-url
value: zhuqiyang/spring-boot-helloworld
- name: version
value: v0.9
---
apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerTemplate
metadata:
name: s2i-tt
spec:
params: # 定义参数,这里的值是由TriggerBinding传过来的
- name: git-revision
- name: git-repo-url
- name: image-url
- name: version
resourcetemplates: # 资源模板
- apiVersion: tekton.dev/v1beta1
kind: PipelineRun # 可以是pipelinerun,也可以是taskrun
metadata:
generateName: s2i-trigger-run- # pipelineRun 名称前缀
spec:
serviceAccountName: default
## PipelineRun.Spec.ServiceAccountNames field is deprecated; use PipelineRun.Spec.TaskRunSpecs instead.
#serviceAccountNames:
# - taskName: deploy-to-cluster
# serviceAccountName: helloworld-admin
pipelineRef:
name: source-to-image # 引用的哪个pipeline
taskRunSpecs:
- pipelineTaskName: deploy-to-cluster
taskServiceAccountName: helloworld-admin
# taskPodTemplate:
# nodeSelector:
# disktype: ssd
params:
- name: git-repo-url
value: $(tt.params.git-repo-url) # 这里的tt指的就是TriggerTemplate
- name: git-revision
value: $(tt.params.git-revision)
- name: image-url
value: $(tt.params.image-url)
- name: version
value: $(tt.params.version)
workspaces:
- name: codebase
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: managed-nfs-storage
- name: docker-config
secret:
secretName: docker-config
---
apiVersion: triggers.tekton.dev/v1beta1
kind: EventListener
metadata:
name: s2i-listener
spec:
serviceAccountName: tekton-triggers-gitlab-sa
triggers: # 定义trigger,trigger可以单独定义,也可以内联定义,这里是内联定义
- name: gitlab-push-events-trigger
interceptors:
- ref:
name: "gitlab" # gitlab实例化的interceptor
params:
- name: "secretRef" # 访问gitlab使用的账号和密码
value:
secretName: gitlab-webhook-token
secretKey: webhookToken
- name: "eventTypes" # 监视仓库的那些事件
value:
- "Push Hook"
- "Tag Push Hook"
- "Merge Request Hook" # 事件列表
bindings: # 将triggerbinding和triggertemplate绑定起来
- ref: s2i-binding # triggerbinding
template:
ref: s2i-tt # triggertemplate
---tekton hub
这里有别人定义好的Task:
https://hub.tekton.dev/
catalog:
https://github.com/tektoncd/catalog
克隆代码:
https://github.com/tektoncd/catalog/tree/main/task/git-clone
