本文是我對Tekton的實現原理和背後技術邏輯的理解,以及在實踐過程中的一些總結。
簡介
Tekton 是一個基於 Kubernetes 的雲原生 CI/CD 開源(https://cd.foundation/)框架,基於 CRD(Custom Resource Definitions)方式實現,目前阿里、google、ibm 都在使用這個框架。
Tekton 定義了 Task、TaskRun、Pipeline、PipelineRun、PipelineResource 五類核心物件,透過對task、pipeline資源的編排我可以實現CI/CD。
除此之外Tekton還提供了:
- Tekton CLI 命令列工具可以更加快捷和針對性的現實tekton的執行狀態;
- Tekton Dashboard 可以圖形化介面的形式檢視執行狀態和結果;
- Tekton Trigger 提供了web api可以進行基本的觸發。
實現原理
Tekton 是基於CRD(Custom Resource Definitions)實現的,是標準的k8s擴充套件機制。Tekton 有四個基本的物件 Task、TaskRun、Pipeline、PipelineRun ,下圖是Tekton Dashboard 的介面,可以直觀的感受一下 這幾個物件。
如下圖所示, Pipeline 例項化為 Pipeline Run,Pipeline Run 建立並管理 Pod,一個 Pod 對應 Task 的例項 Task Run,Task Run / Task 中的 step 對應 Pod 中的 container,除此Pod通常會共享一個 PersistentVolume 支援的臨時檔案系統。
- Task 構建任務,是 Tekton 中不可分割的最小單位,正如同 Pod 在 Kubernetes 中的概念一樣。在 Task 中,可以有多個 Step,每個 Step 由一個 Container 來執行。
- Pipeline 由一個或多個 Task 組成。在 Pipeline 中,使用者可以定義這些 Task 的執行順序以及依賴關係來組成 DAG(有向無環圖)。
- Pipeline Run 是 Pipeline 的實際執行產物,當使用者定義好 Pipeline 後,可以透過建立 PipelineRun 的方式來執行流水線,並生成一條流水線記錄。
- Task Run PipelineRun 被建立出來後,會對應 Pipeline 裡面的 Task 建立各自的 TaskRun。一個 TaskRun 控制一個 Pod,Task 中的 Step 對應 Pod 中的 Container。當然,TaskRun 也可以單獨被建立。
CLI
Tekton Trigger
可以透過http介面的形式觸發Tekton流水線,包括三個主要元件,設定有點繁瑣,如果是所有人都需要配置會瘋掉。
- EventListner 監聽http請求的發起
- TriggerTemplate 配置Pipeline Run
- TriggerBinding 從http的request body中獲取資料傳遞給Pipeline Run
Tekton Dashboard
後端的介面會轉發到k8s的api
參考:https://tekton.dev/docs/dashboard/install/
原始碼:https://github.com/tektoncd/dashboard
實踐
以下yaml檔案均儲存於 https://github.com/smallidea/tekton-test
部署
以 linux / mac 為例
# docker & docker-compose install
curl -o- https://smartidedl.blob.core.chinacloudapi.cn/docker/linux/docker-install.sh | bash
# Kubectl install
curl -LO https://smartidedl.blob.core.chinacloudapi.cn/kubectl/v1.23.0/bin/linux/amd64/kubectl
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
# minikube install,參考 https://minikube.sigs.k8s.io/docs/start/
curl -LO https://smartidedl.blob.core.chinacloudapi.cn/minikube/v1.24.0/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikub
minikube delete
minikube start --image-mirror-country=cn --driver=docker --cpus=2 --memory=2048mb
# Tekton Pipeline & Dashboard install
kubectl apply -f https://gitee.com/chileeb/SmartIDE/raw/main/server/deployment/online/pipeline/v0.32.0/smartide-tekton-release.yaml
kubectl apply -f https://gitee.com/chileeb/SmartIDE/raw/main/server/deployment/online/dashboard/v0.32.0/smartide-tekton-dashboard-release.yaml
# Tekton Trigger install (選裝)
kubectl apply -f https://gitee.com/chileeb/SmartIDE/raw/main/server/deployment/online/trigger/v0.18.0/smartide-release.yaml
kubectl apply -f https://gitee.com/chileeb/SmartIDE/raw/main/server/deployment/online/trigger/v0.18.0/smartide-interceptor.yaml
# Tekton CLI, https://tekton.dev/docs/cli/
brew install tektoncd-cli
參考:SmartIDE (https://smartide.cn/zh/)的私有化部署指令碼
國內網路一鍵安裝
curl -o- https://gitee.com/chileeb/SmartIDE/raw/main/server/deployment/online/deployment_cn.sh | bash
國際網路一鍵安裝
curl -o- https://gitee.com/chileeb/SmartIDE/raw/main/server/deployment/online/deployment.sh | bash
示例
1. yaml
task.yaml
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: tekton-task-test
spec:
description: >-
This Task is test task to test Tekton.
params:
- name: USERNAME
description: your name
type: string
default:
steps:
- name: step-01
image: ubuntu
script: |
#!/bin/bash
echo "Hello World!"
- name: step-02
image: ubuntu
script: |
#!/bin/bash
echo "I'm $(params.USERNAME)"
pipeline.yaml
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: tekton-pipeline-test
spec:
params:
- name: FIRST_NAME
description: Your first name
type: string
default: "jason"
- name: LAST_NAME
description: Your last name
type: string
default: "chen"
tasks:
- name: task-001
taskRef:
name: tekton-task-test
params:
- name: USERNAME
value: $(params.FIRST_NAME)
- name: task-002
runAfter:
- task-001
taskRef:
name: tekton-task-test
params:
- name: USERNAME
value: $(params.LAST_NAME)
pipeline_run.yaml
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: tekton-pipeline-test-run-003
spec:
pipelineRef:
name: tekton-pipeline-test
params:
- name: FIRST_NAME
value: "Jason"
- name: LAST_NAME
value: "Chen"
2. Pipeline Run
# apply
kubectl apply -f task.yaml
kubectl apply -f pipeline.yaml
kubectl apply -f pipeline-run.yaml
# 透過 Tekton CLI 檢視執行結果
tkn pipelinerun logs tekton-pipeline-test-run-003 -f -n default
透過 Dashboard 檢視執行結果
3. Tekton Trigger
trigger.yaml
apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerBinding
metadata:
name: pipeline-binding-test
spec:
params:
- name: FIRST_NAME
value: $(body.FIRST_NAME)
- name: LAST_NAME
value: $(body.LAST_NAME)
---
apiVersion: triggers.tekton.dev/v1beta1
kind: EventListener
metadata:
name: trigger-listener-test
spec:
serviceAccountName: tekton-triggers-test-sa
triggers:
- name: trigger-test
bindings:
- ref: pipeline-binding-test
template:
ref: tekton-pipeline-test
---
apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerTemplate
metadata:
name: pipeline-template-test
spec:
params:
- name: FIRST_NAME
default:
- name: LAST_NAME
default:
resourcetemplates:
- apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
generateName: tekton-pipeline-test-run-
spec:
pipelineRef:
name: tekton-pipeline-test
params:
- name: FIRST_NAME
value: $(tt.params.FIRST_NAME)
- name: LAST_NAME
value: $(tt.params.LAST_NAME)
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: tekton-triggers-test-sa
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: tekton-triggers-test-eventlistener-binding
subjects:
- kind: ServiceAccount
name: tekton-triggers-test-sa
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: tekton-triggers-eventlistener-roles
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: tekton-triggers-test-eventlistener-clusterbinding
subjects:
- kind: ServiceAccount
name: tekton-triggers-test-sa
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: tekton-triggers-eventlistener-clusterroles
# apply
kubectl apply -f trigger.yaml
# 埠儘量不要使用常用的,避免衝突;如果是多個pipeline的trigger,記得埠保持唯一。
# Tekton Listener 對應service的名稱,一般是 el-<tekton listener name>
kubectl port-forward service/el-trigger-listener-test 9091:8080 --address 0.0.0.0 &
# 使用curl命令觸發
curl -v \
-H 'content-Type: application/json' \
-d '{"FIRST_NAME": "Tekton", "LAST_NAME": "CD"}' \
http://localhost:9091