随笔 - 50  文章 - 0  评论 - 0  阅读 - 3203

tekton

tekton

1、概念

1.1 组件

1.1.1 pipline

使用k8s crd 来定义一个基础组件块,用来组件cicd

1.1.2 trigger

触发器,根据事件来触发cicd

1.1.3 CLI

交互式命令,与tekton进行交互

1.1.4 dashboard

一个图形化的界面,显示cicd

1.1.5 catalog

cicd的一个仓库

1.1.6 hub

访问catalog的一个web界面

1.1.7 Operator

基于k8s的自定义控制器,控制tekton

1.1.8 chain

生成,存储和签名的工具,使用pipeline的组件
# 工作原理
Tekton Chains的工作原理是部署一个在后台运行并监视TaskRun的控制器。当Tekton Pipelines执行您的任务时,Tekton Chains会监视操作,一旦操作成功完成,Chains控制器就会生成所生产工件的来源
记录了任务的输入:源存储库、分支、其他工件;以及输出:容器镜像、包等。这些信息作为元数据记录并签名。您可以将密钥存储在Kubernetes secrets中,或使用支持的密钥管理系统(GCP、AWS、Azure或Vault)对出处进行签名。然后,您可以将出处上传到指定的位置

1.2 使用

1.2.1 cli

1.2.2 kubectl cli

1.2.3 api

1.3 模型

image-20230919092416967

1.3.1 step

# 步骤
pipeline中的每一步操作称之为步骤

1.3.2 task

# 任务
按顺序执行的一些列步骤的集合,task的执行依赖于pod

1.3.3 pipelines

按顺序执行的task的集合,定义了如何执行

1.3.4 taskrun

可以自定义task的运行方式时间

1.3.5 pipelinerun

同taskrun,定义了执行所需要的参数及所用的sectet等类似于模版与实例的关系

1.4 工作原理

通过对step容器注入一个二进制文件来执行我们预定的命令
使用Kubernetes Annotations跟踪cicd的状态。这些注释通过Kubernetes Downward API以文件的形式投影在每个step容器中。二进制文件密切监视投射的文件,并且只有在特定注释显示为文件时才会启动所提供的命令。
例如,当您要求Tekton在一个任务中连续运行两个步骤时,注入到第二个步骤容器中的二进制文件将空闲等待,直到注释报告第一个步骤容器已成功完成
Tekton Pipelines安排一些容器在步骤容器前后自动运行,以支持特定的内置功能,例如检索输入资源和将输出上传到blob存储解决方案。您还可以通过taskRuns和pipelineRuns跟踪它们的运行状态。在运行步骤容器之前,系统还执行许多其他操作来设置环境

2、安装

2.1 pipeline

2.1.1 安装

# 下载yaml
curl -Lfs -o tektoncd-pipeline.yaml https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml
# 下载镜像并将其上传到自己的docker仓库
# 替换镜像为自己的docker仓库
sed -ir 's#gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/#quanheng.com/k8s/#g' *.yamls
# 安装
kubectl apply -f xx.yaml

2.1.2 task测试

# 运行task
---
apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
  name: hello-task-run
spec:
  taskRef:
    name: hello
apiVersion: tekton.dev/v1beta1
# 定义一个task
---
kind: Task
metadata:
  name: hello
spec:
  steps:
    - name: echo
      image: quanheng.com/k8s/alpine:v2
      script: |
        #!/bin/sh
        echo "Hello World"
# 查看pod和taskrun
(base) gu@python:~/k8s/yaml/tekton/task$ kubectl get pod 
NAME                                      READY   STATUS      RESTARTS       AGE
hello-task-run-pod                        0/1     Completed   0              2m17s
nfs-client-provisioner-5967bfdf67-nmbx2   1/1     Running     24 (23m ago)   3d17h
(base) gu@python:~/k8s/yaml/tekton/task$ kubectl get taskruns.tekton.dev 
NAME             SUCCEEDED   REASON      STARTTIME   COMPLETIONTIME
hello-task-run   True        Succeeded   5m25s       2m24s
(base) gu@python:~/k8s/tekton/pipeline-main/yaml$ kubectl logs hello-task-run-pod 
Defaulted container "step-echo" out of: step-echo, prepare (init), place-scripts (init)
Hello World

2.1.3 pipeline测试

2.1.3.1 安装cli

# 下载cli包
https://github.com/tektoncd/cli
# 解压并安装
unzip cli && cd cli && make amd64
# 做软连接
ln -sv /home/gu/k8s/tekton/cli-main/bin/tkn-linux-amd64 /usr/bin/tkn
# 将其作为kubectl plugin
ln -sv /home/gu/k8s/tekton/cli-main/bin/tkn-linux-amd64 /usr/bin/kubectl-tkn

2.1.3.2 测试

# 创建第二个task
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: goodbye
spec:
  params: # 指定必须传入一个字符串变量名称为username
  - name: username
    type: string
  steps:
    - name: goodbye
      image: quanheng.com/k8s/ubuntu:2
      script: |
        #!/bin/bash
        echo "Goodbye $(params.username)!"
# 创建pipeline
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: hello-goodbye
spec:
  params: # 指定必须传入一个字符串变量名称为username
  - name: username
    type: string
  tasks:
    - name: hello
      taskRef:
        name: hello
    - name: goodbye
      runAfter:
        - hello
      taskRef:
        name: goodbye
      params:
      - name: username
        value: $(params.username)
# 创建pipelinerun
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
  name: hello-goodbye-run
spec:
  pipelineRef:
    name: hello-goodbye
  params: #传入变量
  - name: username
    value: "Tekton"
# 验证
(base) gu@python:~/k8s/yaml/tekton/pipelines$ tkn pipelinerun logs hello-goodbye-run -f -n default
[hello : echo] Hello World

[goodbye : goodbye] Goodbye Tekton!

2.2 trigger

2.2.1 安装

# 下载
curl -LO https://storage.googleapis.com/tekton-releases/triggers/latest/interceptors.yaml
curl -LO https://storage.googleapis.com/tekton-releases/triggers/latest/release.yaml
# 替换文件镜像
sed -ir 's#gcr.io/tekton-releases/github.com/tektoncd/triggers/cmd/#quanheng.com/k8s/#g' *.yamls
# 安装
kubectl apply -f release.yaml
kubectl apply -f interceptors.yaml

2.2.2 工作模型

image-20230919143500180

# Event Listener
一个等待事件发生的监听器
    # Trigger Template(k8s API)
    当配置的事件发生时创建一个pipelinerun
    # Trigger Binding
    将数据传递给template,然后根据给定参数创建pipelinerun
    
# Cluster Interceptor
可以添加一个可选对象来验证和处理事件数据
# 在一个pod中运行一个可以创建pipelinerun的模版对象,当监听的事件发生时触发创建事件将数据传递给模版来创建pipelinerun

2.2.3 测试

# 创建一个template
apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerTemplate
metadata:
  name: hello-template
spec:
  params: # 传递一个变量
  - name: username
    default: "Kubernetes"
  resourcetemplates: # 资源模版
  - apiVersion: tekton.dev/v1beta1
    kind: PipelineRun # 创建一个pipelinerun
    metadata:
      generateName: hello-goodbye-run-
    spec:
      pipelineRef: # 引用哪个pipeline
        name: hello-goodbye
      params: # 使用变量
      - name: username
        value: $(tt.params.username) # tt=TriggerTemplate
# 创建binding(模版使用的数据)
apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerBinding
metadata:
  name: hello-binding
spec: 
  params: 
  - name: username
    value: $(body.username) # 接收到的变化,将其传递给template
# 创建一个事件监听器
apiVersion: triggers.tekton.dev/v1beta1
kind: EventListener
metadata:
  name: hello-listener
spec:
  serviceAccountName: tekton-robot # 指定sa
  triggers: # 指定binding数据和模版template
    - name: hello-trigger 
      bindings: 
      - ref: hello-binding
      template:
        ref: hello-template
# 定义使用的sa
apiVersion: v1
kind: ServiceAccount
metadata:
  name: tekton-robot
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: triggers-example-eventlistener-binding
subjects:
- kind: ServiceAccount
  name: tekton-robot
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: tekton-triggers-eventlistener-roles
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: triggers-example-eventlistener-clusterbinding
subjects:
- kind: ServiceAccount
  name: tekton-robot
  namespace: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: tekton-triggers-eventlistener-clusterroles
# 运行触发器
kubectl apply -f ./
# 提交一个有效负载
curl -v -H 'content-Type: application/json' -d '{"username": "guquanheng"}'  10.173.200.93:8080
{"eventListener":"hello-listener","namespace":"default","eventListenerUID":"30e562fd-d1c5-4980-a9e6-7872937cec0f","eventID":"85380be6-def2-4527-b150-cbad2e80aec8"}
# 查看触发的负载
(base) gu@python:~/k8s/yaml/tekton/trigger$ kubectl get pipelineruns
NAME                      SUCCEEDED   REASON      STARTTIME   COMPLETIONTIME
hello-goodbye-run         True        Succeeded   63m         62m
hello-goodbye-run-v25g4   True        Succeeded   2m20s       2m5s
# 检查管道运行日志。名称是自动生成的
(base) gu@python:~/k8s/yaml/tekton/trigger$ tkn pipelinerun logs hello-goodbye-run-v25g4
[hello : echo] Hello World

[goodbye : goodbye] Goodbye guquanheng!

2.3 dashboard

2.3.1 安装

# 下载安装文件
curl -LO https://storage.googleapis.com/tekton-releases/dashboard/latest/release-full.yaml
# 更改镜像为自己镜像
sed -ir 's#gcr.io/tekton-releases/github.com/tektoncd/triggers/cmd/#quanheng.com/k8s/#g' *.yamls
# 使用istio进行服务暴露
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: tekton-dashboard-vs
  namespace: tekton-pipelines
spec:
  gateways:
    - istio-system/kiali-gateway 
  hosts:
    - '*'
  http:
    - match:
        - port: 18686
      route:
        - destination:
            host: tekton-dashboard
            port:
              number: 9097

2.3.2 测试

image-20230919160523866

image-20230919160615279

3、使用

3.1 从git仓库拉取代码

# 安装git-clone task
apiVersion: tekton.dev/v1
kind: Task
metadata:
  annotations:
    tekton.dev/categories: Git
    tekton.dev/displayName: git clone
    tekton.dev/pipelines.minVersion: 0.38.0
    tekton.dev/platforms: linux/amd64,linux/s390x,linux/ppc64le,linux/arm64
    tekton.dev/tags: git
  creationTimestamp: "2023-09-19T09:39:27Z"
  generation: 1
  labels:
    app.kubernetes.io/version: "0.9"
    hub.tekton.dev/catalog: tekton
  name: git-clone
  namespace: default
  resourceVersion: "6936599"
  uid: 7760d316-306a-4ffe-aa90-7f4e2160f951
spec:
  description: |-
    These Tasks are Git tasks to work with repositories used by other tasks in your Pipeline.
    The git-clone Task will clone a repo from the provided url into the output Workspace. By default the repo will be cloned into the root of your Workspace. You can clone into a subdirectory by setting this Task's subdirectory param. This Task also supports sparse checkouts. To perform a sparse checkout, pass a list of comma separated directory patterns to this Task's sparseCheckoutDirectories param.
  params:
  - description: Repository URL to clone from.
    name: url
    type: string
  - default: ""
    description: Revision to checkout. (branch, tag, sha, ref, etc...)
    name: revision
    type: string
  - default: ""
    description: Refspec to fetch before checking out revision.
    name: refspec
    type: string
  - default: "true"
    description: Initialize and fetch git submodules.
    name: submodules
    type: string
  - default: "1"
    description: Perform a shallow clone, fetching only the most recent N commits.
    name: depth
    type: string
  - default: "true"
    description: Set the `http.sslVerify` global git config. Setting this to `false`
      is not advised unless you are sure that you trust your git remote.
    name: sslVerify
    type: string
  - default: ca-bundle.crt
    description: file name of mounted crt using ssl-ca-directory workspace. default
      value is ca-bundle.crt.
    name: crtFileName
    type: string
  - default: ""
    description: Subdirectory inside the `output` Workspace to clone the repo into.
    name: subdirectory
    type: string
  - default: ""
    description: Define the directory patterns to match or exclude when performing
      a sparse checkout.
    name: sparseCheckoutDirectories
    type: string
  - default: "true"
    description: Clean out the contents of the destination directory if it already
      exists before cloning.
    name: deleteExisting
    type: string
  - default: ""
    description: HTTP proxy server for non-SSL requests.
    name: httpProxy
    type: string
  - default: ""
    description: HTTPS proxy server for SSL requests.
    name: httpsProxy
    type: string
  - default: ""
    description: Opt out of proxying HTTP/HTTPS requests.
    name: noProxy
    type: string
  - default: "true"
    description: Log the commands that are executed during `git-clone`'s operation.
    name: verbose
    type: string
  - default: gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/git-init:v0.40.2
    description: The image providing the git-init binary that this Task runs.
    name: gitInitImage
    type: string
  - default: /home/git
    description: |
      Absolute path to the user's home directory.
    name: userHome
    type: string
  results:
  - description: The precise commit SHA that was fetched by this Task.
    name: commit
    type: string
  - description: The precise URL that was fetched by this Task.
    name: url
    type: string
  - description: The epoch timestamp of the commit that was fetched by this Task.
    name: committer-date
    type: string
  steps:
  - computeResources: {}
    env:
    - name: HOME
      value: $(params.userHome)
    - name: PARAM_URL
      value: $(params.url)
    - name: PARAM_REVISION
      value: $(params.revision)
    - name: PARAM_REFSPEC
      value: $(params.refspec)
    - name: PARAM_SUBMODULES
      value: $(params.submodules)
    - name: PARAM_DEPTH
      value: $(params.depth)
    - name: PARAM_SSL_VERIFY
      value: $(params.sslVerify)
    - name: PARAM_CRT_FILENAME
      value: $(params.crtFileName)
    - name: PARAM_SUBDIRECTORY
      value: $(params.subdirectory)
    - name: PARAM_DELETE_EXISTING
      value: $(params.deleteExisting)
    - name: PARAM_HTTP_PROXY
      value: $(params.httpProxy)
    - name: PARAM_HTTPS_PROXY
      value: $(params.httpsProxy)
    - name: PARAM_NO_PROXY
      value: $(params.noProxy)
    - name: PARAM_VERBOSE
      value: $(params.verbose)
    - name: PARAM_SPARSE_CHECKOUT_DIRECTORIES
      value: $(params.sparseCheckoutDirectories)
    - name: PARAM_USER_HOME
      value: $(params.userHome)
    - name: WORKSPACE_OUTPUT_PATH
      value: $(workspaces.output.path)
    - name: WORKSPACE_SSH_DIRECTORY_BOUND
      value: $(workspaces.ssh-directory.bound)
    - name: WORKSPACE_SSH_DIRECTORY_PATH
      value: $(workspaces.ssh-directory.path)
    - name: WORKSPACE_BASIC_AUTH_DIRECTORY_BOUND
      value: $(workspaces.basic-auth.bound)
    - name: WORKSPACE_BASIC_AUTH_DIRECTORY_PATH
      value: $(workspaces.basic-auth.path)
    - name: WORKSPACE_SSL_CA_DIRECTORY_BOUND
      value: $(workspaces.ssl-ca-directory.bound)
    - name: WORKSPACE_SSL_CA_DIRECTORY_PATH
      value: $(workspaces.ssl-ca-directory.path)
    image: $(params.gitInitImage)
    name: clone
    script: |
      #!/usr/bin/env sh
      set -eu

      if [ "${PARAM_VERBOSE}" = "true" ] ; then
        set -x
      fi

      if [ "${WORKSPACE_BASIC_AUTH_DIRECTORY_BOUND}" = "true" ] ; then
        cp "${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/.git-credentials" "${PARAM_USER_HOME}/.git-credentials"
        cp "${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/.gitconfig" "${PARAM_USER_HOME}/.gitconfig"
        chmod 400 "${PARAM_USER_HOME}/.git-credentials"
        chmod 400 "${PARAM_USER_HOME}/.gitconfig"
      fi

      if [ "${WORKSPACE_SSH_DIRECTORY_BOUND}" = "true" ] ; then
        cp -R "${WORKSPACE_SSH_DIRECTORY_PATH}" "${PARAM_USER_HOME}"/.ssh
        chmod 700 "${PARAM_USER_HOME}"/.ssh
        chmod -R 400 "${PARAM_USER_HOME}"/.ssh/*
      fi

      if [ "${WORKSPACE_SSL_CA_DIRECTORY_BOUND}" = "true" ] ; then
         export GIT_SSL_CAPATH="${WORKSPACE_SSL_CA_DIRECTORY_PATH}"
         if [ "${PARAM_CRT_FILENAME}" != "" ] ; then
            export GIT_SSL_CAINFO="${WORKSPACE_SSL_CA_DIRECTORY_PATH}/${PARAM_CRT_FILENAME}"
         fi
      fi
      CHECKOUT_DIR="${WORKSPACE_OUTPUT_PATH}/${PARAM_SUBDIRECTORY}"

      cleandir() {
        # Delete any existing contents of the repo directory if it exists.
        #
        # We don't just "rm -rf ${CHECKOUT_DIR}" because ${CHECKOUT_DIR} might be "/"
        # or the root of a mounted volume.
        if [ -d "${CHECKOUT_DIR}" ] ; then
          # Delete non-hidden files and directories
          rm -rf "${CHECKOUT_DIR:?}"/*
          # Delete files and directories starting with . but excluding ..
          rm -rf "${CHECKOUT_DIR}"/.[!.]*
          # Delete files and directories starting with .. plus any other character
          rm -rf "${CHECKOUT_DIR}"/..?*
        fi
      }

      if [ "${PARAM_DELETE_EXISTING}" = "true" ] ; then
        cleandir || true
      fi

      test -z "${PARAM_HTTP_PROXY}" || export HTTP_PROXY="${PARAM_HTTP_PROXY}"
      test -z "${PARAM_HTTPS_PROXY}" || export HTTPS_PROXY="${PARAM_HTTPS_PROXY}"
      test -z "${PARAM_NO_PROXY}" || export NO_PROXY="${PARAM_NO_PROXY}"

      git config --global --add safe.directory "${WORKSPACE_OUTPUT_PATH}"
      /ko-app/git-init \
        -url="${PARAM_URL}" \
        -revision="${PARAM_REVISION}" \
        -refspec="${PARAM_REFSPEC}" \
        -path="${CHECKOUT_DIR}" \
        -sslVerify="${PARAM_SSL_VERIFY}" \
        -submodules="${PARAM_SUBMODULES}" \
        -depth="${PARAM_DEPTH}" \
        -sparseCheckoutDirectories="${PARAM_SPARSE_CHECKOUT_DIRECTORIES}"
      cd "${CHECKOUT_DIR}"
      RESULT_SHA="$(git rev-parse HEAD)"
      EXIT_CODE="$?"
      if [ "${EXIT_CODE}" != 0 ] ; then
        exit "${EXIT_CODE}"
      fi
      RESULT_COMMITTER_DATE="$(git log -1 --pretty=%ct)"
      printf "%s" "${RESULT_COMMITTER_DATE}" > "$(results.committer-date.path)"
      printf "%s" "${RESULT_SHA}" > "$(results.commit.path)"
      printf "%s" "${PARAM_URL}" > "$(results.url.path)"
    securityContext:
      runAsNonRoot: true
      runAsUser: 65532
  workspaces:
  - description: The git repo will be cloned onto the volume backing this Workspace.
    name: output
  - description: |
      A .ssh directory with private key, known_hosts, config, etc. Copied to
      the user's home before git commands are executed. Used to authenticate
      with the git remote when performing the clone. Binding a Secret to this
      Workspace is strongly recommended over other volume types.
    name: ssh-directory
    optional: true
  - description: |
      A Workspace containing a .gitconfig and .git-credentials file. These
      will be copied to the user's home before any git commands are run. Any
      other files in this Workspace are ignored. It is strongly recommended
      to use ssh-directory over basic-auth whenever possible and to bind a
      Secret to this Workspace over other volume types.
    name: basic-auth
    optional: true
  - description: |
      A workspace containing CA certificates, this will be used by Git to
      verify the peer with when fetching or pushing over HTTPS.
    name: ssl-ca-directory
    optional: true
---
# 创建一个pipeline
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: clone-read
spec:
  description: | 
    This pipeline clones a git repo, then echoes the README file to the stout.
  params:   # 添加一个参数来表示git仓库
  - name: repo-url
    type: string
    description: The git repo URL to clone from.
  workspaces: # 添加一个工作区用来存储代码
  - name: shared-data
    description: | 
      This workspace contains the cloned repo files, so they can be read by the next task.
  - name: git-credentials # 存储ssh秘钥
    description: My ssh credentials
  tasks: # 使用上述参数来定义一个task
  - name: fetch-source # colne 仓库
    taskRef:
      name: git-clone
    workspaces:
    - name: output
      workspace: shared-data
    - name: ssh-directory
      workspace: git-credentials
    params:
    - name: url
      value: $(params.repo-url)
  - name: show-readme # clone后查看README.md
    runAfter: ["fetch-source"] # 定义在clone后执行
    taskRef: # 引用哪个task
      name: show-readme
    workspaces: # 使用哪个工作区
    - name: source
      workspace: shared-data
---
# 创建一个pipelinerun(实例化上面pipeline定义的参数)
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
  generateName: clone-read-run-
spec:
  pipelineRef:
    name: clone-read
  podTemplate:
    securityContext:
      fsGroup: 65532
  workspaces: # 实例化工作区,使用一个pvc来存储代码,
  - name: shared-data
    volumeClaimTemplate:
      spec:
        accessModes:
        - ReadWriteOnce
        resources:
          requests:
            storage: 1Gi
        storageClassName: nfs # 指定一个类来实现pvc
  - name: git-credentials # 指定git仓库的secret
    secret:
      secretName: git-credentials
  params:  # 设置git仓库url
  - name: repo-url
    value: git@172.31.3.155:guquanheng/argo.git
# 创建一个secret用来访问git私有仓库
# config格式
Host 172.31.3.155
  Hostname 172.31.3.155
  PreferredAuthentications publickey
  IdentityFile ~/.ssh/id_rsa
---
apiVersion: v1
kind: Secret
metadata:
  name: git-credentials
type: kubernetes.io/ssh-auth
data:
  id_rsa:  LS0tLS1CRUdJTiBPUEVOU1NIIFBSSVZBVEUgS0VZLS0tLS0KYjNCbGJuTnphQzFyWlhrdGRqRUFBQUFBQkc1dmJtVUFBQUFFYm05dVpRQUFBQUFBQUFBQkFBQUJsd0FBQUFkemMyZ3RjbgpOaEFBQUFBd0VBQVFBQUFZRUFuQ21mazNYOFhseVJZaFNZdExGM2U3cWkwS1M5dlJEaTY1d1Y3QUovSzFnWFlDOHZyK2RzCjg3ZDVndU5YdFcrQndkbzJCNjRTVjZINW9XdFhlS0FNakRadU12am1lcW9UZndVa2c1U2kvRzN4c28wNlhYalhiTUJqYjkKVkMwdzA5NllwbUJNWjFqNDBhSUFHRGFub3N0eWdkUWRjeHpCVCt5NnFuSFIwLzJ4MmplL1N3NkpkOE5DYzVkZERCa1R5SQpHcTJRb2x0ZlVqNG5yUUlhRzVGVGl1STZqMW1JN0llL2JERGZKbzNrY1U1dUtTanVNVjB0d0lhNzhsM2V5UDhveFcvSG5aCmZNdHhka2ZRakMrdTkzdnJtWGhMdW84bFQ2NC9XOVlrLzhHOGdtS25vS3AyTC9jbmIrZFNnZkZ3OEZ6eEZTSjM5dWdRSTMKdWdwR0I1SVZTeDV1SmQwZEJqZmJ5SkdIaGEwU0ZHL21FbTdGa0E1cFBGVGxOTFZjMG9XQm50OG5WanozbGxKUUVTTlNQMgpPb0tlSUhpa0RPUnN5Y3F0eUdJK3cwVFJLUDh0YWpLdWZKUjZVWlRFRktyVVZYSUg3bnE5L3huTUxyeFI3ZHVpQjVkbWY4CjhqdVpxc2NHaEdlL0NqY1VaeE4vd29HR2kxQXV0N0w5US85NXBab25BQUFGZ0F3T2tCY01EcEFYQUFBQUIzTnphQzF5YzIKRUFBQUdCQUp3cG41TjEvRjVja1dJVW1MU3hkM3U2b3RDa3ZiMFE0dXVjRmV3Q2Z5dFlGMkF2TDYvbmJQTzNlWUxqVjdWdgpnY0hhTmdldUVsZWgrYUZyVjNpZ0RJdzJiakw0NW5xcUUzOEZKSU9Vb3Z4dDhiS05PbDE0MTJ6QVkyL1ZRdE1OUGVtS1pnClRHZFkrTkdpQUJnMnA2TExjb0hVSFhNY3dVL3N1cXB4MGRQOXNkbzN2MHNPaVhmRFFuT1hYUXdaRThpQnF0a0tKYlgxSSsKSjYwQ0dodVJVNHJpT285WmlPeUh2Mnd3M3lhTjVIRk9iaWtvN2pGZExjQ0d1L0pkM3NqL0tNVnZ4NTJYekxjWFpIMEl3dgpydmQ3NjVsNFM3cVBKVSt1UDF2V0pQL0J2SUppcDZDcWRpLzNKMi9uVW9IeGNQQmM4UlVpZC9ib0VDTjdvS1JnZVNGVXNlCmJpWGRIUVkzMjhpUmg0V3RFaFJ2NWhKdXhaQU9hVHhVNVRTMVhOS0ZnWjdmSjFZODk1WlNVQkVqVWo5anFDbmlCNHBBemsKYk1uS3JjaGlQc05FMFNqL0xXb3lybnlVZWxHVXhCU3ExRlZ5Qis1NnZmOFp6QzY4VWUzYm9nZVhabi9QSTdtYXJIQm9Sbgp2d28zRkdjVGY4S0Job3RRTHJleS9VUC9lYVdhSndBQUFBTUJBQUVBQUFHQU94QVhGYnV6SnJGV0gwVncrQzZDNVY0U2hGCjA2a2c2WDlNckZFODFoOGEvUXI0VkpRUHVEbnE0UEhDMEdHRTVEUW1GWXZCRGZTUnV2QVpsS3JRbkRsU2hsQjR4U0I2VFoKMk5uR0ZLb2I5dU5TWGRqQ2NXWHAvR3pMYnhtMnU0SXZuMnZENkJ4empFYXUwZG9nclIzbVdhT25aU2FSNUFFdzJURURJYQpUVmFQZE54TzBvRitCcmpvSWpYbWNGUHZ3bzhnWWhSUGJRRjVnQWc1UGU4ZnhHSDZvdXdkYjRUWldPRmNwcUsvZlFwZlltCi9oUkgrbzJtWjBIT1JmMnc3RTVzc3FJZHFIRE4wVGgvbW5LTEc1MEVBRUsraGVJTmloMWxNaU4xR0ZNZFpDZTBXQ1ZpNEwKWXdlWTAyZ1E1a29FYXV3TXM5RTlTcHVuTTk5QXFPL3lwQmw5a3FyT0M4NHRSejZSbzYyOUF1aUVjbkhXQ1JXMUI5MDA5SgpQamZDT0JYdTBmL1hEcnhaSzRlNVdkZ0tWM2VPRlFXTC9jK2tBYjNVWkRYRFBmMWlsL05ETWpsYUlKYWpVVWhrOTl3dUcyCi9lblhXQ2NFdkNoS0ZqN096NWwya2F0NHVmU2ZtbjAremhOWklzMUhXT0E1KzRzSkN4dkxPNWcvdVRGampZQzY3UkFBQUEKd1FDSmdNUXp4QjBvUTE2NGZObS9MRzVaV3dBb3FTb3hnSDI2d05xUXQxY3phQ2VDSmQwNExlaDViMUxTQzRIQTBxSjV4aAp4RDZ3ZVk3K2pEUSt1N1dXSEFhMmM2MWh1ZGFjSFByTEVnRFRZRHBBNnhxZnF5ZTdhVVFIckpYWkEwUWU3RHpYd2FCeGkwClhMc21Xd1NUTVRySXpqbjZuU0hWaFI1bGJwRkJCNDFEUkdEZDkrc2d4Ni9FR2Q1dkE1T3FKcWs2bGpnQThPRlM1VXFYQW8Kc1FTbTJEbWlQQTBKL21uSTNYdEozdkpjcElKQ3BnODNLWHFDUm9EQTYzTWMxS1ZOQUFBQURCQU5YTmpxTnA5QXFGRWZGWQplTGVaSVNYTEJNZ0JtaTkzYXB3Tm1BVDUySkI0eWN5RnlRSm53dlRYR0NtbURFb0V6R2xISTlVVDUwUzhlVkgxWmlqS25TCnZZVEsyODQ0U3MrdFRCRkdFaGFoVXkrdXhhci9veUJCSHhHS1VsMGc1RVEyK0tnVnROZ3drUFViMWM1dkxtbnNWdVEwbVYKUGtRb2sramgrbi9uZ25IY2J0VjZ2MnpuYlg1NXppMVkrZnhRUjRKNXZCa0VVMlFnRXpLWlBwQWxKdTFzeVdHS1dhMjNyQQpLdVI1ZVpBbmswMjhjdFpNQmwrc0Zza092UGFuMGNid0FBQU1FQXV2dkdDcVhBY2NLOTdTY0QxYmJ6UjlHSWVad0tSdkRICjRaeVMxL1ZtUXA3ZThnVGZ1VVowQWFGREpyTS9rTjJvbXNNYmk0RnE5Mi9JN1lqYmc4R0YxaTlxQUpYYzZPR0RPdjVMMEQKVHJEVXd3aVgwYUpDbGVSMlBES3R6Yy9ValRHdDAwV3lMdVZKZlVMdVBIbXV1WG1sajNIK2M2cjlKL25LUXk0bXlHd1ExWAp0QlI5RW55Z1BaYll1YWtlV0tIcmpHdUZqWnYxVFlmVklUN2IrMGdjRnVwV1o5c25GT3V3aU1aSGpONEVIbW43ak1OMFR5Cmo1YW1ieUF2RHhLNm5KQUFBQUNXZDFRSEI1ZEdodmJnRT0KLS0tLS1FTkQgT1BFTlNTSCBQUklWQVRFIEtFWS0tLS0tCg==
  known_hosts: CnwxfFlESjAzUVJhNVVZS3dFbUYvZ0FOTjl5YWxTZz18NC9XVzQxRTAwa3BwN2JXbmJrbWo3U2xYRTVFPSBzc2gtZWQyNTUxOSBBQUFBQzNOemFDMWxaREkxTlRFNUFBQUFJTG9sRlcrU3RIdkQ4MGhEQldyS3hKWXdlL2h0MGE5Qnppa1FuYVJhUGZqWQp8MXxtK1NrOXBkK1p0K3QrK2NlRU4raFBMY0N6aUU9fDZWUHVMVVgxZDRsNGNvbktvN1dlL0IzazVFbz0gZWNkc2Etc2hhMi1uaXN0cDI1NiBBQUFBRTJWalpITmhMWE5vWVRJdGJtbHpkSEF5TlRZQUFBQUlibWx6ZEhBeU5UWUFBQUJCQkZxcU82S3MyWmR2K0tXNGNMc0p1bEQ0QmpsajFDdnNScmtmanNqQkkrQkZXWDd4THpCZVNJM0pFT1BPYjFjbHlrUmRKMW1Gekt0a0JRNHBDTGRidVRJPQp8MXw0dW12TDAzeEZmL1c5Z1pNV3RXQTVVZGJ6dDg9fG1CLzUydVNUVnArdWNsQ2RvanFpMXpwRWMzMD0gc3NoLWVkMjU1MTkgQUFBQUMzTnphQzFsWkRJMU5URTVBQUFBSUxvbEZXK1N0SHZEODBoREJXckt4Sll3ZS9odDBhOUJ6aWtRbmFSYVBmalkKfDF8L3ZMUThVOEx3MW11aXg5ODhlZ0U4VGFtYkVBPXxtWE9ZYXJiVXg5UEI2RDl3RGFpVWVRWkRkYWc9IHNzaC1lZDI1NTE5IEFBQUFDM056YUMxbFpESTFOVEU1QUFBQUlQc0I4aTgvcmxkamUweUtpSEZvTTQ1bEk5RUhWUkdBUU4zSDN2YjFSTUcvCnwxfGFOcnV5UXB4T1FKSk9reVZ1eG9DOWkxVVdVbz18c2ZPZFhwc0FWZ3ZWeXJTWHBXdnIrNHpnRVdnPSBlY2RzYS1zaGEyLW5pc3RwMjU2IEFBQUFFMlZqWkhOaExYTm9ZVEl0Ym1semRIQXlOVFlBQUFBSWJtbHpkSEF5TlRZQUFBQkJCTDg1RFNoaW0wUUFZZ0Jockw3UFYzaDFNa3dCaU42SnpVa3laQndWZGs3aWRRb3pLZHRDdlV0Q0U1SWZvY28zNDY2RERRZHBraGplVjgzMXhQWjFFSEk9CnwxfFpUeG1OVkE1WTczd3dxTDFnS2VMRTY0UUFZbz18SlFWeXpSaDYyaXdNSDBDUzZlbkJTSHVXL3BvPSBzc2gtZWQyNTUxOSBBQUFBQzNOemFDMWxaREkxTlRFNUFBQUFJUHNCOGk4L3JsZGplMHlLaUhGb000NWxJOUVIVlJHQVFOM0gzdmIxUk1HLwp8MXxDZlJsTjM3MWtwSVlOdmIxeTJoWkhtZFNSeWs9fHhGTjdMRGh1QVJUZkZvZjZTMzVJRjI5cUpmTT0gc3NoLWVkMjU1MTkgQUFBQUMzTnphQzFsWkRJMU5URTVBQUFBSUxvbEZXK1N0SHZEODBoREJXckt4Sll3ZS9odDBhOUJ6aWtRbmFSYVBmalkKfDF8bzgveUFOSHVQYis5UG1qeGpxcllkWFlYOEFzPXx5R2FpbTZFa1ZnNVNtb1psektRS1FhYnluazQ9IHNzaC1lZDI1NTE5IEFBQUFDM056YUMxbFpESTFOVEU1QUFBQUlMb2xGVytTdEh2RDgwaERCV3JLeEpZd2UvaHQwYTlCemlrUW5hUmFQZmpZCnwxfFkvMmFHa0ZuYU5aaEMwVExMcnRnRGVOZEo3cz18MWxVcUJSdkZuYm85NFRBSUhFeTRrMitQYjJVPSBzc2gtZWQyNTUxOSBBQUFBQzNOemFDMWxaREkxTlRFNUFBQUFJSDZ0V2NzYkdTa0tBS2kvdzJQUWlSdmRJc3BxNThMU0ZmQVdsSGhEYSt2NQp8MXxWeU9oMGEvYnUrN3h0blk0MndEbS81ZUQxYkU9fGh4UDdIMW5tSXFvdWh1REVjajgwUkFmZVVEQT0gZWNkc2Etc2hhMi1uaXN0cDI1NiBBQUFBRTJWalpITmhMWE5vWVRJdGJtbHpkSEF5TlRZQUFBQUlibWx6ZEhBeU5UWUFBQUJCQkhEdVBuRERRcyt1QzNOTVdJTU4yT1cyWHo1KzljK2l4dWhSK1JQZkZCaFYzVWMxYnB0TnJZTk5JSGFXbFBQcTVHWXFaU09jekdxVnlwMGVDNGhMdzlBPQo=
  config: SG9zdCAxNzIuMzEuMy4xNTUKICBIb3N0bmFtZSAxNzIuMzEuMy4xNTUKICBQcmVmZXJyZWRBdXRoZW50aWNhdGlvbnMgcHVibGlja2V5CiAgSWRlbnRpdHlGaWxlIH4vLnNzaC9pZF9yc2EK
# 创建一个task
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: show-readme
spec:
  description: Read and display README file.
  workspaces:
  - name: source
  steps:
  - name: read
    image: alpine:latest
    script: | 
      #!/usr/bin/env sh
      cat $(workspaces.source.path)/README.md
# 查看结果 
(base) gu@python:~/k8s/yaml/tekton/use/gitpull$ tkn pipelinerun logs  clone-read-run-xr2hn -f
[fetch-source : clone] + '[' false '=' true ]
[fetch-source : clone] + '[' true '=' true ]
[fetch-source : clone] + cp -R /workspace/ssh-directory /home/git/.ssh
[fetch-source : clone] + chmod 700 /home/git/.ssh
[fetch-source : clone] + chmod -R 400 /home/git/.ssh/config /home/git/.ssh/id_rsa /home/git/.ssh/known_hosts
[fetch-source : clone] + '[' false '=' true ]
[fetch-source : clone] + CHECKOUT_DIR=/workspace/output/
[fetch-source : clone] + '[' true '=' true ]
[fetch-source : clone] + cleandir
[fetch-source : clone] + '[' -d /workspace/output/ ]
[fetch-source : clone] + rm -rf '/workspace/output//*'
[fetch-source : clone] + rm -rf '/workspace/output//.[!.]*'
[fetch-source : clone] + rm -rf '/workspace/output//..?*'
[fetch-source : clone] + test -z 
[fetch-source : clone] + test -z 
[fetch-source : clone] + test -z 
[fetch-source : clone] + git config --global --add safe.directory /workspace/output
[fetch-source : clone] + /ko-app/git-init '-url=git@172.31.3.155:guquanheng/argo.git' '-revision=' '-refspec=' '-path=/workspace/output/' '-sslVerify=true' '-submodules=true' '-depth=1' '-sparseCheckoutDirectories='
[fetch-source : clone] {"level":"warn","ts":1695180336.8236978,"caller":"git/git.go:271","msg":"URL(\"git@172.31.3.155:guquanheng/argo.git\") appears to need SSH authentication but no SSH credentials have been provided"}
[fetch-source : clone] {"level":"info","ts":1695180338.4686594,"caller":"git/git.go:176","msg":"Successfully cloned git@172.31.3.155:guquanheng/argo.git @ b66baa6c468d7ca3eff27e72e3820e4a7ff0926f (grafted, HEAD) in path /workspace/output/"}
[fetch-source : clone] {"level":"info","ts":1695180338.5491166,"caller":"git/git.go:215","msg":"Successfully initialized and updated submodules in path /workspace/output/"}
[fetch-source : clone] + cd /workspace/output/
[fetch-source : clone] + git rev-parse HEAD
[fetch-source : clone] + RESULT_SHA=b66baa6c468d7ca3eff27e72e3820e4a7ff0926f
[fetch-source : clone] + EXIT_CODE=0
[fetch-source : clone] + '[' 0 '!=' 0 ]
[fetch-source : clone] + git log -1 '--pretty=%ct'
[fetch-source : clone] + RESULT_COMMITTER_DATE=1695180275
[fetch-source : clone] + printf '%s' 1695180275
[fetch-source : clone] + printf '%s' b66baa6c468d7ca3eff27e72e3820e4a7ff0926f
[fetch-source : clone] + printf '%s' git@172.31.3.155:guquanheng/argo.git

[show-readme : read] this is test pipeline

3.2 创建并上传镜像到仓库

# kaniko使用教程 
https://juejin.cn/post/7217665415710081081#heading-31
# 创建一个task用来实现对镜像的打包及上传
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: kaniko
  labels:
    app.kubernetes.io/version: "0.6"
  annotations:
    tekton.dev/pipelines.minVersion: "0.17.0"
    tekton.dev/categories: Image Build
    tekton.dev/tags: image-build
    tekton.dev/displayName: "Build and upload container image using Kaniko"
    tekton.dev/platforms: "linux/amd64,linux/arm64,linux/ppc64le"
spec:
  description: >-
    This Task builds a simple Dockerfile with kaniko and pushes to a registry.
    This Task stores the image name and digest as results, allowing Tekton Chains to pick up
    that an image was built & sign it.
  params:
    - name: IMAGE
      description: Name (reference) of the image to build.
    - name: DOCKERFILE
      description: Path to the Dockerfile to build.
      default: ./Dockerfile
    - name: CONTEXT
      description: The build context used by Kaniko.
      default: ./
    - name: EXTRA_ARGS
      type: array
      default: []
    - name: BUILDER_IMAGE
      description: The image on which builds will run (default is v1.5.1)
      #default: quanheng.com/k8s/executor:v1.5.2
      # 注意,此处无法对私有仓库进行解析,需要提前下载好镜像后docker load进去或者使用公网地址进行下载
      default: registry.cn-hangzhou.aliyuncs.com/weiyigeek/kaniko-executor:latest
  workspaces:
    - name: source
      description: Holds the context and Dockerfile
    - name: docker-credentials
      description: Includes a docker `config.json`
      optional: true
      mountPath: /kaniko/.docker
  results:
    - name: IMAGE_DIGEST
      description: Digest of the image just built.
    - name: IMAGE_URL
      description: URL of the image just built.
  steps:
    - name: build-and-push
      workingDir: $(workspaces.source.path)
      image: $(params.BUILDER_IMAGE)
      args:
        - $(params.EXTRA_ARGS)
        - --insecure # 使用http与仓库进行通信,使用私有仓库必须用此参数
        - --skip-tls-verify # push忽略tls认证
        - --skip-tls-verify-pull # pull忽略tls
        - --dockerfile=$(params.DOCKERFILE)
        - --context=$(workspaces.source.path)/$(params.CONTEXT) # The user does not need to care the workspace and the source.
        - --destination=$(params.IMAGE)
        - --digest-file=$(results.IMAGE_DIGEST.path)
      # kaniko assumes it is running as root, which means this example fails on platforms
      # that default to run containers as random uid (like OpenShift). Adding this securityContext
      # makes it explicit that it needs to run as root.
      securityContext:
        runAsUser: 0
      volumeMounts: # 依赖hosts解析需要将本地hosts挂载进pod
        - name: hosts
          mountPath: /etc/hosts
        - name: host
          mountPath: /workspace/source/hosts
    - name: write-url
      image: quanheng.com/k8s/bash:5.1.4
      script: |
        set -e
        image="$(params.IMAGE)"
        echo -n "${image}" | tee "$(results.IMAGE_URL.path)"
      volumeMounts:
        - name: hosts
          mountPath: /etc/hosts
  volumes:
    - name: hosts
      hostPath:
        path: /etc/hosts
    - name: host
      hostPath:
        path: /etc/hosts
# 创建一个pipeline
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: clone-build-push
spec:
  description: |
    This pipeline clones a git repo, builds a Docker image with Kaniko and
    pushes it to a registry    
  params:
  - name: repo-url
    type: string
  - name: image-reference
    type: string
  workspaces:
  - name: shared-data
  - name: docker-credentials
  - name: git-credentials
  tasks:
  - name: fetch-source
    taskRef:
      name: git-clone
    workspaces:
    - name: output
      workspace: shared-data
    - name: ssh-directory
      workspace: git-credentials
    params:
    - name: url
      value: $(params.repo-url)
  - name: build-push
    runAfter: ["fetch-source"]
    taskRef:
      name: kaniko
    workspaces:
    - name: source
      workspace: shared-data
    - name: docker-credentials
      workspace: docker-credentials
    params:
    - name: IMAGE
      value: $(params.image-reference)
# 创建pipelinerun
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
  generateName: clone-build-push-run-
spec:
  pipelineRef:
    name: clone-build-push
  podTemplate:
    securityContext:
      fsGroup: 65532
  workspaces:
  - name: shared-data
    volumeClaimTemplate:
      spec:
        accessModes:
        - ReadWriteOnce
        resources:
          requests:
            storage: 1Gi
        storageClassName: nfs
  - name: docker-credentials
    secret:
      secretName: docker-credentials
  - name: git-credentials # 指定git仓库的secret
    secret:
      secretName: git-credentials
  params:
  - name: repo-url
    value: git@172.31.3.155:guquanheng/tekton.git
  - name: image-reference
    value: quanheng.com/k8s/alpine:v7
# 验证结果
(base) gu@python:~/k8s/yaml/tekton/use/pushimage$ kubectl tkn pipelinerun logs  clone-build-push-run-k9pvs -f
[fetch-source : clone] + '[' false '=' true ]
[fetch-source : clone] + '[' true '=' true ]
[fetch-source : clone] + cp -R /workspace/ssh-directory /home/git/.ssh
[fetch-source : clone] + chmod 700 /home/git/.ssh
[fetch-source : clone] + chmod -R 400 /home/git/.ssh/config /home/git/.ssh/id_rsa /home/git/.ssh/known_hosts
[fetch-source : clone] + '[' false '=' true ]
[fetch-source : clone] + CHECKOUT_DIR=/workspace/output/
[fetch-source : clone] + '[' true '=' true ]
[fetch-source : clone] + cleandir
[fetch-source : clone] + '[' -d /workspace/output/ ]
[fetch-source : clone] + rm -rf '/workspace/output//*'
[fetch-source : clone] + rm -rf '/workspace/output//.[!.]*'
[fetch-source : clone] + rm -rf '/workspace/output//..?*'
[fetch-source : clone] + test -z 
[fetch-source : clone] + test -z 
[fetch-source : clone] + test -z 
[fetch-source : clone] + git config --global --add safe.directory /workspace/output
[fetch-source : clone] + /ko-app/git-init '-url=git@172.31.3.155:guquanheng/tekton.git' '-revision=' '-refspec=' '-path=/workspace/output/' '-sslVerify=true' '-submodules=true' '-depth=1' '-sparseCheckoutDirectories='
[fetch-source : clone] {"level":"warn","ts":1695362820.9618697,"caller":"git/git.go:271","msg":"URL(\"git@172.31.3.155:guquanheng/tekton.git\") appears to need SSH authentication but no SSH credentials have been provided"}
[fetch-source : clone] {"level":"info","ts":1695362822.768268,"caller":"git/git.go:176","msg":"Successfully cloned git@172.31.3.155:guquanheng/tekton.git @ c9c9a5c2506927e058508ffc659618c6bc4e6cb8 (grafted, HEAD) in path /workspace/output/"}
[fetch-source : clone] {"level":"info","ts":1695362822.8658404,"caller":"git/git.go:215","msg":"Successfully initialized and updated submodules in path /workspace/output/"}
[fetch-source : clone] + cd /workspace/output/
[fetch-source : clone] + git rev-parse HEAD
[fetch-source : clone] + RESULT_SHA=c9c9a5c2506927e058508ffc659618c6bc4e6cb8
[fetch-source : clone] + EXIT_CODE=0
[fetch-source : clone] + '[' 0 '!=' 0 ]
[fetch-source : clone] + git log -1 '--pretty=%ct'
[fetch-source : clone] + RESULT_COMMITTER_DATE=1695361527
[fetch-source : clone] + printf '%s' 1695361527
[fetch-source : clone] + printf '%s' c9c9a5c2506927e058508ffc659618c6bc4e6cb8
[fetch-source : clone] + printf '%s' git@172.31.3.155:guquanheng/tekton.git

[build-push : build-and-push] INFO[0000] Retrieving image manifest quanheng.com/k8s/ubuntu:2 
[build-push : build-and-push] INFO[0000] Retrieving image quanheng.com/k8s/ubuntu:2 from registry quanheng.com 
[build-push : build-and-push] INFO[0000] Built cross stage deps: map[]                
[build-push : build-and-push] INFO[0000] Retrieving image manifest quanheng.com/k8s/ubuntu:2 
[build-push : build-and-push] INFO[0000] Returning cached image manifest              
[build-push : build-and-push] INFO[0000] Executing 0 build triggers                   
[build-push : build-and-push] INFO[0000] Building stage 'quanheng.com/k8s/ubuntu:2' [idx: '0', base-idx: '-1'] 
[build-push : build-and-push] INFO[0000] Unpacking rootfs as cmd RUN echo hello requires it. 
[build-push : build-and-push] INFO[0007] RUN echo hello                               
[build-push : build-and-push] INFO[0007] Initializing snapshotter ...                 
[build-push : build-and-push] INFO[0007] Taking snapshot of full filesystem...        
[build-push : build-and-push] INFO[0009] Cmd: /bin/sh                                 
[build-push : build-and-push] INFO[0009] Args: [-c echo hello]                        
[build-push : build-and-push] INFO[0009] Running: [/bin/sh -c echo hello]             
[build-push : build-and-push] hello
[build-push : build-and-push] INFO[0009] Taking snapshot of full filesystem...        
[build-push : build-and-push] INFO[0009] No files were changed, appending empty layer to config. No layer added to image. 
[build-push : build-and-push] INFO[0009] CMD ["tail","-f","/etc/resolv.conf"]         
[build-push : build-and-push] INFO[0009] Pushing image to quanheng.com/k8s/ubuntu:3   
[build-push : build-and-push] INFO[0010] Pushed quanheng.com/k8s/ubuntu@sha256:8862a8d0ba6e6057a1d539554697fc4d075688b0ec124039f55d0e2b8417c25d 

[build-push : write-url] quanheng.com/k8s/ubuntu:3

4、核心资源

4.1 crd

https://tekton.dev/docs/pipelines/pipeline-api/

4.2 task

# 详细配置
https://tekton.dev/docs/pipelines/tasks/
必要:
    apiVersion api版本
    kind 资源类型
    metadata 元数据信息
    spec 配置信息
    steps 所要执行task的容器的信息
可选:
	description 为所有field添加描述信息
    params 参数
    workspaces 所要使用的volume
    results 将执行结果写入指定的路径
    volumes 挂载在指定的task时使用的卷
    stepTemplate 为所有step设置一个基本配置
    sidecars 指定一个边车容器

4.3 taskrun

# 详细配置
https://tekton.dev/docs/pipelines/taskruns
必要:
    apiVersion API 版本
    kind 资源类型
    metadata 元数据信息
    spec 配置信息
    # 选择要执行的task来源
    - taskRef # 指定一个已定义的task
    - taskSpec # 重新配置一个task
可选:
    serviceAccountName 指定一个sa来对taskrun进行授权
    params 指定参数
    timeout  指定运行多久不成功后返回失败
    podTemplate 将用于所有要执行task的pod的配置,比如卷挂载,指定运行的用户id等
        env	 Pod 模板中定义的环境变量优先于 和TaskRunPipelineRunstepsstepTemplate
        nodeSelector	必须为 true,Pod 才能适应节点。
        tolerations	允许(但不要求)Pod 调度到具有匹配污点的节点上。
        affinity	允许约束节点集,可以根据节点上存在的标签来调度 Pod。
        securityContext	指定容器级安全属性和常见容器设置,例如  。runAsUserselinux
        volumes	指定 Pod 中的容器可以挂载的卷列表。这允许您为 .volumeMountTask
        runtimeClassName	指定 Pod 的运行时类。
        automountServiceAccountToken	默认值:。确定 Tekton 是否以预定义的路径自动为 Pod 在容器内使用的服务帐户提供令牌。true
        dnsPolicy	默认值:。指定容器的 DNS 策略。合法值为   。不支持,因为 Tekton Pod 无法与主机网络一起运行。ClusterFirstClusterFirstDefaultNoneClusterFirstWithHostNet
        dnsConfig	指定容器的其他 DNS 配置,例如名称服务器和搜索域。
        enableServiceLinks	默认值:。确定 Pod 命名空间中的服务是否作为环境变量公开给 Pod,类似于 Docker 服务链接。true
        priorityClassName	指定容器的优先级类。允许您有选择地在优先级较低的工作负载上启用抢占。
        schedulerName	指定调度 Pod 时要使用的调度程序。您可以为不同类型的 工作负载,例如机器学习工作负载。volcano.sh
        imagePullSecrets	指定拉取容器映像时要使用的机密。
        hostNetwork	默认值:。确定是否使用主机网络命名空间。false
        hostAliases	将条目添加到 Pod 的“/etc/hosts”中,以提供 Pod 级别的主机名覆盖。有关更多信息,请参阅 [此字段的 Kubernetes 文档](https://kubernetes.io/docs/tasks/network/customize-hosts-file-for-pods/)。
        topologySpreadConstraints	指定 Pod 在拓扑域中跨集群的分布方式。
    Workspaces 定义要使用的卷

4.4 pipeline

必要:
    apiVersion api版本
    kind 资源类型
    metadata 元数据信息
    spec 配置信息
        tasks 要执行的tasks
可选:
    params 参数
    workspaces 要使用的卷
    tasks: # 里面是一个列表
      - name 名称
        displayName 面向用户的名称
        description 定义的资源描述信息
        taskRef 指定一个已定义的task
        taskSpec 新建一个task
        runAfter 指定task运行顺序,可以是一个列表,多个不同task可以定义相同目标(使其并行执行)
        retries 重试次数
        when 指定一个条件当满足条件时执行task
        timeout 指定超时时间
        params 指定参数
        workspaces 指定使用的workspaces
        matrix 
    results 指定一个执行结果要保存的位置
    displayName 面向用户的名称
    description 针对定义资源的描述
    finally 当所有其他任务完成后要执行的task 是一个列表。配置同tasks

4.5 pipelinerun

必要:
    apiVersion api版本
    kind 资源类型
    metadata 元数据信息
    spec 配置信息
    pipelineRef 使用已定义的pipeline
    pipelineSpec 新定义一个pipeline
可选:
    params 参数
    serviceAccountName sa授权
    status 
    必要:
        statusPipelineRun状态的最新观察结果
        startTime 开始时间
        completionTime 完成时间
        pipelineSpec 
    可选:
        pipelineResults 执行结果输出到文件
        skippedTasks 跳过执行的task
        childReferences taskrun或者task引用列表包含下面字段
            kind 资源类型
            apiVersion api版本
        	whenExpressions when表达式
        provenance 有关运行时配置和 PipelineRun 中使用的资源的元数据
            RefSource: 来源
            FeatureFlags: 映射的配置数据
        finallyStartTime 最终任务的开始时间
    taskRunSpecs 定义taskrun
    timeouts 指定失败前的超时
    podTemplate 最终执行任务时,pod所使用的模版数据
    workspaces 卷定义

4.6 CustomRun

必要:
    apiVersion API 版本
    kind 资源类型
    metadata 元数据信息
    spec 配置信息
    	customRef 指定一个自定义任务
		customSpec 新建一个自定义任务
可选:
    serviceAccountName 指定一个sa来对taskrun进行授权
    params 指定参数
    retries 指定重试次数
    timeout  指定运行多久不成功后返回失败
    Workspaces 定义要使用的卷

4.7 eventlist

#  eventlist 具体表现为一个pod 使用binding和trigger来进行binding binding中存在触发器所需要的参数,trigger是一个生成tekton实例的模版,会根据传递来的参数进行pipeline的实例化
必要:
    apiVersion api版本
    kind 资源类型
    metadata 元数据信息
    spec 配置信息
    serviceAccountName 指定sa授权
可选:
    triggers 指定一个触发器,当检测到事件要执行的列表# 见4.8触发器配置
    cloudEventURI
    resources - 指定事件监听服务资源 # 可以使用k8s原生资源或者自定义资源
    	kubernetesResource
    	CustomResource
    namespaceSelector 指定生成实例的ns # 指定el pod所处ns
    labelSelector 指定实例化的标签选择 #  

4.8 trigger

# 工作原理
定义一个触发器,触发器内部使用binding和template,拦截器用来处理外来数据然后传递给binding,再传递给template最后创建实例
拦截器是一个定义如何与后端eventslist pod通信的svc
apiVersion - 指定 API 版本;例如。triggers.tekton.dev/v1alpha1
kind - 指定此资源对象是一个对象。Trigger
metadata - 指定用于唯一标识此对象的元数据;例如 .Triggername
spec - 指定此触发器对象的配置信息,包括:
    [bindings] - 指定一个列表
    [template] - 指定一个模版
    [interceptors] - 指定一个或者多个拦截器进行处理数据
        name 名称
        ref 引用拦截器
            name 引用名称
            kind 默认为cluster,可以指定namespace
            apiVersion api版本
            params 指定要传递给拦截器的参数
        params 定义传递给拦截器参数的格式
    [serviceAccountName] - (可选)指定要提供给 以实例化/执行目标资源。ServiceAccountEventListener
下面是一个示例定义:Trigger
---
apiVersion: triggers.tekton.dev/v1beta1
kind: Trigger
metadata:
  name: trigger
spec:
  interceptors:
    - ref:
        name: "cel"
      params:
        - name: "filter"
          value: "header.match('X-GitHub-Event', 'pull_request')"
        - name: "overlays"
          value:
            - key: extensions.truncated_sha
              expression: "body.pull_request.head.sha.truncate(7)"
  bindings:
  - ref: pipeline-binding
  template:
    ref: pipeline-template

4.8.1 TriggerTemplate

#  用来实例化tekton对象的模版文件可以是 一般是pipelinerun
Pipeline
PipelineRun	
Task	
TaskRun	
ClusterTask	

4.8.2 TriggerBindings

# 从事件中提取信息传递给tt用来生成实例
内联绑定: 定义在tt中
tb定义: 定义在tb中
tb引用: 引用其他的
# 验证
安装工具
从github下载trigger 
go build main.go
$ cat testdata/triggerbinding.yaml
apiVersion: tekton.dev/v1alpha1
kind: TriggerBinding
metadata:
  name: pipeline-binding
spec:
  params:
  - name: foo
    value: $(body.test)
  - name: bar
    value: $(header.X-Header)

$ cat testdata/http.txt
POST /foo HTTP/1.1
Content-Length: 16
Content-Type: application/json
X-Header: tacocat

{"test": "body"}

$ binding-eval -b testdata/triggerbinding.yaml -r testdata/http.txt
[
  {
    "name": "foo",
    "value": "body"
  },
  {
    "name": "bar",
    "value": "tacocat"
  }
]

4.9 Interceptor

4.9.1 clusterInterceptor

apiVersion API 版本
kind 资源类型
metadata 元数据信息
spec 配置信息
	[clientConfig]  指定客户端与EventListener的通信方式
---
spec:
  clientConfig:
    caBundle: <cert data> # https
    service:
      name: "my-interceptor-svc"
      namespace: "default"
      path: "/optional-path" # optional
      port: 8081 # defaults to 80

4.9.2 NamespacedInterceptor

配置同4.9.1 区别在于为ns级别

4.9.3 配置拦截器

4.9.3.1 格式

name 名称
ref 引用拦截器
    name 引用名称
    kind 默认为cluster,可以指定namespace
    apiVersion api版本
    params 指定要传递给拦截器的参数
params 定义传递给拦截器参数的格式

4.9.3.2 一般配置

---
interceptors:
    - name: "validate GitHub payload and filter on eventType" 配置名称
      ref: # 引用名称为github的拦截器
        name: "github"
      params: # 传递给github拦截器的参数
      - name: "secretRef" # 参数名称
        value: # 参数值
          secretName: github-secret
          secretKey: secretToken
      - name: "eventTypes" # 参数名称
        value: ["pull_request"] # 参数值
    - name: "CEL filter: only when PRs are opened"
      ref:
        name: "cel"
      params:
      - name: "filter"
        value: "body.action in ['opened', 'reopened']"

4.9.3.3 webhook拦截器

---
apiVersion: triggers.tekton.dev/v1alpha1
kind: EventListener
metadata:
  name: listener-interceptor
spec:
  serviceAccountName: tekton-triggers-example-sa
  triggers:
    - name: foo-trig
      interceptors:
        - webhook:
            header:
              - name: Foo-Trig-Header1
                value: string-value
              - name: Foo-Trig-Header2
                value:
                  - array-val1
                  - array-val2
            objectRef:
              kind: Service
              name: gh-validate
              apiVersion: v1
              namespace: default
      bindings:
        - ref: pipeline-binding
      template:
        ref: pipeline-template

4.9.3.4 gitlab拦截器

interceptors:
- ref:
    name: "gitlab"
  params:
  - name: "secretRef"
    value:
      secretName: foo
      secretKey: bar
  - name: "eventTypes"
    value: ["Push Hook"]

4.9.4 排错

# 查看el-listening日志
# 修改el实例日志格式为debug config-logging-triggers 
loglevel.eventlistener": "info"

4.10 events

tekton EventListener 事件发生
#  事件格式
资源	事件	事件类型
EventListener	Started	dev.tekton.event.triggers.started.v1
EventListener	Succeed	dev.tekton.event.triggers.successful.v1
EventListener	Done	dev.tekton.event.triggers.done.v1
EventListener	Failed	dev.tekton.event.triggers.failed.v1
# 事件发生时间点
EventListener发出以下事件:
    Started:收到请求时第一次发出。EventListener
    Succeeded:当事件侦听器收到请求并处理所有触发器请求时发出。
    Done:使用事件侦听器处理程序完成时发出。
    Failed:如果触发器无法处理请求,则发出

5、设置

https://tekton.dev/docs/operator/

5.1 控制器设置

# 指定controller镜像运行的参数,在controller的deployment里进行配置
spec:
  serviceAccountName: tekton-pipelines-controller
  containers:
    - name: tekton-pipelines-controller
      image: ko://github.com/tektoncd/pipeline/cmd/controller
      args: [
          "-kube-api-qps", "50", # qps数量
          "-kube-api-burst", "50", # 
          "-threads-per-controller", "32", # 每个控制器要创建的线程
          # other flags defined here...
        ]

5.2 控制器高可用

# 更改副本数
# 配置数据副本
路径 pipeline-main/config/resolvers
data.buckets	1 # 数据分桶
data.leaseDuration	15 # 租赁
data.renewDeadline	10 # 续订
data.retryPeriod	2 # 重试 
# 设置hpa和pdb(控制人为干预情况下pod的最少可使用数量)

6、身份认证

6.1 以非root身份使用

    securityContext:
      runAsNonRoot: true
      runAsUser: 65532

6.2 为git配置身份认证

6.2.1 ssh认证

---
apiVersion: v1
kind: Secret
metadata:
  name: git-credentials
type: kubernetes.io/ssh-auth
data:
  id_rsa: # cat ~/.ssh/id_rsa|base64|tr -d '\n' LS0tLS1CRUdJTiBPUEVOU1NIIFBSSVZBVEUgS0VZLS0tLS0KYjNCbGJuTnphQzFyWlhrdGRqRUFBQUFBQkc1dmJtVUFBQUFFYm05dVpRQUFBQUFBQUFBQkFBQUJsd0FBQUFkemMyZ3RjbgpOaEFBQUFBd0VBQVFBQUFZRUFuQ21mazNYOFhseVJZaFNZdExGM2U3cWkwS1M5dlJEaTY1d1Y3QUovSzFnWFlDOHZyK2RzCjg3ZDVndU5YdFcrQndkbzJCNjRTVjZINW9XdFhlS0FNakRadU12am1lcW9UZndVa2c1U2kvRzN4c28wNlhYalhiTUJqYjkKVkMwdzA5NllwbUJNWjFqNDBhSUFHRGFub3N0eWdkUWRjeHpCVCt5NnFuSFIwLzJ4MmplL1N3NkpkOE5DYzVkZERCa1R5SQpHcTJRb2x0ZlVqNG5yUUlhRzVGVGl1STZqMW1JN0llL2JERGZKbzNrY1U1dUtTanVNVjB0d0lhNzhsM2V5UDhveFcvSG5aCmZNdHhka2ZRakMrdTkzdnJtWGhMdW84bFQ2NC9XOVlrLzhHOGdtS25vS3AyTC9jbmIrZFNnZkZ3OEZ6eEZTSjM5dWdRSTMKdWdwR0I1SVZTeDV1SmQwZEJqZmJ5SkdIaGEwU0ZHL21FbTdGa0E1cFBGVGxOTFZjMG9XQm50OG5WanozbGxKUUVTTlNQMgpPb0tlSUhpa0RPUnN5Y3F0eUdJK3cwVFJLUDh0YWpLdWZKUjZVWlRFRktyVVZYSUg3bnE5L3huTUxyeFI3ZHVpQjVkbWY4CjhqdVpxc2NHaEdlL0NqY1VaeE4vd29HR2kxQXV0N0w5US85NXBab25BQUFGZ0F3T2tCY01EcEFYQUFBQUIzTnphQzF5YzIKRUFBQUdCQUp3cG41TjEvRjVja1dJVW1MU3hkM3U2b3RDa3ZiMFE0dXVjRmV3Q2Z5dFlGMkF2TDYvbmJQTzNlWUxqVjdWdgpnY0hhTmdldUVsZWgrYUZyVjNpZ0RJdzJiakw0NW5xcUUzOEZKSU9Vb3Z4dDhiS05PbDE0MTJ6QVkyL1ZRdE1OUGVtS1pnClRHZFkrTkdpQUJnMnA2TExjb0hVSFhNY3dVL3N1cXB4MGRQOXNkbzN2MHNPaVhmRFFuT1hYUXdaRThpQnF0a0tKYlgxSSsKSjYwQ0dodVJVNHJpT285WmlPeUh2Mnd3M3lhTjVIRk9iaWtvN2pGZExjQ0d1L0pkM3NqL0tNVnZ4NTJYekxjWFpIMEl3dgpydmQ3NjVsNFM3cVBKVSt1UDF2V0pQL0J2SUppcDZDcWRpLzNKMi9uVW9IeGNQQmM4UlVpZC9ib0VDTjdvS1JnZVNGVXNlCmJpWGRIUVkzMjhpUmg0V3RFaFJ2NWhKdXhaQU9hVHhVNVRTMVhOS0ZnWjdmSjFZODk1WlNVQkVqVWo5anFDbmlCNHBBemsKYk1uS3JjaGlQc05FMFNqL0xXb3lybnlVZWxHVXhCU3ExRlZ5Qis1NnZmOFp6QzY4VWUzYm9nZVhabi9QSTdtYXJIQm9Sbgp2d28zRkdjVGY4S0Job3RRTHJleS9VUC9lYVdhSndBQUFBTUJBQUVBQUFHQU94QVhGYnV6SnJGV0gwVncrQzZDNVY0U2hGCjA2a2c2WDlNckZFODFoOGEvUXI0VkpRUHVEbnE0UEhDMEdHRTVEUW1GWXZCRGZTUnV2QVpsS3JRbkRsU2hsQjR4U0I2VFoKMk5uR0ZLb2I5dU5TWGRqQ2NXWHAvR3pMYnhtMnU0SXZuMnZENkJ4empFYXUwZG9nclIzbVdhT25aU2FSNUFFdzJURURJYQpUVmFQZE54TzBvRitCcmpvSWpYbWNGUHZ3bzhnWWhSUGJRRjVnQWc1UGU4ZnhHSDZvdXdkYjRUWldPRmNwcUsvZlFwZlltCi9oUkgrbzJtWjBIT1JmMnc3RTVzc3FJZHFIRE4wVGgvbW5LTEc1MEVBRUsraGVJTmloMWxNaU4xR0ZNZFpDZTBXQ1ZpNEwKWXdlWTAyZ1E1a29FYXV3TXM5RTlTcHVuTTk5QXFPL3lwQmw5a3FyT0M4NHRSejZSbzYyOUF1aUVjbkhXQ1JXMUI5MDA5SgpQamZDT0JYdTBmL1hEcnhaSzRlNVdkZ0tWM2VPRlFXTC9jK2tBYjNVWkRYRFBmMWlsL05ETWpsYUlKYWpVVWhrOTl3dUcyCi9lblhXQ2NFdkNoS0ZqN096NWwya2F0NHVmU2ZtbjAremhOWklzMUhXT0E1KzRzSkN4dkxPNWcvdVRGampZQzY3UkFBQUEKd1FDSmdNUXp4QjBvUTE2NGZObS9MRzVaV3dBb3FTb3hnSDI2d05xUXQxY3phQ2VDSmQwNExlaDViMUxTQzRIQTBxSjV4aAp4RDZ3ZVk3K2pEUSt1N1dXSEFhMmM2MWh1ZGFjSFByTEVnRFRZRHBBNnhxZnF5ZTdhVVFIckpYWkEwUWU3RHpYd2FCeGkwClhMc21Xd1NUTVRySXpqbjZuU0hWaFI1bGJwRkJCNDFEUkdEZDkrc2d4Ni9FR2Q1dkE1T3FKcWs2bGpnQThPRlM1VXFYQW8Kc1FTbTJEbWlQQTBKL21uSTNYdEozdkpjcElKQ3BnODNLWHFDUm9EQTYzTWMxS1ZOQUFBQURCQU5YTmpxTnA5QXFGRWZGWQplTGVaSVNYTEJNZ0JtaTkzYXB3Tm1BVDUySkI0eWN5RnlRSm53dlRYR0NtbURFb0V6R2xISTlVVDUwUzhlVkgxWmlqS25TCnZZVEsyODQ0U3MrdFRCRkdFaGFoVXkrdXhhci9veUJCSHhHS1VsMGc1RVEyK0tnVnROZ3drUFViMWM1dkxtbnNWdVEwbVYKUGtRb2sramgrbi9uZ25IY2J0VjZ2MnpuYlg1NXppMVkrZnhRUjRKNXZCa0VVMlFnRXpLWlBwQWxKdTFzeVdHS1dhMjNyQQpLdVI1ZVpBbmswMjhjdFpNQmwrc0Zza092UGFuMGNid0FBQU1FQXV2dkdDcVhBY2NLOTdTY0QxYmJ6UjlHSWVad0tSdkRICjRaeVMxL1ZtUXA3ZThnVGZ1VVowQWFGREpyTS9rTjJvbXNNYmk0RnE5Mi9JN1lqYmc4R0YxaTlxQUpYYzZPR0RPdjVMMEQKVHJEVXd3aVgwYUpDbGVSMlBES3R6Yy9ValRHdDAwV3lMdVZKZlVMdVBIbXV1WG1sajNIK2M2cjlKL25LUXk0bXlHd1ExWAp0QlI5RW55Z1BaYll1YWtlV0tIcmpHdUZqWnYxVFlmVklUN2IrMGdjRnVwV1o5c25GT3V3aU1aSGpONEVIbW43ak1OMFR5Cmo1YW1ieUF2RHhLNm5KQUFBQUNXZDFRSEI1ZEdodmJnRT0KLS0tLS1FTkQgT1BFTlNTSCBQUklWQVRFIEtFWS0tLS0tCg==
  known_hosts: # cat ~/.ssh/known_hosts|base64|tr -d '\n' CnwxfFlESjAzUVJhNVVZS3dFbUYvZ0FOTjl5YWxTZz18NC9XVzQxRTAwa3BwN2JXbmJrbWo3U2xYRTVFPSBzc2gtZWQyNTUxOSBBQUFBQzNOemFDMWxaREkxTlRFNUFBQUFJTG9sRlcrU3RIdkQ4MGhEQldyS3hKWXdlL2h0MGE5Qnppa1FuYVJhUGZqWQp8MXxtK1NrOXBkK1p0K3QrK2NlRU4raFBMY0N6aUU9fDZWUHVMVVgxZDRsNGNvbktvN1dlL0IzazVFbz0gZWNkc2Etc2hhMi1uaXN0cDI1NiBBQUFBRTJWalpITmhMWE5vWVRJdGJtbHpkSEF5TlRZQUFBQUlibWx6ZEhBeU5UWUFBQUJCQkZxcU82S3MyWmR2K0tXNGNMc0p1bEQ0QmpsajFDdnNScmtmanNqQkkrQkZXWDd4THpCZVNJM0pFT1BPYjFjbHlrUmRKMW1Gekt0a0JRNHBDTGRidVRJPQp8MXw0dW12TDAzeEZmL1c5Z1pNV3RXQTVVZGJ6dDg9fG1CLzUydVNUVnArdWNsQ2RvanFpMXpwRWMzMD0gc3NoLWVkMjU1MTkgQUFBQUMzTnphQzFsWkRJMU5URTVBQUFBSUxvbEZXK1N0SHZEODBoREJXckt4Sll3ZS9odDBhOUJ6aWtRbmFSYVBmalkKfDF8L3ZMUThVOEx3MW11aXg5ODhlZ0U4VGFtYkVBPXxtWE9ZYXJiVXg5UEI2RDl3RGFpVWVRWkRkYWc9IHNzaC1lZDI1NTE5IEFBQUFDM056YUMxbFpESTFOVEU1QUFBQUlQc0I4aTgvcmxkamUweUtpSEZvTTQ1bEk5RUhWUkdBUU4zSDN2YjFSTUcvCnwxfGFOcnV5UXB4T1FKSk9reVZ1eG9DOWkxVVdVbz18c2ZPZFhwc0FWZ3ZWeXJTWHBXdnIrNHpnRVdnPSBlY2RzYS1zaGEyLW5pc3RwMjU2IEFBQUFFMlZqWkhOaExYTm9ZVEl0Ym1semRIQXlOVFlBQUFBSWJtbHpkSEF5TlRZQUFBQkJCTDg1RFNoaW0wUUFZZ0Jockw3UFYzaDFNa3dCaU42SnpVa3laQndWZGs3aWRRb3pLZHRDdlV0Q0U1SWZvY28zNDY2RERRZHBraGplVjgzMXhQWjFFSEk9CnwxfFpUeG1OVkE1WTczd3dxTDFnS2VMRTY0UUFZbz18SlFWeXpSaDYyaXdNSDBDUzZlbkJTSHVXL3BvPSBzc2gtZWQyNTUxOSBBQUFBQzNOemFDMWxaREkxTlRFNUFBQUFJUHNCOGk4L3JsZGplMHlLaUhGb000NWxJOUVIVlJHQVFOM0gzdmIxUk1HLwp8MXxDZlJsTjM3MWtwSVlOdmIxeTJoWkhtZFNSeWs9fHhGTjdMRGh1QVJUZkZvZjZTMzVJRjI5cUpmTT0gc3NoLWVkMjU1MTkgQUFBQUMzTnphQzFsWkRJMU5URTVBQUFBSUxvbEZXK1N0SHZEODBoREJXckt4Sll3ZS9odDBhOUJ6aWtRbmFSYVBmalkKfDF8bzgveUFOSHVQYis5UG1qeGpxcllkWFlYOEFzPXx5R2FpbTZFa1ZnNVNtb1psektRS1FhYnluazQ9IHNzaC1lZDI1NTE5IEFBQUFDM056YUMxbFpESTFOVEU1QUFBQUlMb2xGVytTdEh2RDgwaERCV3JLeEpZd2UvaHQwYTlCemlrUW5hUmFQZmpZCnwxfFkvMmFHa0ZuYU5aaEMwVExMcnRnRGVOZEo3cz18MWxVcUJSdkZuYm85NFRBSUhFeTRrMitQYjJVPSBzc2gtZWQyNTUxOSBBQUFBQzNOemFDMWxaREkxTlRFNUFBQUFJSDZ0V2NzYkdTa0tBS2kvdzJQUWlSdmRJc3BxNThMU0ZmQVdsSGhEYSt2NQp8MXxWeU9oMGEvYnUrN3h0blk0MndEbS81ZUQxYkU9fGh4UDdIMW5tSXFvdWh1REVjajgwUkFmZVVEQT0gZWNkc2Etc2hhMi1uaXN0cDI1NiBBQUFBRTJWalpITmhMWE5vWVRJdGJtbHpkSEF5TlRZQUFBQUlibWx6ZEhBeU5UWUFBQUJCQkhEdVBuRERRcyt1QzNOTVdJTU4yT1cyWHo1KzljK2l4dWhSK1JQZkZCaFYzVWMxYnB0TnJZTk5JSGFXbFBQcTVHWXFaU09jekdxVnlwMGVDNGhMdzlBPQo=
  config: SG9zdCAxNzIuMzEuMy4xNTUKICBIb3N0bmFtZSAxNzIuMzEuMy4xNTUKICBQcmVmZXJyZWRBdXRoZW50aWNhdGlvbnMgcHVibGlja2V5CiAgSWRlbnRpdHlGaWxlIH4vLnNzaC9pZF9yc2EK
--- 
# config文件生成
cat ~/.ssh/config
Host 172.31.3.155 # 固定格式
  Hostname 172.31.3.155 # git服务器ip
  PreferredAuthentications publickey # 固定格式
  IdentityFile ~/.ssh/id_rsa # 指定私钥文件路径

6.2.2 账户密码认证

apiVersion: v1
kind: Secret
metadata:
  name: basic-user-git
  annotations:
    tekton.dev/git-0: http://172.31.3.155:80 #git仓库地址 可以跟端口
type: kubernetes.io/basic-auth
stringData:
  username: base64编码
  password: base64编码

6.3 为docker仓库配置身份认证

apiVersion: v1
data: # cat ~/.docker/config|base64
  .dockercfg: ewoJImF1dGhzIjogewoJCSIxNzIuMzEuMy4xNjYiOiB7CgkJCSJhdXRoIjogIllXUnRhVzQ2TVRJek5EVTIiCgkJfSwKCQkicXVhbmhlbmcuY29tIjogewoJCQkiYXV0aCI6ICJZV1J0YVc0Nk1USXpORFUyIgoJCX0KCX0KfQ==
kind: Secret
metadata:
  name: secret-dockercfg
type: kubernetes.io/dockercfg

7、变量使用

8、测试项目

8.1 测试webhook

目的:查看webhook传递信息

8.1.1 生成triggerbinding

# gitlab-webhook格式

# header
X-Gitlab-Event: Push Hook
# body
{
    "object_kind":"push",
    "before":"95790bf891e76fee5e1747ab589903a6a1f80f22",
    "after":"da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
    "ref":"refs/heads/master",
    "checkout_sha":"da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
    "user_id":4,
    "user_name":"John Smith",
    "user_username":"jsmith",
    "user_email":"john@example.com",
    "user_avatar":"https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80",
    "project_id":15,
    "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",
        "namespace":"Mike",
        "visibility_level":0,
        "path_with_namespace":"mike/diaspora",
        "default_branch":"master",
        "homepage":"http://example.com/mike/diaspora",
        "url":"git@example.com:mike/diaspora.git",
        "ssh_url":"git@example.com:mike/diaspora.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.",
            "timestamp":"2011-12-12T14:27:31+02:00",
            "url":"http://example.com/mike/diaspora/commit/b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327",
            "author":{
                "name":"Jordi Mallach",
                "email":"jordi@softcatala.org"
            },
            "added":[
                "CHANGELOG"
            ],
            "modified":[
                "app/controller/application.rb"
            ],
            "removed":[

            ]
        },
        {
            "id":"da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
            "message":"fixed readme",
            "title":"fixed readme",
            "timestamp":"2012-01-03T23:36:29+02:00",
            "url":"http://example.com/mike/diaspora/commit/da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
            "author":{
                "name":"GitLab dev user",
                "email":"gitlabdev@dv6700.(none)"
            },
            "added":[
                "CHANGELOG"
            ],
            "modified":[
                "app/controller/application.rb"
            ],
            "removed":[

            ]
        }
    ],
    "total_commits_count":4
}
# 作用是当el触发时将参数传递给triggertemplate
apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerBinding
metadata:
  name: test-binding
spec: 
  params:
  - name: git-webhook
    value: $(body.repository.git_http_url) 

8.1.2 生成eventlister

apiVersion: triggers.tekton.dev/v1alpha1
kind: EventListener
metadata:
  name: test-cicd-listener
spec:
  serviceAccountName: tekton-robot
  triggers:
  - name: test-trigger
    interceptors:
      - gitlab:
          eventTypes:
              - Push Hook
    bindings:
      - ref: test-binding
    template:
      ref: test-template
  resources:
    kubernetesResource:
      serviceType: NodePort
      spec:
        template:
          spec:
            nodeSelector:
              disktype: ssd

8.1.3 生成triggertemplate

apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerTemplate
metadata:
  name: test-template
spec:
  params:
  - name: git-webhook
    description: The git webhook
  resourcetemplates:
  - apiVersion: tekton.dev/v1beta1
    kind: PipelineRun
    metadata:
      generateName: test-cicd
    spec:
      pipelineRef:
        name: test-pipeline
      params:
      - name: git-webhook
        value: $(tt.params.git-webhook)

8.1.4 生成pipline

apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: test-pipeline
spec:
  params:
  - name: git-webhook
    type: string
  tasks:
    - name: test-task
      taskRef:
        name: test-task
      params:
      - name: git-webhook
        value: $(params.git-webhook)

8.1.5 生成task

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: test-task
spec:
  params:
  - name: git-webhook
    type: string
    default: "no any message"
  steps:
    - name: test-task
      image: quanheng.com/k8s/ubuntu:2
      script: |
        #!/bin/bash
        echo "$(params.git-webhook)!"

8.1.6 配置gitlab-webhook

(base) gu@python:~$ kubectl get el
NAME                 ADDRESS                                                       AVAILABLE   REASON                     READY   REASON
test-cicd-listener   http://el-test-cicd-listener.default.svc.cluster.local:8080   True        MinimumReplicasAvailable   True    
(base) gu@python:~$ kubectl get svc 
NAME                    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                         AGE
el-test-cicd-listener   NodePort    10.173.217.133   <none>        8080:10918/TCP,9000:25230/TCP   114m
base) gu@python:~$ kubectl get pod -owide|grep el
el-test-cicd-listener-55df68c555-vm9pz    1/1     Running     0               108m    10.182.107.220   worker-03

image-20231130171334836

image-20231130171409641

8.2 利用tekton实现ci

目的:当上传代码后可以自动进行打包镜像并上传镜像仓库

8.2.1 生成task-拉取代码

apiVersion: tekton.dev/v1
kind: Task
metadata:
  annotations:
    tekton.dev/categories: Git
    tekton.dev/displayName: git clone
    tekton.dev/pipelines.minVersion: 0.38.0
    tekton.dev/platforms: linux/amd64,linux/s390x,linux/ppc64le,linux/arm64
    tekton.dev/tags: git
  labels:
    app.kubernetes.io/version: "0.9"
    hub.tekton.dev/catalog: tekton
  name: git-clone
  namespace: default
spec:
  # 定义所需的参数
  params:
  - description: git仓库地址
    name: url
    type: string
  - default: ""
    description: 修订信息,比如分支名或者tag等
    name: revision
    type: string
  - default: ""
    description: Refspec to fetch before checking out revision.
    name: refspec
    type: string
  - default: "true"
    description: 初始化子模块
    name: submodules
    type: string
  - default: "1"
    description: 执行浅克隆
    name: depth
    type: string
  - default: "true"
    description: 将http.sslVerify设置为false
    name: sslVerify
    type: string
  - default: ca-bundle.crt
    description: 设置ca证书文件名
    name: crtFileName
    type: string
  - default: ""
    description: 设置clone到的子目录
    name: subdirectory
    type: string
  - default: ""
    description: 定义要匹配的目录模式
    name: sparseCheckoutDirectories
    type: string
  - default: "true"
    description: 删除已存在的目录
    name: deleteExisting
    type: string
  - default: ""
    description: HTTP proxy server for non-SSL requests.
    name: httpProxy
    type: string
  - default: ""
    description: HTTPS proxy server for SSL requests.
    name: httpsProxy
    type: string
  - default: ""
    description: Opt out of proxying HTTP/HTTPS requests.
    name: noProxy
    type: string
  - default: "true"
    description: Log the commands that are executed during `git-clone`'s operation.
    name: verbose
    type: string
  - default: quanheng.com/k8s/git-init:v0.40.2
    description: The image providing the git-init binary that this Task runs.
    name: gitInitImage
    type: string
  - default: /home/git
    description: |
      Absolute path to the user's home directory.
    name: userHome
    type: string
  results:
  - description: The precise commit SHA that was fetched by this Task.
    name: commit
    type: string
  - description: The precise URL that was fetched by this Task.
    name: url
    type: string
  - description: The epoch timestamp of the commit that was fetched by this Task.
    name: committer-date
    type: string
  steps:
  - computeResources: {}
    env:
    - name: HOME
      value: $(params.userHome)
    - name: PARAM_URL
      value: $(params.url)
    - name: PARAM_REVISION
      value: $(params.revision)
    - name: PARAM_REFSPEC
      value: $(params.refspec)
    - name: PARAM_SUBMODULES
      value: $(params.submodules)
    - name: PARAM_DEPTH
      value: $(params.depth)
    - name: PARAM_SSL_VERIFY
      value: $(params.sslVerify)
    - name: PARAM_CRT_FILENAME
      value: $(params.crtFileName)
    - name: PARAM_SUBDIRECTORY
      value: $(params.subdirectory)
    - name: PARAM_DELETE_EXISTING
      value: $(params.deleteExisting)
    - name: PARAM_HTTP_PROXY
      value: $(params.httpProxy)
    - name: PARAM_HTTPS_PROXY
      value: $(params.httpsProxy)
    - name: PARAM_NO_PROXY
      value: $(params.noProxy)
    - name: PARAM_VERBOSE
      value: $(params.verbose)
    - name: PARAM_SPARSE_CHECKOUT_DIRECTORIES
      value: $(params.sparseCheckoutDirectories)
    - name: PARAM_USER_HOME
      value: $(params.userHome)
    - name: WORKSPACE_OUTPUT_PATH
      value: $(workspaces.output.path)
    - name: WORKSPACE_SSH_DIRECTORY_BOUND
      value: $(workspaces.ssh-directory.bound)
    - name: WORKSPACE_SSH_DIRECTORY_PATH
      value: $(workspaces.ssh-directory.path)
    - name: WORKSPACE_BASIC_AUTH_DIRECTORY_BOUND
      value: $(workspaces.basic-auth.bound)
    - name: WORKSPACE_BASIC_AUTH_DIRECTORY_PATH
      value: $(workspaces.basic-auth.path)
    - name: WORKSPACE_SSL_CA_DIRECTORY_BOUND
      value: $(workspaces.ssl-ca-directory.bound)
    - name: WORKSPACE_SSL_CA_DIRECTORY_PATH
      value: $(workspaces.ssl-ca-directory.path)
    image: $(params.gitInitImage)
    name: clone
    script: |
      #!/usr/bin/env sh
      set -eu

      if [ "${PARAM_VERBOSE}" = "true" ] ; then
        set -x
      fi

      if [ "${WORKSPACE_BASIC_AUTH_DIRECTORY_BOUND}" = "true" ] ; then
        cp "${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/.git-credentials" "${PARAM_USER_HOME}/.git-credentials"
        cp "${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/.gitconfig" "${PARAM_USER_HOME}/.gitconfig"
        chmod 400 "${PARAM_USER_HOME}/.git-credentials"
        chmod 400 "${PARAM_USER_HOME}/.gitconfig"
      fi

      if [ "${WORKSPACE_SSH_DIRECTORY_BOUND}" = "true" ] ; then
        cp -R "${WORKSPACE_SSH_DIRECTORY_PATH}" "${PARAM_USER_HOME}"/.ssh
        chmod 700 "${PARAM_USER_HOME}"/.ssh
        chmod -R 400 "${PARAM_USER_HOME}"/.ssh/*
      fi

      if [ "${WORKSPACE_SSL_CA_DIRECTORY_BOUND}" = "true" ] ; then
         export GIT_SSL_CAPATH="${WORKSPACE_SSL_CA_DIRECTORY_PATH}"
         if [ "${PARAM_CRT_FILENAME}" != "" ] ; then
            export GIT_SSL_CAINFO="${WORKSPACE_SSL_CA_DIRECTORY_PATH}/${PARAM_CRT_FILENAME}"
         fi
      fi
      CHECKOUT_DIR="${WORKSPACE_OUTPUT_PATH}/${PARAM_SUBDIRECTORY}"

      cleandir() {
        # Delete any existing contents of the repo directory if it exists.
        #
        # We don't just "rm -rf ${CHECKOUT_DIR}" because ${CHECKOUT_DIR} might be "/"
        # or the root of a mounted volume.
        if [ -d "${CHECKOUT_DIR}" ] ; then
          # Delete non-hidden files and directories
          rm -rf "${CHECKOUT_DIR:?}"/*
          # Delete files and directories starting with . but excluding ..
          rm -rf "${CHECKOUT_DIR}"/.[!.]*
          # Delete files and directories starting with .. plus any other character
          rm -rf "${CHECKOUT_DIR}"/..?*
        fi
      }

      if [ "${PARAM_DELETE_EXISTING}" = "true" ] ; then
        cleandir || true
      fi

      test -z "${PARAM_HTTP_PROXY}" || export HTTP_PROXY="${PARAM_HTTP_PROXY}"
      test -z "${PARAM_HTTPS_PROXY}" || export HTTPS_PROXY="${PARAM_HTTPS_PROXY}"
      test -z "${PARAM_NO_PROXY}" || export NO_PROXY="${PARAM_NO_PROXY}"

      git config --global --add safe.directory "${WORKSPACE_OUTPUT_PATH}"
      /ko-app/git-init \
        -url="${PARAM_URL}" \
        -revision="${PARAM_REVISION}" \
        -refspec="${PARAM_REFSPEC}" \
        -path="${CHECKOUT_DIR}" \
        -sslVerify="${PARAM_SSL_VERIFY}" \
        -submodules="${PARAM_SUBMODULES}" \
        -depth="${PARAM_DEPTH}" \
        -sparseCheckoutDirectories="${PARAM_SPARSE_CHECKOUT_DIRECTORIES}"
      cd "${CHECKOUT_DIR}"
      RESULT_SHA="$(git rev-parse HEAD)"
      EXIT_CODE="$?"
      if [ "${EXIT_CODE}" != 0 ] ; then
        exit "${EXIT_CODE}"
      fi
      RESULT_COMMITTER_DATE="$(git log -1 --pretty=%ct)"
      printf "%s" "${RESULT_COMMITTER_DATE}" > "$(results.committer-date.path)"
      printf "%s" "${RESULT_SHA}" > "$(results.commit.path)"
      printf "%s" "${PARAM_URL}" > "$(results.url.path)"
    securityContext:
      runAsNonRoot: true
      runAsUser: 65532
  workspaces:
  - description: git仓库克隆到的目录
    name: output
  - description: |
      sshkey的目录,这个目录下面应该有一个id_rsa和id_rsa.pub文件,这个目录会被挂载到
    name: ssh-directory
    optional: true
  - description: |
      基础认证的目录,这个目录下面应该有一个.git-credentials和.gitconfig文件,这个目录会被挂载到
    name: basic-auth
    optional: true
  - description: |
      ca证书的目录,这个目录下面应该有一个ca-bundle.crt文件,这个目录会被挂载到
    name: ssl-ca-directory
    optional: true

8.2.2 生成task-build镜像

apiVersion: tekton.dev/v1
kind: Task
  name: kaniko
  namespace: default
spec:
  description: This Task builds a simple Dockerfile with kaniko and pushes to a registry.
    This Task stores the image name and digest as results, allowing Tekton Chains
    to pick up that an image was built & sign it.
  params:
  - description: Name (reference) of the image to build.
    name: IMAGE
    type: string
  - default: ./Dockerfile
    description: Path to the Dockerfile to build.
    name: DOCKERFILE
    type: string
  - default: ./
    description: The build context used by Kaniko.
    name: CONTEXT
    type: string
  - default: []
    name: EXTRA_ARGS
    type: array
  - default: registry.cn-hangzhou.aliyuncs.com/weiyigeek/kaniko-executor:latest
    description: The image on which builds will run (default is v1.5.1)
    name: BUILDER_IMAGE
    type: string
  results:
  - description: Digest of the image just built.
    name: IMAGE_DIGEST
    type: string
  - description: URL of the image just built.
    name: IMAGE_URL
    type: string
  steps:
  - args:
    - $(params.EXTRA_ARGS)
    - --insecure
    - --skip-tls-verify
    - --skip-tls-verify-pull
    - --dockerfile=$(params.DOCKERFILE)
    - --context=$(workspaces.source.path)/$(params.CONTEXT)
    - --destination=$(params.IMAGE)
    - --digest-file=$(results.IMAGE_DIGEST.path)
    computeResources: {}
    image: $(params.BUILDER_IMAGE)
    name: build-and-push
    securityContext:
      runAsUser: 0
    volumeMounts:
    - mountPath: /etc/hosts
      name: hosts
    - mountPath: /workspace/source/hosts
      name: host
    workingDir: $(workspaces.source.path)
  - computeResources: {}
    image: quanheng.com/k8s/bash:5.1.4
    name: write-url
    script: |
      set -e
      image="$(params.IMAGE)"
      echo -n "${image}" | tee "$(results.IMAGE_URL.path)"
    volumeMounts:
    - mountPath: /etc/hosts
      name: hosts
  volumes:
  - hostPath:
      path: /etc/hosts
    name: hosts
  - hostPath:
      path: /etc/hosts
    name: host
  workspaces:
  - description: Holds the context and Dockerfile
    name: source
  - description: Includes a docker `config.json`
    mountPath: /kaniko/.docker
    name: docker-credentials
    optional: true

8.2.3 生成pipeline


posted on   要快乐不要emo  阅读(119)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示