云原生 CI/CD 框架 Tekton 初体验

云计算 云原生
Tekton 是一款功能非常强大而灵活的 CI/CD 开源的云原生框架。Tekton 的前身是 Knative 项目的 build-pipeline 项目。

[[404558]]

Tekton 是一款功能非常强大而灵活的 CI/CD 开源的云原生框架。Tekton 的前身是 Knative 项目的 build-pipeline 项目,这个项目是为了给 build 模块增加 pipeline 的功能,但是随着不同的功能加入到 Knative build 模块中,build 模块越来越变得像一个通用的 CI/CD 系统,于是,索性将 build-pipeline 剥离出 Knative,就变成了现在的 Tekton,而 Tekton 也从此致力于提供全功能、标准化的云原生 CI/CD 解决方案。

Tekton 为 CI/CD 系统提供了诸多好处:

  • 可定制:Tekton 是完全可定制的,具有高度的灵活性,我们可以定义非常详细的构建块目录,供开发人员在各种场景中使用。
  • 可重复使用:Tekton 是完全可移植的,任何人都可以使用给定的流水线并重用其构建块,可以使得开发人员无需"造轮子"就可以快速构建复杂的流水线。
  • 可扩展:Tekton Catalog 是社区驱动的 Tekton 构建块存储库,我们可以使用 Tekton Catalog 中定义的组件快速创建新的流水线并扩展现有管道。
  • 标准化:Tekton 在你的 Kubernetes 集群上作为扩展安装和运行,并使用完善的 Kubernetes 资源模型,Tekton 工作负载在 Kubernetes Pod 内执行。
  • 伸缩性:要增加工作负载容量,只需添加新的节点到集群即可,Tekton 可随集群扩展,无需重新定义资源分配或对管道进行任何其他修改。

组件

Tekton 由一些列组件组成:

  • Tekton Pipelines 是 Tekton 的基础,它定义了一组 Kubernetes CRD 作为构建块,我们可以使用这些对象来组装 CI/CD 流水线。
  • Tekton Triggers 允许我们根据事件来实例化流水线,例如,可以我们在每次将 PR 合并到 GitHub 仓库的时候触发流水线实例和构建工作。
  • Tekton CLI 提供了一个名为 tkn 的命令行界面,它构建在 Kubernetes CLI 之上,运行和 Tekton 进行交互。
  • Tekton Dashboard 是 Tekton Pipelines 的基于 Web 的一个图形界面,可以线上有关流水线执行的相关信息。
  • Tekton Catalog 是一个由社区贡献的高质量 Tekton 构建块(任务、流水线等)存储库,可以直接在我们自己的流水线中使用这些构建块。
  • Tekton Hub 是一个用于访问 Tekton Catalog 的 Web 图形界面工具。
  • Tekton Operator 是一个 Kubernetes Operator,可以让我们在 Kubernetes 集群上安装、更新、删除 Tekton 项目。

安装

安装 Tekton 非常简单,可以直接通过 tektoncd/pipeline 的 GitHub 仓库中的 release.yaml 文件进行安装,如下所示的命令:

  1. kubectl apply --filename https://storage.googleapis.com/tekton-releases/pipeline/previous/v0.24.1/release.yaml 

由于官方使用的镜像是 gcr 的镜像,所以正常情况下我们是获取不到的,如果你的集群由于某些原因获取不到镜像,可以使用下面的资源清单文件,我已经将镜像替换成了 Docker Hub 上面的镜像:

  1. kubectl apply -f http://my-oss-testing.oss-cn-beijing.aliyuncs.com/k8s/tekton/release.yaml 

上面的资源清单文件安装后,会创建一个名为 tekton-pipelines 的命名空间,在该命名空间下面会有大量和 tekton 相关的资源对象,我们可以通过在该命名空间中查看 Pod 并确保它们处于 Running 状态来检查安装是否成功:

  1. $ kubectl get pods -n tekton-pipelines 
  2. NAME                                           READY   STATUS    RESTARTS   AGE 
  3. tekton-pipelines-controller-795dd94d96-lkbxt   1/1     Running   0          92s 
  4. tekton-pipelines-webhook-6b8964445d-mp4k6      1/1     Running   0          92s 

Tekton 安装完成后,我们还可以选择是否安装 CLI 工具,有时候可能 Tekton 提供的命令行工具比 kubectl 管理这些资源更加方便,当然这并不是强制的,我这里是 Mac 系统,所以可以使用常用的 Homebrew 工具来安装:

  1. brew tap tektoncd/tools 
  2. brew install tektoncd/tools/tektoncd-cli 

安装完成后可以通过如下命令验证 CLI 是否安装成功:

  1. $ tkn version 
  2. Client version: 0.15.0 
  3. Pipeline version: v0.24.1 
  4. Dashboard version: v0.17.0 

还可以从 tknReleases 页面下载安装包,下载文件后,将其解压缩到您的 PATH:

  1. Replace YOUR-DOWNLOADED-FILE with the file path of your own. 
  2. sudo tar xvzf YOUR-DOWNLOADED-FILE -C /usr/local/bin/ tkn 

此外,还可以安装一个 Tekton 提供的一个 Dashboard,我们可以通过 Dashboard 查看 Tekton 整个任务的构建过程,直接执行下面的命令直接安装即可:

  1. kubectl apply -f http://my-oss-testing.oss-cn-beijing.aliyuncs.com/k8s/tekton/dashboard.yaml 

安装完成后我们可以通过 Dashboard 的 Service 的 NodePort 来访问应用。

概念

Tekton 为 Kubernetes 提供了多种 CRD 资源对象,可用于定义我们的流水线。

主要有以下几个资源对象:

  • Task:表示执行命令的一系列有序的步骤,task 里可以定义一系列的 steps,例如编译代码、构建镜像、推送镜像等,每个 step 实际由一个 Pod 执行。
  • Pipeline:一组有序的 Task,Pipeline 中的 Task 可以使用之前执行过的 Task 的输出作为它的输入。表示一个或多个 Task、PipelineResource 以及各种定义参数的集合。
  • TaskRun:Task 只是定义了一个模版,TaskRun 才真正代表了一次实际的运行,当然你也可以自己手动创建一个 TaskRun,TaskRun 创建出来之后,就会自动触发 Task 描述的构建任务。
  • PipelineRun:类似 Task 和 TaskRun 的关系,PipelineRun 也表示某一次实际运行的 pipeline,下发一个 PipelineRun CRD 实例到 Kubernetes 后,同样也会触发一次 pipeline 的构建。
  • ClusterTask:覆盖整个集群的任务,而不是单一的某一个命名空间,这是和 Task 最大的区别,其他基本上一致的。
  • PipelineResource:表示 pipeline 输入资源,比如 github 上的源码,或者 pipeline 输出资源,例如一个容器镜像或者构建生成的 jar 包等。

每个任务都在自己的 Kubernetes Pod 中执行,因此,默认情况下,管道内的任务不共享数据。要在 Tasks 之间共享数据,你必须明确配置每个 Task 以使其输出可用于下一个 Task 并获取先前执行的 Task 的输出作为其输入。

示例

使用 Tekton 后你的 CI/CD 工作流中的每个操作都变成了一个 Step,使用指定的容器镜像来执行。Steps 然后组织在 Tasks 中,它在集群中作为 Kubernetes Pod 运行,还可以进一步组织 Tasks 变成成 Pipelines,还可以控制几个 Tasks 的执行顺序。

在这里我们使用一个简单的 Golang 应用,可以在仓库 https://github.com/cnych/tekton-demo 下面获取应用程序代码,测试以及 Dockerfile 文件。

首先第一个任务就是 Clone 应用程序代码进行测试,要创建一个 Task 任务,就需要使用到 Kubernetes 中定义的 Task 这个 CRD 对象,这里我们创建一个如下所示的资源文件,内容如下所示:

  1. # task-test.yaml 
  2. apiVersion: tekton.dev/v1beta1 
  3. kind: Task 
  4. metadata: 
  5.   name: test 
  6. spec: 
  7.   resources: 
  8.     inputs: 
  9.       - name: repo 
  10.         type: git 
  11.   steps: 
  12.     - name: run-test 
  13.       image: golang:1.14-alpine 
  14.       workingDir: /workspace/repo 
  15.       command: ['go'
  16.       args: ['test'

其中 resources 定义了我们的任务中定义的 Step 所需的输入内容,这里我们的步骤需要 Clone 一个 Git 仓库作为 go test 命令的输入,目前支持 git、pullRequest、image、cluster、storage、cloudevent 等资源。

Tekton 内置的 git 资源类型,它会自动将代码仓库 Clone 到 /workspace/$input_name 目录中,由于我们这里输入被命名成 repo,所以代码会被 Clone 到 /workspace/repo 目录下面。

然后下面的 steps 就是来定义执行运行测试命令的步骤,这里我们直接在代码的根目录中运行 go test 命令即可,需要注意的是命令和参数需要分别定义。

定义完成后直接使用 kubectl 创建该任务:

  1. $ kubectl apply -f task-test.yaml 
  2. task.tekton.dev/test created 

现在我们定义完成了一个新建的 Task 任务,但是该任务并不会立即执行,我们必须创建一个 TaskRun 引用它并提供所有必需输入的数据才行。当然我们也可以直接使用 tkn 命令来启动这个 Task 任务,我们可以通过如下所示的命令来获取启动 Task 所需的资源对象:

  1. $ tkn task start test --dry-run 
  2. no pipeline resource of type "git" found in namespace: default 
  3. Please create a new "git" resource for pipeline resource "repo" 
  4. ? Enter a name for a pipeline resource : demo-git 
  5. ? Enter a value for url :  https://github.com/cnych/tekton-demo 
  6. ? Enter a value for revision :  master 
  7. New git resource "demo-git" has been created 
  8. apiVersion: tekton.dev/v1beta1 
  9. kind: TaskRun 
  10. metadata: 
  11.   creationTimestamp: null 
  12.   generateName: test-run- 
  13.   namespace: default 
  14. spec: 
  15.   resources: 
  16.     inputs: 
  17.     - name: repo 
  18.       resourceRef: 
  19.         name: demo-git 
  20.   serviceAccountName: "" 
  21.   taskRef: 
  22.     name: test 
  23. status: 
  24.   podName: "" 

由于我们这里的 Task 任务需要一个 git 代码仓库作为输入,所以需要一个 PipelineResource 对象来定义输入信息,上面的命令会自动创建一个名为 demo-git 的 PipelineResource 资源对象,如下所示:

  1. $ kubectl get pipelineresource 
  2. NAME       AGE 
  3. demo-git   3m37s 
  4. $ kubectl get pipelineresource demo-git -o yaml 
  5. apiVersion: tekton.dev/v1alpha1 
  6. kind: PipelineResource 
  7. metadata: 
  8.   name: demo-git 
  9.   namespace: default 
  10.   ...... 
  11. spec: 
  12.   params: 
  13.   - name: url 
  14.     value: https://github.com/cnych/tekton-demo 
  15.   - name: revision 
  16.     value: master 
  17.   type: git 

当我们不知道如何创建 PipelineResource 的时候我们就可以参考上面的方式来创建,当然最后还需要创建 TaskRun 对象才可以真正执行这个 Task 任务,上面的 tkn task start 命令也为我们打印出对应的 TaskRun 资源,将其内容添加到 taskrun.yaml 文件中:

  1. # taskrun.yaml 
  2. apiVersion: tekton.dev/v1beta1 
  3. kind: TaskRun 
  4. metadata: 
  5.   name: testrun 
  6. spec: 
  7.   resources: 
  8.     inputs: 
  9.       - name: repo 
  10.         resourceRef: 
  11.           name: demo-git 
  12.   taskRef: 
  13.     name: test 

这里的 taskRef 引用上面定义的 Task 和 git 仓库作为输入,resourceRef 也是引用上面定义的 PipelineResource 资源对象。现在我们创建这个资源对象过后,就会开始运行了:

  1. $ kubectl apply -f taskrun.yaml 
  2. taskrun.tekton.dev/testrun created 

Tekton 现在将开始运行您的 Task, 要查看最后一个 TaskRun 的日志,可以使用以下 tkn命令:

  1. tkn taskrun logs --last -f 

此外我们还可以通过查看 TaskRun 资源对象的状态来查看构建状态:

  1. $ kubectl get taskrun 
  2. NAME      SUCCEEDED   REASON    STARTTIME   COMPLETIONTIME 
  3. testrun   Unknown     Pending   21s 
  4. $ kubectl get pods 
  5. NAME                             READY   STATUS     RESTARTS   AGE 
  6. testrun-pod-l629c                0/2     Init:1/2   0          59s 
  7. $ kubectl describe pod testrun-pod-l629c 
  8. Name:         testrun-pod-l629c 
  9. Namespace:    default 
  10. ...... 
  11. Events: 
  12.   Type    Reason     Age    From               Message 
  13.   ----    ------     ----   ----               ------- 
  14.   Normal  Scheduled  2m53s  default-scheduler  Successfully assigned default/testrun-pod-l629c to node1 
  15.   Normal  Pulling    2m52s  kubelet, node1     Pulling image "cnych/tekton-distroless-base:v0.24.1" 
  16.   Normal  Pulled     2m27s  kubelet, node1     Successfully pulled image "cnych/tekton-distroless-base:v0.24.1" in 24.910571044s 
  17.   Normal  Created    2m27s  kubelet, node1     Created container working-dir-initializer 
  18.   Normal  Started    2m27s  kubelet, node1     Started container working-dir-initializer 
  19.   Normal  Pulling    2m27s  kubelet, node1     Pulling image "cnych/tekton-entrypoint:v0.24.1" 
  20.   Normal  Pulled     2m     kubelet, node1     Successfully pulled image "cnych/tekton-entrypoint:v0.24.1" in 27.120230223s 
  21.   Normal  Created    2m     kubelet, node1     Created container place-tools 
  22.   Normal  Started    2m     kubelet, node1     Started container place-tools 
  23.   Normal  Pulling    119s   kubelet, node1     Pulling image "cnych/tekton-git-init:v0.24.1" 
  24.   Normal  Pulled     82s    kubelet, node1     Successfully pulled image "cnych/tekton-git-init:v0.24.1" in 36.318235738s 
  25.   Normal  Created    82s    kubelet, node1     Created container step-git-source-repo-jg7vz 
  26.   Normal  Started    82s    kubelet, node1     Started container step-git-source-repo-jg7vz 
  27.   Normal  Pulling    82s    kubelet, node1     Pulling image "golang:1.14-alpine" 
  28.   Normal  Pulled     28s    kubelet, node1     Successfully pulled image "golang:1.14-alpine" in 54.587298174s 
  29.   Normal  Created    27s    kubelet, node1     Created container step-run-test 
  30.   Normal  Started    27s    kubelet, node1     Started container step-run-test 

我们可以通过 kubectl describe 命令来查看任务运行的过程,首先会通过 tekton-git-init 拉取代码,然后会使用我们定义的 Task 任务中的 Steps 镜像来执行任务。当任务执行完成后, Pod 就会变成 Completed 状态了:

  1. $ kubectl get pods 
  2. NAME                        READY   STATUS      RESTARTS   AGE 
  3. testrun-r-n97ls-pod-7jvrd   0/2     Completed   0          4m27s 
  4. $ kubectl get taskrun 
  5. NAME              SUCCEEDED   REASON      STARTTIME   COMPLETIONTIME 
  6. testrun-r-n97ls   True        Succeeded   16m         119s 

我们可以查看容器的日志信息来了解任务的执行结果信息:

  1. $ kubectl logs testrun-r-n97ls-pod-7jvrd --all-containers 
  2. 2021/06/08 09:07:31 Copied /ko-app/entrypoint to /tekton/tools/entrypoint 
  3. {"level":"info","ts":1623144122.7787642,"caller":"git/git.go:169","msg":"Successfully cloned https://github.com/cnych/tekton-demo @ c6c2a85091d538a13c44f85bcee9e861c362b0d3 (grafted, HEAD, origin/master) in path /workspace/repo"
  4. {"level":"info","ts":1623144122.796532,"caller":"git/git.go:207","msg":"Successfully initialized and updated submodules in path /workspace/repo"
  5. PASS 
  6. ok      _/workspace/repo        0.002s 

我们可以看到我们的测试已经通过了。

Docker Hub 配置

为了能够构建 Docker 镜像,一般来说我们需要使用 Docker 来进行,我们这里是容器,所以可以使用 Docker In Docker 模式,这种模式安全性不高,除了这种方式之外,我们还可以使用 Google 推出的 Kaniko 工具来进行构建,该工具可以在 Kubernetes 集群中构建 Docker 镜像而无需依赖 Docker 守护进程,之前我们已经介绍过 kaniko 这种形式,这里我们就介绍 DIND 这种模式。

使用 Kaniko 构建镜像和 Docker 命令基本上一致,所以我们可以提前设置下 Docker Hub 的登录凭证,方便后续将镜像推送到镜像仓库。登录凭证可以保存到 Kubernetes 的 Secret 资源对象中,创建一个名为 harbor-auth.yaml 的文件,内容如下所示:

  1. # harbor-auth.yaml 
  2. apiVersion: v1 
  3. kind: Secret 
  4. metadata: 
  5.   name: harbor-auth 
  6.   annotations: 
  7.     tekton.dev/docker-0: http://harbor.k8s.local 
  8. type: kubernetes.io/basic-auth 
  9. stringData: 
  10.   username: admin 
  11.   password: Harbor12345 

记得将 username 和 password 替换成你的 Harbor 仓库登录凭证。

我们这里在 Secret 对象中添加了一个 tekton.dev/docker-0 的 annotation,该注解信息是用来告诉 Tekton 这些认证信息所属的 Docker 镜像仓库。

然后创建一个 ServiceAccount 对象来使用上面的 docker-auth 这个 Secret 对象,创建一个名为 sa.yaml 的文件,内容如下所示:

  1. # sa.yaml 
  2. apiVersion: v1 
  3. kind: ServiceAccount 
  4. metadata: 
  5.   name: build-sa 
  6. secrets: 
  7.   - name: harbor-auth 

然后直接创建上面两个资源对象即可:

  1. $ kubectl apply -f harbor-auth.yaml 
  2. secret/harbor-auth created 
  3. $ kubectl apply -f sa.yaml 
  4. serviceaccount/build-sa created 

创建完成后,我们就可以在运行 Tekton 的任务或者流水线的时候使用上面的 build-sa 这个 ServiceAccount 对象来进行 Docker Hub 的登录认证了。

创建镜像任务

现在我们创建一个 Task 任务来构建并推送 Docker 镜像,我们这里使用的示例应用根目录下面已经包含了一个 Dockerfile 文件了,所以我们直接 Clone 代码就可以获得:

  1. FROM golang:1.14-alpine 
  2.  
  3. WORKDIR /go/src/app 
  4. COPY . . 
  5.  
  6. RUN go get -d -v ./... 
  7. RUN go install -v ./... 
  8.  
  9. CMD ["app"

创建一个名为 task-build-push.yaml 的文件,文件内容如下所示:

  1. apiVersion: tekton.dev/v1beta1 
  2. kind: Task 
  3. metadata: 
  4.   name: build-and-push 
  5. spec: 
  6.   resources: 
  7.     inputs: # 定义输入资源 
  8.       - name: repo #输入资源,就是github的那个仓库 
  9.         type: git 
  10.     outputs: # 定义输出资源 
  11.       - name: builtImage # 输出镜像名字 
  12.         type: image 
  13.   params: 
  14.     - name: pathToDockerfile #指明 dockerfile 在仓库中的哪个位置 
  15.       type: string 
  16.       default: /workspace/repo/Dockerfile # repo资源的路径 
  17.       description: dockerfile path 
  18.     - name: pathToContext #指明 dockerfile 在仓库中的哪个位置 
  19.       type: string 
  20.       default: /workspace/repo  # repo资源的路径 
  21.       description: the build context used by docker daemon 
  22.   steps: 
  23.     - name: build-and-push 
  24.       image: docker:stable 
  25.       script: | 
  26.         #!/usr/bin/env sh 
  27.         docker login harbor.k8s.local 
  28.         docker build -t $(resources.outputs.builtImage.url) -f $(params.pathToDockerfile) $(params.pathToContext) 
  29.         docker push $(resources.outputs.builtImage.url)  # 这边的参数都是在 input 和 output 中定义的 
  30.       volumeMounts: 
  31.         - name: dockersock #将docker.sock文件挂载进来,使用宿主机docker daemon 构建镜像 
  32.           mountPath: /var/run/docker.sock 
  33.   volumes: 
  34.     - name: dockersock 
  35.       hostPath: 
  36.         path: /var/run/docker.sock 

和前面的测试任务类似,这里我们同样将 git 作为输入资源,此外还定义了一个 dockerfile-path 的参数,用来指定 Dockerfile 的路径,此外还定义了一个名为 builtImage 的镜像输出资源,用来定义 Docker 镜像的相关参数。然后定义了一个名为 build-and-push 的步骤,这里我们使用 DIND 的方式,将宿主机的 /var/run/docker.sock 文件挂载到 docker:stable 的容器中,然后执行 script 下面的 Docker 镜像构建推送的操作。同样直接创建上面的资源对象即可:

  1. $ kubectl apply -f task-build-push.yaml 
  2. task.tekton.dev/build-and-push created 

创建了 Task 任务过后,要想真正去执行这个任务,我们就需要创建一个对应的 TaskRun 资源对象。

执行任务

和前面一样,现在我们来创建一个 TaskRun 对象来触发任务,不同之处在于我们需要指定 Task 时需要的 ServiceAccount 对象。创建一个名为 taskrun-build-push.yaml 的文件,内容如下所示:

  1. # taskrun-build-push.yaml 
  2. apiVersion: tekton.dev/v1beta1 
  3. kind: TaskRun 
  4. metadata: 
  5.   name: build-and-push 
  6. spec: 
  7.   serviceAccountName: build-sa 
  8.   taskRef: 
  9.     name: build-and-push # 关联定义好的task 
  10.   resources: 
  11.     inputs: 
  12.       - name: repo # 指定输入的仓库资源 
  13.         resourceRef: 
  14.           name: demo-git 
  15.     outputs: # 指定输出的镜像资源 
  16.       - name: builtImage 
  17.         resourceRef: 
  18.           name: harbor-image 

注意这里我们通过 serviceAccountName 属性指定了 Docker 认证信息的 ServiceAccount对象,然后通过 taskRef 引用我们的任务,以及下面的 resourceRef 关联第一部分我们声明的输入资源,此外还需要定义一个关于输出镜像的 PipelineResource 资源:

  1. # harbor-image-res.yaml 
  2. apiVersion: tekton.dev/v1alpha1 
  3. kind: PipelineResource 
  4. metadata: 
  5.   name: harbor-image 
  6. spec: 
  7.   type: image 
  8.   params: 
  9.     - name: url 
  10.       value: harbor.k8s.local/course/tekton-demo:latest #构建完的镜像名称 

然后直接创建这个资源对象即可:

  1. $ kubectl apply -f harbor-image-res.yaml 
  2. pipelineresource.tekton.dev/harbor-image created 
  3. $ kubectl apply -f taskrun-build-push.yaml 
  4. taskrun.tekton.dev/build-and-push created 

创建完成后就会触发任务执行了,我们可以通过查看 Pod 对象状态来了解进度:

  1. $ kubectl get pods 
  2. NAME                                      READY   STATUS            RESTARTS   AGE 
  3. build-and-push-pod-fl65m                  0/4     PodInitializing   0          9s 
  4. $ kubectl get taskrun 
  5. NAME              SUCCEEDED   REASON      STARTTIME   COMPLETIONTIME 
  6. build-and-push    Unknown     Pending     26s 

现在任务执行的 Pod 还在初始化容器阶段,我们可以看到 TaskRun 的状态处于 Pending,隔一会儿正常构建就会成功了,我们可以查看构建任务的 Pod 日志信息:

  1. $ kubectl get pods 
  2. NAME                                      READY   STATUS            RESTARTS   AGE 
  3. build-and-push-pod-fl65m                  0/4     PodInitializing   0          9s 
  4. $  tkn taskrun logs build-and-push 
  5.  
  6. [git-source-repo-rsvcf] {"level":"info","ts":1623151584.9503093,"caller":"git/git.go:169","msg":"Successfully cloned https://github.com/cnych/tekton-demo @ c6c2a85091d538a13c44f85bcee9e861c362b0d3 (grafted, HEAD, origin/master) in path /workspace/repo"
  7. [git-source-repo-rsvcf] {"level":"info","ts":1623151584.968812,"caller":"git/git.go:207","msg":"Successfully initialized and updated submodules in path /workspace/repo"
  8.  
  9. [build-and-push] Authenticating with existing credentials... 
  10. [build-and-push] WARNING! Your password will be stored unencrypted in /root/.docker/config.json. 
  11. [build-and-push] Configure a credential helper to remove this warning. See 
  12. [build-and-push] https://docs.docker.com/engine/reference/commandline/login/#credentials-store 
  13. [build-and-push] 
  14. [build-and-push] Login Succeeded 
  15. [build-and-push] Sending build context to Docker daemon  12.99MB 
  16. [build-and-push] Step 1/6 : FROM golang:1.14-alpine 
  17. ...... 
  18. [build-and-push] 9f9d00b69565: Pushed 
  19. [build-and-push] latest: digest: sha256:521a803fb15d2e05b6168cba36e6e31c548bdd369f274e86c8f5be2118cdb357 size: 2201 
  20.  
  21. [image-digest-exporter-mpbwq] {"severity":"INFO","timestamp":"2021-06-08T11:26:43.642545898Z","caller":"logging/config.go:116","message":"Successfully created the logger."
  22. [image-digest-exporter-mpbwq] {"severity":"INFO","timestamp":"2021-06-08T11:26:43.642786678Z","caller":"logging/config.go:117","message":"Logging level set to: info"
  23. [image-digest-exporter-mpbwq] {"severity":"INFO","timestamp":"2021-06-08T11:26:43.643090681Z","caller":"imagedigestexporter/main.go:59","message":"No index.json found for: builtImage","commit":"7ca5d61"
  24. $ kubectl get taskrun 
  25. NAME             SUCCEEDED   REASON      STARTTIME   COMPLETIONTIME 
  26. build-and-push   True        Succeeded   15m         2m24s 

我们可以看到 TaskRun 任务已经执行成功了。这个时候其实我们可以在 Harbor 上找到我们的镜像了,当然也可以直接使用这个镜像进行测试:

创建流水线

到这里前面我们的两个任务 test 和 build-and-push 都已经完成了,我们还可以创建一个流水线来将这两个任务组织起来,首先运行 test 任务,如果通过了再执行后面的 build-and-push 这个任务。

创建一个名为 pipeline.yaml 的文件,内容如下所示:

  1. apiVersion: tekton.dev/v1beta1 
  2. kind: Pipeline 
  3. metadata: 
  4.   name: test-build-push 
  5. spec: 
  6.   resources: 
  7.     - name: repo 
  8.       type: git 
  9.   tasks: 
  10.     # 运行应用测试 
  11.     - name: test 
  12.       taskRef: 
  13.         name: test 
  14.       resources: 
  15.         inputs: 
  16.           - name: repo # Task 输入名称 
  17.             resource: repo # Pipeline 资源名称 
  18.     # 构建并推送 Docker 镜像 
  19.     - name: build-and-push 
  20.       taskRef: 
  21.         name: build-and-push 
  22.       runAfter: 
  23.         - test # 测试任务执行之后 
  24.       resources: 
  25.         inputs: 
  26.           - name: repo # Task 输入名称 
  27.             resource: repo # Pipeline 资源名称 

首先我们需要定义流水线需要哪些资源,可以是输入或者输出的资源,在这里我们只有一个输入,那就是命名为 repo 的应用程序源码的 GitHub 仓库。接下来定义任务,每个任务都通过 taskRef 进行引用,并传递任务需要的输入参数。

同样直接创建这个资源对象即可:

  1. $ kubectl apply -f pipeline.yaml 
  2. pipeline.tekton.dev/test-build-push created 

前面我们提到过和通过创建 TaskRun 去触发 Task 任务类似,我们可以通过创建一个 PipelineRun 对象来运行流水线。这里我们创建一个名为 pipelinerun.yaml 的 PipelineRun 对象来运行流水线,文件内容如下所示:

  1. apiVersion: tekton.dev/v1beta1 
  2. kind: PipelineRun 
  3. metadata: 
  4.   name: test-build-push-run 
  5. spec: 
  6.   serviceAccountName: build-sa 
  7.   pipelineRef: 
  8.     name: test-build-push 
  9.   resources: 
  10.     - name: repo 
  11.       resourceRef: 
  12.         name: demo-git 

定义方式和 TaskRun 几乎一样,通过 serviceAccountName 属性指定 ServiceAccount 对象,pipelineRef 关联流水线对象。同样直接创建这个资源,创建后就会触发我们的流水线任务了:

  1. $ kubectl apply -f pipelinerun.yaml 
  2. pipelinerun.tekton.dev/test-build-push-run created 
  3. $ kubectl get pods | grep test-build-push-run 
  4. test-build-push-run-build-and-push-xl7wp-pod-hdnbl   0/2     Completed   0          5m27s 
  5. test-build-push-run-test-4s6qh-pod-tkwzk             0/2     Completed   0          6m5s 
  6. $ kubectl logs -f test-build-push-run-build-and-push-xl7wp-pod-hdnbl --all-containers 
  7. {"level":"info","ts":1588908934.442572,"caller":"git/git.go:136","msg":"Successfully cloned https://github.com/cnych/tekton-demo @ f840e0c390be9a1a6edad76abbde64e882047f05 (grafted, HEAD, origin/master) in path /workspace/repo"
  8. {"level":"info","ts":1588908934.577377,"caller":"git/git.go:177","msg":"Successfully initialized and updated submodules in path /workspace/repo"
  9. {"level":"info","ts":1588908927.469531,"caller":"creds-init/main.go:44","msg":"Credentials initialized."
  10. INFO[0004] Retrieving image manifest golang:1.14-alpine 
  11. ...... 
  12. app 
  13. INFO[0281] Taking snapshot of full filesystem... 
  14. INFO[0287] Resolving 11666 paths 
  15. INFO[0291] CMD ["app"
  16. $ kubectl get taskrun |grep test-build-push-run 
  17. test-build-push-run-build-and-push-xl7wp   True        Succeeded   6m21s       65s 
  18. test-build-push-run-test-4s6qh             True        Succeeded   6m58s       6m21s 

到这里证明我们的流水线执行成功了。我们将 Tekton 安装在 Kubernetes 集群上,定义了一个 Task,并通过 YAML 清单和 Tekton CLI 创建 TaskRun 对其进行了测试。我们创建了由两个任务组成的 Tektok 流水线,第一个任务是从 GitHub 克隆代码并运行应用程序测试,第二个任务是构建一个 Docker 镜像并将其推送到 Docker Hub 上。到这里我们就完成了使用 Tekton 创建 CI/CD 流水线的一个简单示例,不过这个示例还比较简单,接下来我们再通过一个稍微复杂点的应用来完成我们的流水线。

 

责任编辑:姜华 来源: k8s技术圈
相关推荐

2021-05-13 18:23:53

Tekton云原生Kubernetes

2021-11-26 08:14:05

云原生CICD

2023-08-07 08:48:13

2023-05-04 16:03:50

KubernetesCI/CD集成

2021-07-04 07:24:48

GitOps 工具 Argo CD

2022-02-21 10:17:33

Rancher开源云原生

2020-10-21 14:10:28

工具测试开发

2021-07-27 08:01:22

CICD平台

2021-08-26 07:20:05

云原生K8sSpringboot

2021-08-13 07:00:41

云原生k8sspringboot

2021-07-09 06:40:59

TektonArgo CD GitOps

2022-02-22 09:00:00

软件开发CI/CD 管道工具

2022-04-25 08:07:45

TektonArgocdCI和CD

2009-03-09 15:12:39

XenServer安装

2009-08-01 09:06:35

UbuntuOneLinux开源操作系统

2011-11-21 11:19:19

Oracle NoSQ

2023-04-02 21:49:10

开源Tekton

2021-07-02 16:30:01

CICDDevOps

2024-11-06 14:40:18

2010-11-16 09:12:42

SQL Azure
点赞
收藏

51CTO技术栈公众号