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