使用 Workspaces 加速 Tekton 流水线

k8s技术圈

共 11130字,需浏览 23分钟

 ·

2021-06-19 21:07

在实际工作中,我们经常需要的一个功能是能够在任务之间共享制品,以便缓存构建工具(比如 Maven 和 NPM)的依赖项,在 Tekton 0.10 版本就发布增加了对 Workspaces 的支持,这使得流水线中的任务可以更加轻松地使用 PV 来共享数据了,Workspaces 允许指定一个或多个 pipeline 中 task 运行时需要的 volume。

Tekton Pipelines 中的 Workspaces 是指流水线运行时需要的共享卷的声明,在流水线定义中,Workspaces 可以作为共享卷传递给相关任务,这样当为多个任务提供相同的 Workspaces 的时候,它们就可以从相同的 Volumes 中读取和写入数据。当然 Workspaces 的 Volumes 卷除了可以是 PVC,也可以是 ConfigMap,或者是在任务之间挂载和共享的 Secret 资源。

接下来让我们看看在实践中如何使用 Workspaces 来缓存 Maven 依赖,加速流水线的构建,这里我们使用的项目为:https://github.com/cnych/spring-petclinic。

要在流水线中构建 Maven 项目,当然需要定义一个 Maven 的 Task 任务,其实在 Tekton Catalog 里面就已经包含了这样的通用的 Task 了,但是这里我们需要对其进行一些修改来为 Maven 的依赖项添加 Workspaces 支持。

# workspace-mvn-task.yaml
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: mvn-task
spec:
  workspaces:
  - name: maven-repo
  resources:
    inputs:
    - name: source
      type: git
  params:
  - name: GOALS
    description: The Maven goals to run
    type: array
    default: ["package"]
  steps:
    - name: mvn
      image: cnych/cloud-builders-mvn:tekton
      workingDir: /workspace/source
      command: ["/usr/bin/mvn"]
      args:
        - -Dmaven.repo.local=$(workspaces.maven-repo.path)
        - "$(inputs.params.GOALS)"

上面的任务中我们新增了一个名为 maven-repo 的 Workspace,该工作区规定无论何时运行该任务,都应该提供并配置一个卷来充当本地的 Maven 存储库,然后将工作区的路径传递给 Maven 命令,以便通过 -Dmaven.repo.local=$(workspaces.maven-repo.path) 命令将工作区的路径作为本地的 Maven 库,当然也可以配置 Workspace 挂载的路径,这里我们使用的是默认的路径。

接着我们来定义一个使用 Maven 任务构建 Java 应用程序的流水线 Pipeline,为了演示 Maven 依赖的缓存效果,这里的流水线我们运行3个 Maven 任务来执行构建、集成测试,并生成测试结果和代码覆盖率等报告。

流水线定义如下所示:

# workspace-mvn-pipeline.yaml
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: mvn-pipeline
spec:
  workspaces:  # 声明 workspaces
  - name: local-maven-repo
  resources: # 声明使用的资源
  - name: app-git
    type: git
  tasks:
  - name: build  # 构建任务
    taskRef:
      name: mvn-task  # 引用上面的 mvn 任务
    resources:  # 传递 resources 资源
      inputs:
      - name: source
        resource: app-git
    params:  # 传递 params 参数
    - name: GOALS
      value: ["package"]
    workspaces:  # 传递 workspaces
    - name: maven-repo
      workspace: local-maven-repo
  - name: int-test  # 测试任务
    taskRef:
      name: mvn-task
    runAfter: ["build"]  # 需要 build 任务执行完成后
    resources:
      inputs:
      - name: source
        resource: app-git
    params:
    - name: GOALS
      value: ["verify"]
    workspaces:
    - name: maven-repo
      workspace: local-maven-repo
  - name: gen-report  # 测试报告
    taskRef:
      name: mvn-task
    runAfter: ["build"]  # 需要 build 任务执行完成后
    resources:
      inputs:
      - name: source
        resource: app-git
    params:
    - name: GOALS
      value: ["site"]
    workspaces:
    - name: maven-repo
      workspace: local-maven-repo

需要注意流水线中的 local-maven-repo 工作区的声明,它指出,当此流水线运行时,应提供一个卷并将其用作此工作区,然后将此工作区提供给此流水线中的每个任务,以便它们都共享相同的工作区。然后我们根据传入的 GOALS 参数来决定应该执行的任务。

流水线 Pipeline 声明完成后,现在我们就可以运行这个流水线来构建 Spring PetClinic 这个示例应用了,在启动流水线之前,需要先创建一个 PVC 来提供一个 Workspace 对 Maven 依赖项进行缓存。

# workspace-mvn-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mvn-repo-pvc
spec:
  resources:
    requests:
      storage: 5Gi
  volumeMode: Filesystem
  storageClassName: nfs-storage  # 使用 StorageClass 自动生成 PV
  accessModes:
    - ReadWriteOnce

这里我们使用了一个名为 nfs-storage 的 StorageClass,这样就可以自动生成一个对应的 PV 进行绑定,如果你没有需要自行创建一个对应的静态 PV。

现在我们就可以创建一个使用上述 PVC 作为流水线工作区的 PipelineRun 来执行流水线了:

# workspace-mvn-pipelinerun.yaml
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
  name: mvn-pipelinerun
spec:
  pipelineRef:
    name: mvn-pipeline
  resources:
  - name: app-git
    resourceSpec:
      type: git
      params:
        - name: url
          value: https://github.com.cnpmjs.org/cnych/spring-petclinic
  workspaces:
  - name: local-maven-repo
    persistentVolumeClaim:
      claimName: mvn-repo-pvc

请注意 PVC 和为缓存 maven 依赖项而声明的工作区之间的映射,mvn-repo-pvc 被传递到流水线和相应的任务作为缓存文件和制品的共享卷。

第一次流水线运行将需要一些时间来下载依赖项执行任务,直接创建上面声明的几个资源对象,观察 PipelineRun 的执行过程:

kubectl apply -f workspace-mvn-task.yaml
kubectl apply -f workspace-mvn-pipeline.yaml
kubectl apply -f workspace-mvn-pvc.yaml
kubectl apply -f workspace-mvn-pipelinerun.yaml

当第一次执行流水线的时候会在执行 mvn 命令的时候消耗大量的时间,因为需要下载依赖包,我这里的环境差不多等了20分钟左右:

然后在执行后面的两个任务的时候就非常快了,因为前面任务执行完成后会把依赖项存入到 Workspace 声明的 PVC 中去,后面的任务直接使用了这个 Workspace,我们可以重新执行一次 PipelineRun,对比下前后两次的时间,在我的环境中,执行时间由37分钟减少到大约两分钟。

$ tkn pr list
NAME                      STARTED         DURATION     STATUS
mvn-pipelinerun-r-fgwf2   3 minutes ago   2 minutes    Succeeded
mvn-pipelinerun           2 hours ago     37 minutes   Succeeded
# 查看第一次pipelinerun的执行情况
$ tkn pr describe mvn-pipelinerun
Name:              mvn-pipelinerun
Namespace:         default
Pipeline Ref:      mvn-pipeline
Service Account:   default
Timeout:           1h0m0s
Labels:
 tekton.dev/pipeline=mvn-pipeline

🌡️  Status

STARTED       DURATION     STATUS
2 hours ago   37 minutes   Succeeded
......
🗂  Taskruns

 NAME                                 TASK NAME    STARTED       DURATION     STATUS
 ∙ mvn-pipelinerun-int-test-mbppx     int-test     2 hours ago   33 seconds   Succeeded
 ∙ mvn-pipelinerun-gen-report-xlns9   gen-report   2 hours ago   36 minutes   Succeeded
 ∙ mvn-pipelinerun-build-x9zkf        build        2 hours ago   20 minutes   Succeeded

#
 查看第二次执行的详细信息
$ tkn pr describe mvn-pipelinerun-r-fgwf2
Name:              mvn-pipelinerun-r-fgwf2
Namespace:         default
Pipeline Ref:      mvn-pipeline
Service Account:   default
Timeout:           1h0m0s
Labels:
 reruns=mvn-pipelinerun
 tekton.dev/pipeline=mvn-pipeline

🌡️  Status

STARTED         DURATION    STATUS
4 minutes ago   2 minutes   Succeeded
......

🗂  Taskruns

 NAME                                         TASK NAME    STARTED         DURATION     STATUS
 ∙ mvn-pipelinerun-r-fgwf2-gen-report-n69g8   gen-report   4 minutes ago   1 minute     Succeeded
 ∙ mvn-pipelinerun-r-fgwf2-int-test-4g58z     int-test     4 minutes ago   32 seconds   Succeeded
 ∙ mvn-pipelinerun-r-fgwf2-build-ftqgr        build        4 minutes ago   38 seconds   Succeeded

测试任务运行没有受到太大影响,因为它使用了大部分在构建任务运行中下载的依赖项,即使在第一次流水线运行中也是如此。

我们可以看到利用 Workspaces 功能可以对我们的流水线构建进行大幅度的优化,特别是对于依赖包特别大的应用,比如 Maven、NPM、Go Modules 等。


浏览 55
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报