Tekton入門
什麼是流水線
流水線是把一個重複的過程分解為若幹個子過程,使每個子過程與其他子過程并行進行的技術,也叫 Pipeline。以“建構鏡像更新應用”為例:
當一次代碼變更之後,jenkins都需要拉取最新的代碼,進行代碼編譯,建構鏡像,推送鏡像到鏡像倉庫,最後更新k8s資源對象。而且每次代碼變更,此過程都是不變的。是以使用流水線工具可以極大的提升這一過程的效率,隻需要進行簡單的配置便可以輕松的完成重複性的工作,這樣的過程也被稱之為 CI。
什麼是Tekton
Tekton 是一個基于 Kubernetes 的雲原生 CI/CD 開源架構,屬于 CD 基金會的項目之一。Tekton 通過定義 CRD 的方式,讓使用者以靈活的自定義流水線以滿足自身 CI/CD 需求。
Tekton使用人員
- 為組織中的開發人員建構 CI/CD 系統的平台工程師。
- 使用這些 CI/CD 系統完成工作的開發人員。
Tekton優點
- 可定制Tekton 實體是完全可定制的,具有高度的靈活性。平台工程師可以定義高度詳細的建構塊目錄,供開發人員在各種場景中使用。
- 可重複使用的Tekton 實體是完全可移植的,是以一旦定義,組織内的任何人都可以使用給定的管道并重用其建構塊。這使開發人員無需“重新發明輪子”即可快速建構複雜的管道。
- 可擴充Tekton Catalog 是社群驅動的 Tekton 建構塊存儲庫。您可以使用 Tekton Catalog 中的預制元件快速建立新管道并擴充現有管道。
- 标準化Tekton 在您的 Kubernetes 叢集上作為擴充安裝和運作,并使用完善的 Kubernetes 資源模型。Tekton 工作負載在 Kubernetes 容器内執行。
Tekton組成
Tekton 由以下元件組成:
- **Tekton Pipelines是Tekton**的基礎。它定義了一組 Kubernetes自定義資源 ,用作建構塊,您可以從中組裝 CI/CD 管道。
- **Tekton Triggers**允許您根據事件執行個體化管道。例如,您可以在每次将 PR 合并到 GitHub 存儲庫時觸發管道的執行個體化和執行。您還可以建構啟動特定 Tekton 觸發器的使用者界面。
- **Tekton CLI**提供了一個名為 的指令行界面
,它建構在 Kubernetes CLI 之上,允許您與 Tekton 進行互動。tkn
- **Tekton Dashboard**是 Tekton Pipelines 的基于 Web 的圖形界面,可顯示有關管道執行的資訊。它目前正在進行中。
- **Tekton Catalog**是一個由社群貢獻的高品質 Tekton 建構塊的存儲庫 -
、Tasks
,等等 - 可以在您自己的管道中使用。Pipelines
- **Tekton Hub**是一個基于 Web 的圖形界面,用于通路 Tekton Catalog。
- **Tekton Operator**是一種 Kubernetes Operator 模式 ,允許您在 Kubernetes 叢集上安裝、更新和删除 Tekton 項目。
Tekton Pipelines基本概念
- Tekton Pipelines最基本的四個概念:Task、TaskRun、Pipeline、PipelineRun。
- Task: Task 為建構任務,是 Tekton 中不可分割的最小機關,正如同 Pod 在 Kubernetes 中的概念一樣。在 Task 中,可以有多個 Step,每個 Step 由一個 Container 按照順序來執行。
- Pipeline: Pipeline 由一個或多個 Task 組成。在 Pipeline 中,使用者可以定義這些 Task 的執行順序以及依賴關系來組成 DAG(有向無環圖)。
- PipelineRun: PipelineRun 是 Pipeline 的實際執行産物,當使用者定義好 Pipeline 後,可以通過建立 PipelineRun 的方式來執行流水線,并生成一條流水線記錄。
- TaskRun: PipelineRun 被建立出來後,會對應 Pipeline 裡面的 Task 建立各自的 TaskRun。一個 TaskRun 控制一個 Pod,Task 中的 Step 對應 Pod 中的 Container。當然,TaskRun 也可以單獨被建立。
- PipelineResource概念 PipelineResource 代表着一系列的資源,主要承擔作為 Task 的輸入或者輸出的作用。它有以下幾種類型:
- git:代表一個 git 倉庫,包含了需要被建構的源代碼。将 git 資源作為 Task 的 Input,會自動 clone 此 git 倉庫。
- pullRequest:表示來自配置的 url(通常是一個 git 倉庫)的 pull request 事件。将 pull request 資源作為 Task 的 Input,将自動下載下傳 pull request 相關中繼資料的檔案,如 base/head commit、comments 以及 labels。
- image:代表鏡像倉庫中的鏡像,通常作為 Task 的 Output,用于生成鏡像。
- cluster:表示一個除了目前叢集外的 Kubernetes 叢集。可以使用 Cluster 資源在不同的叢集上部署應用。
- storage:表示 blob 存儲,它包含一個對象或目錄。将 Storage 資源作為 Task 的 Input 将自動下載下傳存儲内容,并允許 Task 執行操作。目前僅支援 GCS。
- cloud event:會在 TaskRun 執行完成後發送事件資訊(包含整個 TaskRun) 到指定的 URI 位址,在與第三方通信的時候十分有用。
Tekton Triggers基本概念
Tekton Triggers是一個基于事件的觸發器,它可以檢測到事件的發生,并能提取事件中的資訊,
TaskRuns
和
PipelineRuns
可以根據該資訊進行執行個體化和執行。
Tekton Triggers最基本的四個概念:TriggerTemplate、TriggerBinding、EventListener、Interceptor。
TriggerTemplate:指定要在檢測到事件時執行個體化和執行的資源,如
TaskRuns
和
PipelineRuns
。
TriggerBinding:指定要從事件資訊中提取的字段,并将字段資訊傳遞給
TriggerTemplate
,這樣字段就可以在
TaskRuns
和
PipelineRuns
中使用。
EventListener:在Kubernetes叢集啟動一個事件監聽服務、并暴露服務,将
TriggerTemplate
和
TriggerBinding
綁定。
Interceptor:事件攔截器,用于過濾事件,運作在
TriggerBinding
之前。
建構流水線
下邊以接收gitlab pr merged事件自動從gitlab拉取代碼、建構鏡像、推送鏡像到harbor倉庫、更新k8s叢集資源為例,示範tekton建構流水線。
定義PipelineResource
- git-input表示Task的輸入,type=git表示使用git倉庫類型,url表示gitlab的位址,revision表示分支。
apiVersion: tekton.dev/v1alpha1 kind: PipelineResource metadata: name: git-input namespace: test-tekton spec: type: git params: - name: url value: https://xxxx.git - name: revision value: dev
- image-output表示Task的輸出,type=image表示使用鏡像倉庫類型,url表示倉庫位址。
apiVersion: tekton.dev/v1alpha1 kind: PipelineResource metadata: name: image-output namespace: test-tekton spec: type: image params: - name: url value: xxxx/xxxx
配置認證資訊
由于使用了私有gitlab和鏡像倉庫,是以需要配置倉庫的認證資訊。
- git-basic-user-pass表示gitlab的認證資訊,
中annotations
開頭的key表示git類型的secret,value則是gitlab的位址,tekton.dev/git-tekton.dev/git-
表示認證類型,支援type
、kubernetes.io/basic-auth
。kubernetes.io/ssh-auth
apiVersion: v1 kind: Secret metadata: name: git-basic-user-pass namespace: test-tekton annotations: tekton.dev/git-0: https://xxxx.git type: kubernetes.io/basic-auth stringData: username: xxxx password: xxxx
- repo-basic-user-pass表示harbor的認證資訊,
中annotations
開頭的key表示docker倉庫類型的secret,value則是harbor的位址,tekton.dev/docker-
表示認證類型,支援type
、kubernetes.io/basic-auth
、kubernetes.io/dockercfg
。kubernetes.io/dockerconfigjson
apiVersion: v1 kind: Secret metadata: name: repo-basic-user-pass namespace: test-tekton annotations: tekton.dev/docker-0: xxxx type: kubernetes.io/basic-auth stringData: username: xxxx password: xxxx
- build-bot表示PipelineRun、TaskRun使用的ServiceAccount,build-bot綁定git-basic-user-pass、repo-basic-user-pass,這樣PipelineRun、TaskRun就能使用相應認證資訊。
由于部署應用時使用kubectl、triggers,是以build-bot需要叢集權限,這裡給了一個cluster-admin的權限。apiVersion: v1 kind: ServiceAccount metadata: name: build-bot namespace: test-tekton secrets: - name: git-basic-user-pass - name: repo-basic-user-pass
kubectl create clusterrolebinding build-bot-cluster-admin --clusterrole=cluster-admin --serviceaccount=test-tekton:build-bot
定義Task
- build-push表示建構、推送鏡像任務,
下表示表示定義變量并設定了預設值,params
表示引用某個變量,$()
類似于k8s中volume,用于存儲、共享資料,支援pvc、configmap、secret,本例由于需要在task之間共享部署的yaml,是以在pipelineRun中指定使用pvc作為存儲實作。workspaces
apiVersion: tekton.dev/v1beta1 kind: Task metadata: name: build-push namespace: test-tekton spec: workspaces: - name: ws resources: inputs: - name: docker-source type: git outputs: - name: build-image type: image params: - name: pathToDockerfile type: string default: $(resources.inputs.docker-source.path)/Dockerfile - name: pathToContext type: string default: $(resources.inputs.docker-source.path) - name: commitID type: string default: latest steps: - name: build-push image: registry.cn-hangzhou.aliyuncs.com/tanber_rp/gcr.io.kaniko-project.executor:v0.16.0 env: - name: "DOCKER_CONFIG" value: "tekton/home/.docker/" command: - /kaniko/executor args: - --dockerfile=$(params.pathToDockerfile) - --destination=$(resources.outputs.build-image.url):$(params.commitID) - --context=$(params.pathToContext) - name: store-image-url image: busybox script: | #這裡代碼目錄下deploy為部署檔案,可根據實際情況修改 cp -r $(resources.inputs.docker-source.path)/deploy/ $(workspaces.ws.path)/ url='$(resources.outputs.build-image.url):$(params.commitID)' url=${url//\//\\/} sed -i "s/image: tanber\/saml_idp:v1/image: ${url}/" $(workspaces.ws.path)/deploy/deploy.yaml
- deploy表示部署應用。
apiVersion: tekton.dev/v1beta1 kind: Task metadata: name: deploy namespace: test-tekton spec: workspaces: - name: ws params: - name: pathToDeploy type: string default: $(workspaces.ws.path)/deploy/ steps: - name: deploy image: docker.io/bitnami/kubectl:1.22.1 securityContext: runAsUser: 0 securityContext: runAsUser: 0 command: - kubectl args: - apply - -f - $(params.pathToDeploy)
定義Pipeline
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: pipeline
namespace: test-tekton
spec:
workspaces:
- name: ws
resources:
- name: docker-source
type: git
- name: build-image
type: image
params:
- name: mrState
type: string
- name: targetBranch
type: string
- name: commitID
type: string
- name: pathToDockerfile
type: string
default: $(resources.inputs.docker-source.path)/Dockerfile
- name: pathToContext
type: string
default: $(resources.inputs.docker-source.path)
- name: pathToDeploy
type: string
default: $(workspaces.ws.path)/deploy
tasks:
- name: build-push
when:
- input: "$(params.mrState)"
operator: in
values: ["merged"]
- input: "$(params.targetBranch)"
operator: in
values: ["dev"]
taskRef:
name: build-push
workspaces:
- name: ws
workspace: ws
params:
- name: commitID
value: $(params.commitID)
- name: pathToDockerfile
value: $(params.pathToDockerfile)
- name: pathToContext
value: $(params.pathToContext)
resources:
inputs:
- name: docker-source
resource: docker-source
outputs:
- name: build-image
resource: build-image
- name: deploy
when:
- input: "$(params.mrState)"
operator: in
values: ["merged"]
- input: "$(params.targetBranch)"
operator: in
values: ["dev"]
runAfter:
- build-push
taskRef:
name: deploy
workspaces:
- name: ws
workspace: ws
params:
- name: pathToDeploy
value: $(params.pathToDeploy)
定義TriggerTemplate
apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerTemplate
metadata:
name: triggertemplate
namespace: test-tekton
spec:
params:
- name: mrState
- name: targetBranch
- name: commitID
resourcetemplates:
- apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
generateName: pipelinerun-
namespace: test-tekton
spec:
serviceAccountName: build-bot
pipelineRef:
name: pipeline
workspaces:
- name: ws
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
params:
- name: pathToDockerfile
value: $(resources.inputs.docker-source.path)/Dockerfile
- name: pathToContext
value: $(resources.inputs.docker-source.path)
- name: pathToDeploy
value: $(workspaces.ws.path)/deploy
- name: mrState
value: $(tt.params.mrState)
- name: targetBranch
value: $(tt.params.targetBranch)
- name: commitID
value: $(tt.params.commitID)
resources:
- name: docker-source
resourceRef:
name: git-input
- name: build-image
resourceRef:
name: image-output
定義TriggerBinding
apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerBinding
metadata:
name: triggerbinding
namespace: test-tekton
spec:
params:
- name: mrState
value: $(body.object_attributes.state)
- name: targetBranch
value: $(body.object_attributes.target_branch)
- name: commitID
value: $(body.object_attributes.merge_commit_sha)
定義EventListener
apiVersion: triggers.tekton.dev/v1beta1
kind: EventListener
metadata:
name: eventlistener
namespace: test-tekton
spec:
serviceAccountName: build-bot
triggers:
- bindings:
- ref: triggerbinding
template:
ref: triggertemplate
gitlab設定
在Settings–>Webhooks下添加一個webhook,其中URL為建立Eventlistener時自動為你建立的svc,此svc預設是clusterIP,可自行建立一個NodePort類型svc。
測試
在gitlab上提一個pr到dev分支,并合并就會觸發流水線,檢視生成的流水線記錄。
$ kubectl -n test-tekton get pipelineruns.tekton.dev
NAME SUCCEEDED REASON STARTTIME COMPLETIONTIME
pipelinerun-mxlbw True Completed 8d 8d
pipelinerun-ngj6h True Succeeded 8d 7d23h
$ kubectl -n test-tekton get pod
NAME READY STATUS RESTARTS AGE
el-eventlistener-67464796fd-5k62t 1/1 Running 0 8d
pipelinerun-ngj6h-build-push-qjbcz-pod-vltrq 0/5 Completed 0 7d23h
pipelinerun-ngj6h-deploy-rxmd9-pod-hnzps 0/1 Completed 0 7d23h