雲原生CI/CD:Tekton/pipelin之pipeline概念篇
本節介紹下tekton中pipeline概念。作爲雲原生的CI/CD神器在之前介紹的task和taskrun之後,還有什麼強大的功能呢?
Pipeline
用於定義一系列完成特定構建或交付目標的任務。pipeline的運行是由事件觸發或從PipelineRun調用。pipeline和task的區別在於,task只能執行一個task,而pipeline中可以編排多個task,注意是編排,並不只是簡單運行。pipeline的spec.tasks定義了需要編排的task,是個數組,而這個數組中的task的順序並不一定是執行順序,pipeline中task的執行順序是可以指定的。下面講下pipeline的使用:
1.1 Declared resources
爲了使pipeline能與外界互動,可能需要PipelineResources,PipelineResources作爲輸入和輸出提供給Tasks。下面就是pipeline中使用pipelineResource:
spec:
resources:
- name: my-repo
type: git
- name: my-image
type: image
1.2 Workspaces
工作空間是一種爲執行中的管道及其任務提供可用的共享卷的方法。在pipeline中定義worksapce作爲共享卷傳遞個相關的task。在tekton中定義workspace的用途有以下幾點:
- 存儲輸入和/或輸出
- 在task之間共享數據
- secret認證的掛載點
- ConfigMap中保存的配置的掛載點
- 組織共享的常用工具的掛載點
- 高速緩存的構建工件可加快工作速度,簡而言之,用於緩存構建時的包,例如作爲Maven倉庫存儲
使用方式如下:
spec:
workspaces:
- name: pipeline-ws1 # workspace的名稱
tasks:
- name: use-ws-from-pipeline
taskRef:
name: gen-code # 使用的Task
workspaces:
- name: output
workspace: pipeline-ws1
- name: use-ws-again
taskRef:
name: commit # 使用的task
runAfter:
- use-ws-from-pipeline # 定義任務的執行順序,該task在use-ws-from-pipeline之後執行
workspaces:
- name: src
workspace: pipeline-ws1
1.3 使用task和pipelineresource
pipeline中使用已經定義好的task和pipelineResource:
spec:
tasks:
- name: build-the-image
taskRef:
name: build-push # 使用定義好的task
resources:
inputs:#輸入資源 代碼
- name: workspace
resource: my-repo
outputs:#輸出資源 鏡像
- name: image
resource: my-image
1.4 from
你可能需要將先前任務的輸出作爲輸入,舉個例子:
- name: build-app
taskRef:
name: build-push
resources:
outputs: #定義任務輸出
- name: image
resource: my-image
- name: deploy-app
taskRef:
name: deploy-kubectl
resources:
inputs:#定義任務輸入
- name: image
resource: my-image
from:
- build-app #任務輸入源,也意味着任務deploy-kubectl要在任務build-app之後執行
resource my-image將會從build-app的輸出作爲deploy-app的輸入,所以my-image必須是build-app任務的輸出結果,當然這也意味着build-app必須先於deloy-app運行完,無論它們在定義中出現的順序如何。
1.5 runAfter
有時,您需要具有按特定順序運行的pipeline task,但它們沒有明確的輸出來輸入依賴項(通過from表示)。在這種情況下,可以使用runAfter指示應在一個或多個先前的管道任務之後執行管道任務。
- name: test-app
taskRef:
name: make-test
resources:
inputs:
- name: workspace
resource: my-repo
- name: build-app
taskRef:
name: kaniko-build
runAfter:
- test-app #build-app任務在test-app任務之後執行
resources:
inputs:
- name: workspace
resource: my-repo
build-app任務會在test-app之後執行
1.6 retries
有時,你需要一項重試策略以應對可能會遇到的網絡錯誤、缺少依賴或者上傳問題等.
默認retries確省值爲0,不會重試,自定義重試策略如下:
tasks:
- name: build-the-image
retries: 1
taskRef:
name: build-push
build-the-image任務在第一次失敗後,馬上就會啓動第二個。當前設置只能重試1次。
1.7 conditions
有時你需要在某些條件爲true的情況下才去執行task,condition字段允許您列出對在任務運行之前運行的條件的一系列引用。如果所有條件都爲真,則運行任務。要是有一個條件不滿足,那任務就不會運行,同時任務的status標誌位會被置爲ConditionCheckFailed。注意正常來講,一個task不能運行,不會影響整個pipelinerun。pipeline中使用condition:
tasks:
- name: conditional-task
taskRef:
name: build-push
conditions:
- conditionRef: my-condition #使用已有condition
params:
- name: my-param
value: my-value
resources:
- name: workspace
resource: source-repo
關於如何定義condition,後面找個機會詳細找下。
1.8 Timeout
Pipeline Task的Timeout屬性允許爲PipelineRun的一部分TaskRun定義超時。如果TaskRun超過指定的時間,則TaskRun將失敗,並且與Pipeline關聯的PipelineRun也將失敗。Pipeline的Tasks沒有默認超時設置,因此在定義pipeline時必須使用pipeline task指定超時。帶有超時的管道任務示例如下所示:
spec:
tasks:
- name: build-the-image
taskRef:
name: build-push
Timeout: "0h1m30s"
timeout的完整例子:
apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
name: task-echo-message
spec:
inputs:
params:
- name: MESSAGE
type: string
default: "Hello World"
steps:
- name: echo
image: ubuntu
command:
- sleep 90s
args:
- "$(inputs.params.MESSAGE)"
---
apiVersion: tekton.dev/v1alpha1
kind: PipelineRun
metadata:
name: pipelinerun-timeout
spec:
# 1 hour and half timeout
timeout: 1h30m
pipelineSpec:
params:
- name: MORNING_GREETINGS
description: "morning greetings, default is Good Morning!"
type: string
default: "Good Morning!"
- name: NIGHT_GREETINGS
description: "Night greetings, default is Good Night!"
type: string
default: "Good Night!"
tasks:
# Task to display morning greetings
- name: echo-good-morning
taskRef:
name: task-echo-message
params:
- name: MESSAGE
value: $(params.MORNING_GREETINGS)
# Task to display night greetings
- name: echo-good-night
taskRef:
name: task-echo-message
params:
- name: MESSAGE
value: $(params.NIGHT_GREETINGS)
params:
- name: MORNING_GREETINGS
value: "Good Morning, Bob!"
- name: NIGHT_GREETINGS
value: "Good Night, Bob!"
注意:設置超時時間是很有必要的,不然task 的pod會一直運行不完,浪費k8s集羣資源,對於超時的任務確實應該kill掉。我之前構建Java項目時,使用的maven倉庫沒有配置阿里雲的源,拉包很慢,跑了一個小時,最後到了默認的超時時間才強制關掉任務。
1.8 Results
piple中可以使用task的運行結果作爲其他Task的輸入,即task可在執行過程中生成一些result,這些result可用作pipeline後續task中的參數值,此外Tekton將根據輸入參數來推斷tasks的執行順序,以確保生成result的task在那些消耗其結果的task之前運行。
通過變量替換將Task結果用作另一個Task參數的值:
params:
- name: foo
value: "$(tasks.previous-task-name.results.bar-result)"
"previous-task-name"產生的result被用於參數值。完整的例子如下:
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: sum-and-multiply-pipeline
spec:
params:
- name: a
type: string
default: "1"
- name: b
type: string
default: "1"
tasks:
- name: sum-inputs
taskRef:
name: sum
params:
- name: a
value: "$(params.a)"
- name: b
value: "$(params.b)"
- name: multiply-inputs
taskRef:
name: multiply
params:
- name: a
value: "$(params.a)"
- name: b
value: "$(params.b)"
- name: sum-and-multiply
taskRef:
name: sum
params:
- name: a
value: "$(tasks.multiply-inputs.results.product)$(tasks.sum-inputs.results.sum)" #該任務在multiply-inputs之後執行
- name: b
value: "$(tasks.multiply-inputs.results.product)$(tasks.sum-inputs.results.sum)"
---
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: sum
annotations:
description: |
A simple task that sums the two provided integers
spec:
params:
- name: a
type: string
default: "1"
description: The first integer
- name: b
type: string
default: "1"
description: The second integer
results:
- name: sum
description: The sum of the two provided integers
steps:
- name: sum
image: bash:latest
script: |
#!/usr/bin/env bash
echo -n $(( "$(params.a)" + "$(params.b)" )) | tee $(results.sum.path)
---
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: multiply
annotations:
description: |
A simple task that multiplies the two provided integers
spec:
params:
- name: a
type: string
default: "1"
description: The first integer
- name: b
type: string
default: "1"
description: The second integer
results:
- name: product
description: The product of the two provided integers
steps:
- name: product
image: bash:latest
script: |
#!/usr/bin/env bash
echo -n $(( "$(params.a)" * "$(params.b)" )) | tee $(results.product.path)
---
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
generateName: sum-and-multiply-pipeline-run-
spec:
pipelineRef:
name: sum-and-multiply-pipeline
params:
- name: a
value: "2"
- name: b
value: "10"
1.9 Ordering
前面有講過單獨使用from和runAfter這邊講下,這兩者聯合使用能到達指定順序執行任務:
- name: lint-repo
taskRef:
name: pylint
resources:
inputs:
- name: workspace
resource: my-repo
- name: test-app
taskRef:
name: make-test
resources:
inputs:
- name: workspace
resource: my-repo
- name: build-app
taskRef:
name: kaniko-build-app
runAfter:
- test-app #build-app在test-app之後執行
resources:
inputs:
- name: workspace
resource: my-repo
outputs:
- name: image
resource: my-app-image
- name: build-frontend
taskRef:
name: kaniko-build-frontend
runAfter:
- test-app #build-frontend在test-app之後執行
resources:
inputs:
- name: workspace
resource: my-repo
outputs:
- name: image
resource: my-frontend-image
- name: deploy-all
taskRef:
name: deploy-kubectl
resources:
inputs:
- name: my-app-image
resource: my-app-image
from:
- build-app # 在build-app之後執行
- name: my-frontend-image
resource: my-frontend-image
from:
- build-frontend #在build-frontend之後執行
執行過程圖:
| |
v v
test-app lint-repo
/ \
v v
build-app build-frontend
\ /
v v
deploy-all
總結
對於比較複雜的CI/CD任務或者需要指定執行順序時,可以選擇使用pipeline來運行,pipeline定義好了就創建,然後不用管了。在運行pipelineRun時指定必要的參數,每次運行構建任務時,只要運行pipelineRun就行,pipelineRun的使用我們下一次再講。總體來說,pipeline的功能相對於task來說還比較全,之後我會找一些場景進行演示。
歡迎關注“南君手記”公衆號,歡迎評論指正。技術之路,我們一起成長!