kubernetes原生pipeline的示例分析,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。
Tekton Pipeline,是一个k8s native的pipeline, 任务跑在pod中,通过自定义CRD去管理任务与工作流等等,我看完tekton之后感觉是功能很强大,但是有点过度设计了,没有drone的简约大方灵活之感。 |
Task
Tekton Pipelines的主要目标是单独运行您的任务或作为管道的一部分运行。每个任务都在Kubernetes集群上作为Pod运行,每个步骤都作为自己的容器。这点深得drone思想精髓,其实drone也有计划将kubernetes作为任务执行引擎,只是没有下文了。
A Task定义了需要执行的工作,例如以下是一个简单的任务:
apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
name: echo-hello-world
spec:
steps:
- name: echo
image: ubuntu
command:
- echo
args:
- "hello world"
这steps是一系列由任务顺序执行的 命令 。这个steps内的配置几乎与drone如出一辙,Task定义好并没有被执行,创建TaskRun时才会执行。这是合理的,相当于是一个触发
apiVersion: tekton.dev/v1alpha1
kind: TaskRun
metadata:
name: echo-hello-world-task-run
spec:
taskRef:
name: echo-hello-world
trigger:
type: manual
kubectl apply -f < name-of-file.yaml >
查看TaskRun kubectl get taskruns / echo-hello-world-task-run -o yaml
apiVersion: tekton.dev/v1alpha1
kind: TaskRun
metadata:
creationTimestamp: 2018-12-11T15:49:13Z
generation: 1
name: echo-hello-world-task-run
namespace: default
resourceVersion: "6706789"
selfLink: /apis/tekton.dev/v1alpha1/namespaces/default/taskruns/echo-hello-world-task-run
uid: 4e96e9c6-fd5c-11e8-9129-42010a8a0fdc
spec:
generation: 1
inputs: {}
outputs: {}
taskRef:
name: echo-hello-world
taskSpec: null
trigger:
type: manual
status:
conditions:
- lastTransitionTime: 2018-12-11T15:50:09Z
status: "True"
type: Succeeded
podName: echo-hello-world-task-run-pod-85ca51
startTime: 2018-12-11T15:49:39Z
steps:
- terminated:
containerID: docker://fcfe4a004...6729d6d2ad53faff41
exitCode: 0
finishedAt: 2018-12-11T15:50:01Z
reason: Completed
startedAt: 2018-12-11T15:50:01Z
- terminated:
containerID: docker://fe86fc5f7...eb429697b44ce4a5b
exitCode: 0
finishedAt: 2018-12-11T15:50:02Z
reason: Completed
startedAt: 2018-12-11T15:50:02Z
状态Succeeded = True显示任务已成功运行。
任务输入和输出
在更常见的场景中,任务需要多个步骤来处理输入和输出资源。例如,Task可以从GitHub存储库获取源代码并从中构建Docker镜像。
PipelinesResources用于定义任务的输入(如代码)与输出(如Docker镜像)。有一些系统定义的资源类型可供使用,以下是通常需要的两个资源示例。
该git资源可以是你要编译的代码:
apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
name: skaffold-git
spec:
type: git
params:
- name: revision
value: master
- name: url
value: https://github.com/GoogleContainerTools/skaffold
该image资源代表要被任务编译成的镜像:
apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
name: skaffold-image-leeroy-web
spec:
type: image
params:
- name: url
value: gcr.io//leeroy-web
以下是Task输入和输出。输入资源是GitHub存储库,输出是从该源生成的图像。任务 命令 的参数支持模板化,因此任务的定义是常量,参数的值可以在运行时更改。
apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
name: build-docker-image-from-git-source
spec:
inputs:
resources:
- name: docker-source
type: git
params:
- name: pathToDockerFile # 这些参数都是可以自定义的
description: The path to the dockerfile to build
default: /workspace/docker-source/Dockerfile
- name: pathToContext
description:
The build context used by Kaniko
(https://github.com/GoogleContainerTools/kaniko#kaniko-build-contexts)
default: /workspace/docker-source
outputs:
resources:
- name: builtImage
type: image
steps:
- name: build-and-push
image: gcr.io/kaniko-project/executor # 特定功能的镜像,可以用来docker build
command:
- /kaniko/executor
args:
- --dockerfile=${inputs.params.pathToDockerFile} # 这时原pathToDockerFile就是上面定义的参数
- --destination=${outputs.resources.builtImage.url}
- --context=${inputs.params.pathToContext}
TaskRun将输入和输出绑定到已定义的PipelineResources值,除了执行任务步骤外,还将值设置为用于模板化的参数。
apiVersion: tekton.dev/v1alpha1
kind: TaskRun
metadata:
name: build-docker-image-from-git-source-task-run
spec:
taskRef:
name: build-docker-image-from-git-source
trigger:
type: manual
inputs:
resources:
- name: docker-source
resourceRef:
name: skaffold-git
params: # 执行时把参数传给Task,这样就不需要重复定义task,只需要增加input output 和taskrun 就可以跑一个别的工程, 从解耦这个角度到说比drone更好,任务流程可以复用
- name: pathToDockerFile
value: Dockerfile
- name: pathToContext
value: /workspace/docker-source/examples/microservices/leeroy-web #configure: may change according to your source
outputs:
resources:
- name: builtImage
resourceRef:
name: skaffold-image-leeroy-web # 这也是上面指定的资源
PS: inputs outputs应当不限制死必须叫这两个名字,只要是能支持参数就好。比如定义一个叫build的资源去指定docker build的镜像:
apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
name: skaffold-image-leeroy-web
spec:
type: image
params:
- name: url
value: docker-in-docker:latest
Task 里:
apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
name: build-docker-image-from-git-source
spec:
build:
resources:
- name: build
type: image
params:
- name: build-image
default: docker-in-docker:latest
steps:
- name: build-and-push
image: ${build.params.build-image}
我是觉得需要能进行这样的扩展了, 仅是inputs outputs就狭义了
获取pipeline全部信息 kubectl get build-pipeline
NAME AGE taskruns/build-docker-image-from-git-source-task-run 30s NAME AGE pipelineresources/skaffold-git 6m pipelineresources/skaffold-image-leeroy-web 7m NAME AGE tasks/build-docker-image-from-git-source 7m
要查看TaskRun的输出,请使用以下命令:
kubectl get taskruns / build-docker-image-from-git-source-task-run -o yaml
apiVersion: tekton.dev/v1alpha1
kind: TaskRun
metadata:
creationTimestamp: 2018-12-11T18:14:29Z
generation: 1
name: build-docker-image-from-git-source-task-run
namespace: default
resourceVersion: "6733537"
selfLink: /apis/tekton.dev/v1alpha1/namespaces/default/taskruns/build-docker-image-from-git-source-task-run
uid: 99d297fd-fd70-11e8-9129-42010a8a0fdc
spec:
generation: 1
inputs:
params:
- name: pathToDockerFile
value: Dockerfile
- name: pathToContext
value: /workspace/git-source/examples/microservices/leeroy-web #configure: may change depending on your source
resources:
- name: git-source
paths: null
resourceRef:
name: skaffold-git
outputs:
resources:
- name: builtImage
paths: null
resourceRef:
name: skaffold-image-leeroy-web
taskRef:
name: build-docker-image-from-git-source
taskSpec: null
trigger:
type: manual
status:
conditions:
- lastTransitionTime: 2018-12-11T18:15:09Z
status: "True"
type: Succeeded
podName: build-docker-image-from-git-source-task-run-pod-24d414
startTime: 2018-12-11T18:14:29Z
steps:
- terminated:
containerID: docker://138ce30c722eed....c830c9d9005a0542
exitCode: 0
finishedAt: 2018-12-11T18:14:47Z
reason: Completed
startedAt: 2018-12-11T18:14:47Z
- terminated:
containerID: docker://4a75136c029fb1....4c94b348d4f67744
exitCode: 0
finishedAt: 2018-12-11T18:14:48Z
reason: Completed
startedAt: 2018-12-11T18:14:48Z
类型的状态Succeeded = True显示Task已成功运行,您还可以验证Docker镜像是否生成。
Pipeline
Pipeline定义要按顺序执行的任务列表,同时还通过使用该from字段指示是否应将任何输出用作后续任务的输入,并指示执行的顺序(使用runAfter和from字段)。您在任务中使用的相同模板也可以在管道中使用。
apiVersion: tekton.dev/v1alpha1
kind: Pipeline
metadata:
name: tutorial-pipeline
spec:
resources:
- name: source-repo
type: git
- name: web-image
type: image
tasks:
- name: build-skaffold-web # 编译与打镜像任务,上面已经介绍过
taskRef:
name: build-docker-image-from-git-source
params:
- name: pathToDockerFile
value: Dockerfile
- name: pathToContext
value: /workspace/examples/microservices/leeroy-web #configure: may change according to your source
resources:
inputs:
- name: workspace
resource: source-repo
outputs:
- name: image
resource: web-image
- name: deploy-web # 部署
taskRef:
name: deploy-using-kubectl # 这里引入了一个通过k8s部署的Task,我们在下文看它是什么
resources:
inputs: # 定义输入,这里的输入其实是上个任务的输出
- name: workspace
resource: source-repo
- name: image # 比如这个镜像,就是上个任务产生的
resource: web-image
from: # from就如同管道一样,把上个任务的输出作为这个任务的输入
- build-skaffold-web
params: # 留意这些参数都是传给Task模板的,覆盖inputs里的参数
- name: path
value: /workspace/examples/microservices/leeroy-web/kubernetes/deployment.yaml #configure: may change according to your source
- name: yqArg
value: "-d1"
- name: yamlPathToImage
value: "spec.template.spec.containers[0].image"
以上Pipeline是引用一个Task被叫的deploy-using-kubectl:
apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
name: deploy-using-kubectl
spec:
inputs:
resources:
- name: workspace
type: git
- name: image
type: image
params:
- name: path
description: Path to the manifest to apply
- name: yqArg
description:
Okay this is a hack, but I didn't feel right hard-coding `-d1` down
below
- name: yamlPathToImage
description:
The path to the image to replace in the yaml manifest (arg to yq)
steps:
- name: replace-image # 第一步替换镜像
image: mikefarah/yq # 特定功能的镜像,和drone同理,这里主要就是个模板渲染
command: ["yq"]
args:
- "w"
- "-i"
- "${inputs.params.yqArg}"
- "${inputs.params.path}"
- "${inputs.params.yamlPathToImage}"
- "${inputs.resources.image.url}"
- name: run-kubectl # 第二步执行kubectl
image: lachlanevenson/k8s-kubectl
command: ["kubectl"]
args:
- "apply"
- "-f"
- "${inputs.params.path}" # 这就是yaml文件的位置
要运行Pipeline,请创建PipelineRun如下:
apiVersion: tekton.dev/v1alpha1
kind: PipelineRun
metadata:
name: tutorial-pipeline-run-1
spec:
pipelineRef:
name: tutorial-pipeline
trigger:
type: manual
resources:
- name: source-repo
resourceRef:
name: skaffold-git
- name: web-image
resourceRef:
name: skaffold-image-leeroy-web
执行与查看pipeline
kubectl apply -f < name-of-file.yaml > kubectl获取pipelineruns / tutorial-pipeline-run-1 -o yaml
总结
初学者会觉得有点绕,但是这种设计也是为了解耦合,我个人觉得优劣如下:
优势
可以把k8s集群作为任务执行引擎,这样可以更好的利用资源,比如把线上夜间闲置资源用来跑任务,构建镜像 离线分析 甚至机器学习。解耦做的比较好,任务模板可以拿来复用,而不需要大家都去重复定义,输入输出理念,一个任务的输入作为另个任务的输出不错。
劣势
有点过度设计,一些简单的场景可能觉得配置起来有点绕了,输入输出依赖分布式系统,对比drone一个pipeline中的容器是共享了一个数据卷的,这样上个任务产生的文件很方便的给下个任务用,而基于集群的任务就可能得依赖git docker镜像仓库等做输入输出,有点麻烦,好的解决办法是利用k8s分布试存储给pipeline设置一个共享卷,方便任务间传输数据;总体来说路子是对的而且还是有很多场景可以用的。
看完上述内容,你们掌握kubernetes原生pipeline的示例分析的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注亿速云行业资讯频道,感谢各位的阅读!
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
原文链接:http://blog.itpub.net/31559985/viewspace-2644403/