使用 Workspaces 加速 Tekton 流水線(xiàn)

在實(shí)際工作中,我們經(jīng)常需要的一個(gè)功能是能夠在任務(wù)之間共享制品,以便緩存構(gòu)建工具(比如 Maven 和 NPM)的依賴(lài)項(xiàng),在 Tekton 0.10 版本就發(fā)布增加了對(duì) Workspaces 的支持,這使得流水線(xiàn)中的任務(wù)可以更加輕松地使用 PV 來(lái)共享數(shù)據(jù)了,Workspaces 允許指定一個(gè)或多個(gè) pipeline 中 task 運(yùn)行時(shí)需要的 volume。
Tekton Pipelines 中的 Workspaces 是指流水線(xiàn)運(yùn)行時(shí)需要的共享卷的聲明,在流水線(xiàn)定義中,Workspaces 可以作為共享卷傳遞給相關(guān)任務(wù),這樣當(dāng)為多個(gè)任務(wù)提供相同的 Workspaces 的時(shí)候,它們就可以從相同的 Volumes 中讀取和寫(xiě)入數(shù)據(jù)。當(dāng)然 Workspaces 的 Volumes 卷除了可以是 PVC,也可以是 ConfigMap,或者是在任務(wù)之間掛載和共享的 Secret 資源。

接下來(lái)讓我們看看在實(shí)踐中如何使用 Workspaces 來(lái)緩存 Maven 依賴(lài),加速流水線(xiàn)的構(gòu)建,這里我們使用的項(xiàng)目為:https://github.com/cnych/spring-petclinic。
要在流水線(xiàn)中構(gòu)建 Maven 項(xiàng)目,當(dāng)然需要定義一個(gè) Maven 的 Task 任務(wù),其實(shí)在 Tekton Catalog 里面就已經(jīng)包含了這樣的通用的 Task 了,但是這里我們需要對(duì)其進(jìn)行一些修改來(lái)為 Maven 的依賴(lài)項(xiàng)添加 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)"
上面的任務(wù)中我們新增了一個(gè)名為 maven-repo 的 Workspace,該工作區(qū)規(guī)定無(wú)論何時(shí)運(yùn)行該任務(wù),都應(yīng)該提供并配置一個(gè)卷來(lái)充當(dāng)本地的 Maven 存儲(chǔ)庫(kù),然后將工作區(qū)的路徑傳遞給 Maven 命令,以便通過(guò) -Dmaven.repo.local=$(workspaces.maven-repo.path) 命令將工作區(qū)的路徑作為本地的 Maven 庫(kù),當(dāng)然也可以配置 Workspace 掛載的路徑,這里我們使用的是默認(rèn)的路徑。
接著我們來(lái)定義一個(gè)使用 Maven 任務(wù)構(gòu)建 Java 應(yīng)用程序的流水線(xiàn) Pipeline,為了演示 Maven 依賴(lài)的緩存效果,這里的流水線(xiàn)我們運(yùn)行3個(gè) Maven 任務(wù)來(lái)執(zhí)行構(gòu)建、集成測(cè)試,并生成測(cè)試結(jié)果和代碼覆蓋率等報(bào)告。

流水線(xiàn)定義如下所示:
# 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 # 構(gòu)建任務(wù)
taskRef:
name: mvn-task # 引用上面的 mvn 任務(wù)
resources: # 傳遞 resources 資源
inputs:
- name: source
resource: app-git
params: # 傳遞 params 參數(shù)
- name: GOALS
value: ["package"]
workspaces: # 傳遞 workspaces
- name: maven-repo
workspace: local-maven-repo
- name: int-test # 測(cè)試任務(wù)
taskRef:
name: mvn-task
runAfter: ["build"] # 需要 build 任務(wù)執(zhí)行完成后
resources:
inputs:
- name: source
resource: app-git
params:
- name: GOALS
value: ["verify"]
workspaces:
- name: maven-repo
workspace: local-maven-repo
- name: gen-report # 測(cè)試報(bào)告
taskRef:
name: mvn-task
runAfter: ["build"] # 需要 build 任務(wù)執(zhí)行完成后
resources:
inputs:
- name: source
resource: app-git
params:
- name: GOALS
value: ["site"]
workspaces:
- name: maven-repo
workspace: local-maven-repo
需要注意流水線(xiàn)中的 local-maven-repo 工作區(qū)的聲明,它指出,當(dāng)此流水線(xiàn)運(yùn)行時(shí),應(yīng)提供一個(gè)卷并將其用作此工作區(qū),然后將此工作區(qū)提供給此流水線(xiàn)中的每個(gè)任務(wù),以便它們都共享相同的工作區(qū)。然后我們根據(jù)傳入的 GOALS 參數(shù)來(lái)決定應(yīng)該執(zhí)行的任務(wù)。
流水線(xiàn) Pipeline 聲明完成后,現(xiàn)在我們就可以運(yùn)行這個(gè)流水線(xiàn)來(lái)構(gòu)建 Spring PetClinic 這個(gè)示例應(yīng)用了,在啟動(dòng)流水線(xiàn)之前,需要先創(chuàng)建一個(gè) PVC 來(lái)提供一個(gè) Workspace 對(duì) Maven 依賴(lài)項(xiàng)進(jìn)行緩存。
# workspace-mvn-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mvn-repo-pvc
spec:
resources:
requests:
storage: 5Gi
volumeMode: Filesystem
storageClassName: nfs-storage # 使用 StorageClass 自動(dòng)生成 PV
accessModes:
- ReadWriteOnce
這里我們使用了一個(gè)名為 nfs-storage 的 StorageClass,這樣就可以自動(dòng)生成一個(gè)對(duì)應(yīng)的 PV 進(jìn)行綁定,如果你沒(méi)有需要自行創(chuàng)建一個(gè)對(duì)應(yīng)的靜態(tài) PV。
現(xiàn)在我們就可以創(chuàng)建一個(gè)使用上述 PVC 作為流水線(xiàn)工作區(qū)的 PipelineRun 來(lái)執(zhí)行流水線(xiàn)了:
# 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
請(qǐng)注意 PVC 和為緩存 maven 依賴(lài)項(xiàng)而聲明的工作區(qū)之間的映射,mvn-repo-pvc 被傳遞到流水線(xiàn)和相應(yīng)的任務(wù)作為緩存文件和制品的共享卷。
第一次流水線(xiàn)運(yùn)行將需要一些時(shí)間來(lái)下載依賴(lài)項(xiàng)執(zhí)行任務(wù),直接創(chuàng)建上面聲明的幾個(gè)資源對(duì)象,觀察 PipelineRun 的執(zhí)行過(guò)程:
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
當(dāng)?shù)谝淮螆?zhí)行流水線(xiàn)的時(shí)候會(huì)在執(zhí)行 mvn 命令的時(shí)候消耗大量的時(shí)間,因?yàn)樾枰螺d依賴(lài)包,我這里的環(huán)境差不多等了20分鐘左右:

然后在執(zhí)行后面的兩個(gè)任務(wù)的時(shí)候就非??炝?,因?yàn)榍懊嫒蝿?wù)執(zhí)行完成后會(huì)把依賴(lài)項(xiàng)存入到 Workspace 聲明的 PVC 中去,后面的任務(wù)直接使用了這個(gè) Workspace,我們可以重新執(zhí)行一次 PipelineRun,對(duì)比下前后兩次的時(shí)間,在我的環(huán)境中,執(zhí)行時(shí)間由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的執(zhí)行情況
$ 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
# 查看第二次執(zhí)行的詳細(xì)信息
$ 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
測(cè)試任務(wù)運(yùn)行沒(méi)有受到太大影響,因?yàn)樗褂昧舜蟛糠衷跇?gòu)建任務(wù)運(yùn)行中下載的依賴(lài)項(xiàng),即使在第一次流水線(xiàn)運(yùn)行中也是如此。

我們可以看到利用 Workspaces 功能可以對(duì)我們的流水線(xiàn)構(gòu)建進(jìn)行大幅度的優(yōu)化,特別是對(duì)于依賴(lài)包特別大的應(yīng)用,比如 Maven、NPM、Go Modules 等。
