写点什么

Tekton 的工作原理

用户头像
张晓辉
关注
发布于: 2020 年 05 月 23 日
Tekton 的工作原理

这篇文章是基于 Tekton Pipeline 的最新版本v0.12.1版本。



快速入门请参考:云原生 CICD: Tekton Pipeline 实战实战是基于版本 v0.10.x

Pipeline CRD 与核心资源的关系



$ k api-resources --api-group=tekton.dev
NAME SHORTNAMES APIGROUP NAMESPACED KIND
clustertasks tekton.dev false ClusterTask
conditions tekton.dev true Condition
pipelineresources tekton.dev true PipelineResource
pipelineruns pr,prs tekton.dev true PipelineRun
pipelines tekton.dev true Pipeline
taskruns tr,trs tekton.dev true TaskRun
tasks tekton.dev true Task



Tekton Pipelines提供了上面的CRD,其中部分CRD与k8s core中资源相对应



  • Task => Pod

  • Task.Step => Container





工作原理



(图片来自)



Tekton Pipeline 是基于 Knative 的实现,pod tekton-pipelines-controller 中有两个 Knative Controller的实现:PipelineRun 和 TaskRun。





Task的执行顺序



PipelineRun Controller 的 #reconcile()方法,监控到有PipelineRun被创建。然后从PipelineSpec的 tasks 列表,构建出一个图(graph),用于描述Pipeline中 Task 间的依赖关系。依赖关系是通过runAfterfrom,进而控制Task的执行顺序。与此同时,准备PipelineRun中定义的PipelineResources



// Node represents a Task in a pipeline.
type Node struct {
// Task represent the PipelineTask in Pipeline
Task Task
// Prev represent all the Previous task Nodes for the current Task
Prev []*Node
// Next represent all the Next task Nodes for the current Task
Next []*Node
}
// Graph represents the Pipeline Graph
type Graph struct {
//Nodes represent map of PipelineTask name to Node in Pipeline Graph
Nodes map[string]*Node
}
func Build(tasks Tasks) (*Graph, error) {
...
}



PipelineRun中定义的参数(parameters)也会注入到PipelineSpec中:



pipelineSpec = resources.ApplyParameters(pipelineSpec, pr)



接下来就是调用dag#GetSchedulable()方法,获取未完成(通过Task状态判断)的 Task 列表;



func GetSchedulable(g *Graph, doneTasks ...string) (map[string]struct{}, error) {
...
}



为 Task A 创建TaskRun,假如Task配置了Condition。会先为 condition创建一个TaskRun,只有在 condition 的TaskRun运行成功,才会运行 A 的TaskRun;否则就跳过。



Step的执行顺序



这一部分篇幅较长,之前的文章 控制 Pod 内容器的启动顺序 中提到过。



这里补充一下Kubernetes Downward API的使用,Kubernetes Downward API的引入,控制着 Task 的第一个 Step 在合适执行。



TaskRun Controller 在 reconciling 的过程中,在相应的 Pod 状态变为Running时,会将tekton.dev/ready=READY写入到 Pod 的 annotation 中,来通知第一个Step的执行。



Pod的部分内容:

spec:
containers:
- args:
- -wait_file
- /tekton/downward/ready
- -wait_file_content
- -post_file
- /tekton/tools/0
- -termination_path
- /tekton/termination
- -entrypoint
- /ko-app/git-init
- --
- -url
- ssh://git@gitlab.nip.io:8022/addozhang/logan-pulse.git
- -revision
- develop
- -path
- /workspace/git-source
command:
- /tekton/tools/entrypoint
volumeMounts:
- mountPath: /tekton/downward
name: tekton-internal-downward
volumes:
- downwardAPI:
defaultMode: 420
items:
- fieldRef:
apiVersion: v1
fieldPath: metadata.annotations['tekton.dev/ready']
path: ready
name: tekton-internal-downward

自动运行的容器



这些自动运行的容器作为 pod 的initContainer会在 step 容器运行之前运行



  • credential-initializer

  • working-dir-initializer

  • place-scripts

  • place-tools



Task/Step间的数据传递



针对不同的数据,有多种不同的选择。比如WorkspaceResultPipelineResource。对于由于Task的执行是通过Pod来完成的,而Pod会调度到不同的节点上。因此Task间的数据传递,需要用到持久化的卷。



Step作为Pod中的容器来运行,



Workspace



工作区,可以理解为一个挂在到容器上的卷,用于文件的传递。



`persistentVolumeClaim`



引用已存在persistentVolumeClaim卷(volume)。这种工作空间,可多次使用,需要先进行创建。比如 Java 项目的 maven,编译需要本地依赖库,这样可以节省每次编译都要下载依赖包的成本。



workspaces:
- name: m2
persistentVolumeClaim:
claimName: m2-pv-claim



apiVersion: v1
kind: PersistentVolume
metadata:
name: m2-pv
labels:
type: local
spec:
storageClassName: manual
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
hostPath:
path: "/data/.m2"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: m2-pv-claim
spec:
storageClassName: manual
# volumeName: m2-pv
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi



`volumeClaimTemplate`



为每个PipelineRun或者TaskRun创建PersistentVolumeClaim卷(volume)的模板。比如一次构建需要从 git 仓库克隆代码,而针对不同的流水线代码仓库是不同的。这里就会用到volumeClaimTemplate,为每次构建创建一个PersistentVolumeClaim卷。(从0.12.0开始)



生命周期同PipelineRun或者TaskRun,运行之后释放。



workspaces:
- name: git-source
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi



相较于persistantVolumeClain类型的workspace,volumeClaimTemplate不需要在每次在PipelineRun完成后清理工作区;并发情况下可能会出现问题。



`emptyDir`



引用emptyDir卷,跟随Task生命周期的临时目录。适合在TaskStep间共享数据,无法在多个Task间共享。



workspaces:
- name: temp
emptyDir: {}



`configMap`



引用一个configMap卷,将configMap卷作为工作区,有如下限制:



使用场景,比如使用maven编译Java项目,配置文件settings.xml可以使用configMap作为工作区



workspaces:
- name: maven-settings
configmap:
name: maven-settings



`secret`



用于引用secret卷,同configMap工作区一样,也有限制:



Result



results字段可以用来配置多个文件用来存储Tasks的执行结果,这些文件保存在/tekton/results目录中。



Pipeline中,可以通过tasks.[task-nanme].results.[result-name]注入到其他Task的参数中。



apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: print-date
annotations:
description: |
A simple task that prints the date
spec:
results:
- name: current-date-unix-timestamp
description: The current date in unix timestamp format
- name: current-date-human-readable
description: The current date in human readable format
steps:
- name: print-date-unix-timestamp
image: bash:latest
script: |
#!/usr/bin/env bash
date +%s | tee $(results.current-date-unix-timestamp.path)
- name: print-date-humman-readable
image: bash:latest
script: |
#!/usr/bin/env bash
date | tee $(results.current-date-human-readable.path)
---
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: pass-date
spec:
pipelineSpec:
tasks:
- name: print-date
taskRef:
name: print-date
- name: read-date
runAfter: #配置执行顺序
- print-date
taskSpec:
params:
- name: current-date-unix-timestamp
type: string
- name: current-date-human-readable
type: string
steps:
- name: read
image: busybox
script: |
echo $(params.current-date-unix-timestamp)
echo $(params.current-date-human-readable)
params:
- name: current-date-unix-timestamp
value: $(tasks.print-date.results.current-date-unix-timestamp) # 注入参数
- name: current-date-human-readable
value: $(tasks.print-date.results.current-date-human-readable) # 注入参数



执行结果:



┌──────Logs(tekton-pipelines/pass-date-read-date-rhlf2-pod-9b2sk)[all] ────────── │
│ place-scripts stream closed ││ step-read 1590242170 │
│ step-read Sat May 23 13:56:10 UTC 2020 ││ step-read + echo 1590242170 │
│ step-read + echo Sat May 23 13:56:10 UTC 2020 │
│ place-tools stream closed │
│ step-read stream closed │



PipelineResource



PipelineResource在最后提,因为目前只是alpha版本,何时会进入beta或者弃用目前还是未知数。有兴趣的可以看下这里:Why Aren’t PipelineResources in Beta?



简单来说,PipelineResource可以通过其他的方式实现,而其本身也存在弊端:比如实现不透明,debug有难度;功能不够强;降低了Task的重用性等。



比如git类型的PipelineResource,可以通过workspacegit-clone Task来实现;存储类型的,也可以通过workspace来实现。



这也就是为什么上面介绍workspace的篇幅比较大。个人也偏向于使用workspace,灵活度高;使用workspace的Task重用性强。



参考








文章同步发送到公众号:云编码 (微信号:sevenfeet)。





发布于: 2020 年 05 月 23 日阅读数: 95
用户头像

张晓辉

关注

大胆尝试,小心求证 2018.04.09 加入

胡说八道

评论

发布
暂无评论
Tekton 的工作原理