本文選自 《Knative 雲原生應用開發指南》 。
- Knative Build 對自己的一句話概述是:
A Kubernetes-native Build resource.
- Tekton 對自己的一句話概述是:
A K8s-native Pipeline resource. https://tekton.dev
可以看到兩者的定位非常相近,而且在功能上 Tekton 的設計更加的豐富、完整,這也是社群最終采用 Tekton 替代 Build 的原因。接下來我們就看一下 Tekton 的核心概念。
Tekton 極速入門
Tekton 主要由如下五個核心概念組成:
- Task
- TaskRun
- Pipeline
- PipelineRun
- PipelineResource
這五個概念每一個都是以 CRD 的形式提供服務的,下面分别簡述一下這五個概念的含義。
Task 就是一個任務執行模闆,之是以說 Task 是一個模闆是因為 Task 定義中可以包含變量,Task 在真正執行的時候需要給定變量的具體值。如果把 Tekton 的 Task 有點兒類似于定義一個函數,Task 通過 inputs.params 定義需要哪些入參,并且每一個入參還可以指定預設值。Task 的 steps 字段表示目前 Task 是有哪些步驟組成的,每一個步驟具體就是基于鏡像啟動一個 container 執行一些操作,container 的啟動參數可以通過 Task 的入參使用模闆文法進行配置。
apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
name: task-with-parameters
spec:
inputs:
params:
- name: flags
type: array
- name: someURL
type: string
steps:
- name: build
image: registry.cn-hangzhou.aliyuncs.com/knative-sample/alpine:3.9
command: ["sh", "-c"]
args: [ "echo ${inputs.params.flags} ; echo ${someURL}"]
Task 定義好以後是不能執行的,就像一個函數定義好以後需要調用才能執行一樣。是以需要再定義一個 TaskRun 去執行 Task。TaskRun 主要是負責設定 Task 需要的參數,并通過 taskRef 字段引用要執行的 Task。
apiVersion: tekton.dev/v1alpha1
kind: TaskRun
metadata:
name: run-with-parameters
spec:
taskRef:
name: task-with-parameters
inputs:
params:
- name: flags
value: "--set"
- name: someURL
value: "https://github.com/knative-sample"
一個 TaskRun 隻能執行一個 Task,當需要編排多個 Task 的時候就需要 Pipeline 出馬了。Pipeline 是一個編排 Task 的模闆。Pipeline 的 params 聲明了執行時需要的入參。 Pipeline 的 spec.tasks 定義了需要編排的 Task。Tasks 是一個數組,數組中的 task 并不是通過數組聲明的順序去執行的,而是通過 runAfter 來聲明 task 執行的順序。Tekton controller 在解析 CRD 的時候會解析 Task 的順序,然後根據 runAfter 設定生成的依次樹依次去執行。Pipeline 在編排 Task 的時候需要給每一個 Task 傳入必須的參數,這些參數的值可以來自 Pipeline 自身的 params 設定。
apiVersion: tekton.dev/v1alpha1
kind: Pipeline
metadata:
name: pipeline-with-parameters
spec:
params:
- name: context
type: string
description: Path to context
default: /some/where/or/other
tasks:
- name: task-1
taskRef:
name: build
params:
- name: pathToDockerFile
value: Dockerfile
- name: pathToContext
value: "${params.context}"
- name: task-2
taskRef:
name: build-push
runAfter:
- source-to-image
params:
- name: pathToDockerFile
value: Dockerfile
- name: pathToContext
value: "${params.context}"
和 Task 一樣 Pipeline 定義完成以後也是不能直接執行的,需要 PipelineRun 才能執行 Pipeline。PipelineRun 的主要作用是給 Pipeline 傳入必要的入參,并執行 Pipeline
apiVersion: tekton.dev/v1alpha1
kind: PipelineRun
metadata:
name: pipelinerun-with-parameters
spec:
pipelineRef:
name: pipeline-with-parameters
params:
- name: "context"
value: "/workspace/examples/microservices/leeroy-web"
前面已經介紹了 Tekton 的四個核心概念。現在我們已經知道怎麼定義 Task、執行 Task 以及編排 Task 了。但可能你還想在 Task 之間共享資源,這就是 PipelineResource 的作用。比如我們可以把 git 倉庫資訊放在 PipelineResource 中。這樣所有 Task 就可以共享這些資訊了。
piVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
name: wizzbang-git
namespace: default
spec:
type: git
params:
- name: url
value: https://github.com/wizzbangcorp/wizzbang.git
- name: revision
value: master
授權資訊
git 倉庫、鏡像倉庫這些都是需要鑒權才能使用的。是以還需要一種設定鑒權資訊的機制。Tekton 本身是 Kubernetes 原生的編排系統。是以可以直接使用 Kubernetes 的 ServiceAccount 機制實作鑒權。
執行個體如下:
- 定義一個儲存鏡像倉庫鑒權資訊的 secret
apiVersion: v1
kind: Secret
metadata:
name: ack-cr-push-secret
annotations:
tekton.dev/docker-0: https://registry.cn-hangzhou.aliyuncs.com
type: kubernetes.io/basic-auth
stringData:
username: <cleartext non-encoded>
password: <cleartext non-encoded>
- 定義 ServiceAccount ,并且使用上面的 secret
apiVersion: v1
kind: ServiceAccount
metadata:
name: pipeline-account
secrets:
- name: ack-cr-push-secret
- PipelineRun 中引用 ServiceAccount
apiVersion: tekton.dev/v1alpha1
kind: PipelineRun
metadata:
generateName: tekton-kn-sample-
spec:
pipelineRef:
name: build-and-deploy-pipeline
... ...
serviceAccount: pipeline-account
Hello World
https://github.com/knative-sample/tekton-knative/tree/b1.0這是一個完整的 Tekton 的 Helle World。下面我們一起體驗一下這個 Helle World。
在開始實戰之前你需要有一個 Kubernetes 叢集,并還需要安裝 Knative 和 Tekton,本文是基于 Tekton 最新的 0.8.0 版本寫的 Demo。下面我們開始體驗使用 Tekton 從源碼到建構再到部署的自動化過程。
clone 代碼
clone 代碼到本地,切換到 b1.0 分支, 到 tekton-cicd 目錄進行後面的操作。
git clone https://github.com/knative-sample/tekton-knative
git checkout b1.0
建立 PipelineResource
主要内容在
resources/picalc-git.yaml
檔案中。如下所示主要是把
儲存在 resource 中給其他資源使用。
apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
name: tekton-knative-git
spec:
type: git
params:
- name: revision
value: b1.0
- name: url
value: https://github.com/knative-sample/tekton-knative
建立 task
建立 task,這個例子中我們建立兩個 task:source-to-image 和 deploy-using-kubectl
- source-to-image
檔案中。此 task 的主要功能是把源代碼編譯成鏡像。tasks/source-to-image.yaml
主要是使用 kaniko 實作容器内編譯 Docker 鏡像的能力。此 Task 的參數主要是設定編譯上下文的一些資訊,比如:Dockerfile、ContextPath 以及目标鏡像 tag 等。
apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
name: source-to-image
spec:
inputs:
resources:
- name: git-source
type: git
params:
- name: pathToContext
description: The path to the build context, used by Kaniko - within the workspace
default: .
- name: pathToDockerFile
description: The path to the dockerfile to build (relative to the context)
default: Dockerfile
- name: imageUrl
description: Url of image repository
- name: imageTag
description: Tag to apply to the built image
default: "latest"
steps:
- name: build-and-push
image: registry.cn-hangzhou.aliyuncs.com/knative-sample/kaniko-project-executor:v0.10.0
command:
- /kaniko/executor
args:
- --dockerfile=$(inputs.params.pathToDockerFile)
- --destination=$(inputs.params.imageUrl):$(inputs.params.imageTag)
- --context=/workspace/git-source/$(inputs.params.pathToContext)
env:
- name: DOCKER_CONFIG
value: /builder/home/.docker
- deploy-using-kubectl
檔案中。tasks/deploy-using-kubectl.yaml
如下所示這個 Task 主要的作用是通過參數擷取到目标鏡像的資訊,然後執行一條 sed 指令把 Knative Service yaml 中的
__IMAGE__
替換成目标鏡像。再通過 kubectl 釋出到 Kubernetes 中。
apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
name: deploy-using-kubectl
spec:
inputs:
resources:
- name: git-source
type: git
params:
- name: pathToYamlFile
description: The path to the yaml file to deploy within the git source
- name: imageUrl
description: Url of image repository
- name: imageTag
description: Tag of the images to be used.
default: "latest"
steps:
- name: update-yaml
image: alpine
command: ["sed"]
args:
- "-i"
- "-e"
- "s;__IMAGE__;$(inputs.params.imageUrl):$(inputs.params.imageTag);g"
- "/workspace/git-source/$(inputs.params.pathToYamlFile)"
- name: run-kubectl
image: registry.cn-hangzhou.aliyuncs.com/knative-sample/kubectl:v0.5.0
command: ["kubectl"]
args:
- "apply"
- "-f"
- "/workspace/git-source/$(inputs.params.pathToYamlFile)"
定義 Pipeline
現在我們已經有兩個 Task 了,現在我們就用一個 PIpeline 來編排這兩個 Task:
apiVersion: tekton.dev/v1alpha1
kind: Pipeline
metadata:
name: build-and-deploy-pipeline
spec:
resources:
- name: git-source
type: git
params:
- name: pathToContext
description: The path to the build context, used by Kaniko - within the workspace
default: src
- name: pathToYamlFile
description: The path to the yaml file to deploy within the git source
- name: imageUrl
description: Url of image repository
- name: imageTag
description: Tag to apply to the built image
tasks:
- name: source-to-image
taskRef:
name: source-to-image
params:
- name: pathToContext
value: "$(params.pathToContext)"
- name: imageUrl
value: "$(params.imageUrl)"
- name: imageTag
value: "$(params.imageTag)"
resources:
inputs:
- name: git-source
resource: git-source
- name: deploy-to-cluster
taskRef:
name: deploy-using-kubectl
runAfter:
- source-to-image
params:
- name: pathToYamlFile
value: "$(params.pathToYamlFile)"
- name: imageUrl
value: "$(params.imageUrl)"
- name: imageTag
value: "$(params.imageTag)"
resources:
inputs:
- name: git-source
resource: git-source
鑒權資訊
如下所示,定義一個 Secret 和 ServiceAccount。并且給 ServiceAccount 綁定執行 Knative Service 的權限。
首先建立一個 Secret 儲存鏡像倉庫的鑒權資訊,如下所示:
- tekton.dev/docker-0 換成你要推送的鏡像倉庫的位址
- username 換成鏡像倉庫鑒權的使用者名
- password 環境鏡像倉庫鑒權的密碼
apiVersion: v1
kind: Secret
metadata:
name: ack-cr-push-secret
annotations:
tekton.dev/docker-0: https://registry.cn-hangzhou.aliyuncs.com
type: kubernetes.io/basic-auth
stringData:
username: <cleartext non-encoded>
password: <cleartext non-encoded>
下面這些資訊儲存到檔案中,然後使用 kubectl apply -f 指令送出到 Kubernetes
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: pipeline-account
secrets:
- name: ack-cr-push-secret
---
apiVersion: v1
kind: Secret
metadata:
name: kube-api-secret
annotations:
kubernetes.io/service-account.name: pipeline-account
type: kubernetes.io/service-account-token
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: pipeline-role
rules:
- apiGroups: ["serving.knative.dev"]
resources: ["services"]
verbs: ["get", "create", "update", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: pipeline-role-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: pipeline-role
subjects:
- kind: ServiceAccount
name: pipeline-account
定義 PIpelineRun
ServiceAccount 對應的鑒權資訊是通過和 PIpelineRun 綁定的方式執行的。參見
run/picalc-pipeline-run.yaml
檔案
apiVersion: tekton.dev/v1alpha1
kind: PipelineRun
metadata:
generateName: tekton-kn-sample-
spec:
pipelineRef:
name: build-and-deploy-pipeline
resources:
- name: git-source
resourceRef:
name: tekton-knative-git
params:
- name: pathToContext
value: "src"
- name: pathToYamlFile
value: "knative/helloworld-go.yaml"
- name: imageUrl
value: "registry.cn-hangzhou.aliyuncs.com/knative-sample/tekton-knative-helloworld"
- name: imageTag
value: "1.0"
serviceAccount: pipeline-account
運作 Tekton HelloWorld
準備 PIpeline 的資源
kubectl apply -f tasks/source-to-image.yaml -f tasks/deploy-using-kubectl.yaml -f resources/picalc-git.yaml -f image-secret.yaml -f pipeline-account.yaml -f pipeline/build-and-deploy-pipeline.yaml
執行 create 把 pipelieRun 送出到 Kubernetes 叢集。之是以這裡使用 create 而不是使用 apply 是因為 PIpelineRun 每次都會建立一個新的,kubectl 的 create 指令會基于 generateName 建立新的 PIpelineRun 資源。
kubectl create -f run/picalc-pipeline-run.yaml
檢視一下 pod 資訊可能是下面這樣:
└─# kubectl get pod
NAME READY STATUS RESTARTS AGE
tekton-kn-sample-45d84-deploy-to-cluster-wfrzx-pod-f093ef 0/3 Completed 0 8h
tekton-kn-sample-45d84-source-to-image-7zpqn-pod-c2d20c 0/2 Completed 0 8h
此時檢視 Knative service 的配置:
└─# kubectl get ksvc
NAME URL LATESTCREATED LATESTREADY READY REASON
tekton-helloworld-go http://tekton-helloworld-go.default.knative.kuberun.com tekton-helloworld-go-ntksb tekton-helloworld-go-ntksb True
通過浏覽器通路
http://tekton-helloworld-go.default.knative.kuberun.com可以看到 hello World
參考資料
“ 阿裡巴巴雲原生 關注微服務、Serverless、容器、Service Mesh 等技術領域、聚焦雲原生流行技術趨勢、雲原生大規模的落地實踐,做最懂雲原生開發者的技術圈。”