kubernetes原生pipeline的示例分析,相信很多沒有經(jīng)驗的人對此束手無策,為此本文總結了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。
創(chuàng)新互聯(lián)成立于2013年,是專業(yè)互聯(lián)網(wǎng)技術服務公司,擁有項目成都網(wǎng)站建設、成都網(wǎng)站設計網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元雁江做網(wǎng)站,已為上家服務,為雁江各地企業(yè)和個人服務,聯(lián)系電話:13518219792
Tekton Pipeline,是一個k8s native的pipeline, 任務跑在pod中,通過自定義CRD去管理任務與工作流等等,我看完tekton之后感覺是功能很強大,但是有點過度設計了,沒有drone的簡約大方靈活之感。 |
Task
Tekton Pipelines的主要目標是單獨運行您的任務或作為管道的一部分運行。每個任務都在Kubernetes集群上作為Pod運行,每個步驟都作為自己的容器。這點深得drone思想精髓,其實drone也有計劃將kubernetes作為任務執(zhí)行引擎,只是沒有下文了。
A Task定義了需要執(zhí)行的工作,例如以下是一個簡單的任務:
apiVersion: tekton.dev/v1alpha1 kind: Task metadata: name: echo-hello-world spec: steps: - name: echo image: ubuntu command: - echo args: - "hello world"
這steps是一系列由任務順序執(zhí)行的 命令 。這個steps內(nèi)的配置幾乎與drone如出一轍,Task定義好并沒有被執(zhí)行,創(chuàng)建TaskRun時才會執(zhí)行。這是合理的,相當于是一個觸發(fā)
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
狀態(tài)Succeeded = True顯示任務已成功運行。
任務輸入和輸出
在更常見的場景中,任務需要多個步驟來處理輸入和輸出資源。例如,Task可以從GitHub存儲庫獲取源代碼并從中構建Docker鏡像。
PipelinesResources用于定義任務的輸入(如代碼)與輸出(如Docker鏡像)。有一些系統(tǒng)定義的資源類型可供使用,以下是通常需要的兩個資源示例。
該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存儲庫,輸出是從該源生成的圖像。任務 命令 的參數(shù)支持模板化,因此任務的定義是常量,參數(shù)的值可以在運行時更改。
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 # 這些參數(shù)都是可以自定義的 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就是上面定義的參數(shù) - --destination=${outputs.resources.builtImage.url} - --context=${inputs.params.pathToContext}
TaskRun將輸入和輸出綁定到已定義的PipelineResources值,除了執(zhí)行任務步驟外,還將值設置為用于模板化的參數(shù)。
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: # 執(zhí)行時把參數(shù)傳給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應當不限制死必須叫這兩個名字,只要是能支持參數(shù)就好。比如定義一個叫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
類型的狀態(tài)Succeeded = True顯示Task已成功運行,您還可以驗證Docker鏡像是否生成。
Pipeline
Pipeline定義要按順序執(zhí)行的任務列表,同時還通過使用該from字段指示是否應將任何輸出用作后續(xù)任務的輸入,并指示執(zhí)行的順序(使用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 # 編譯與打鏡像任務,上面已經(jīng)介紹過 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 # 比如這個鏡像,就是上個任務產(chǎn)生的 resource: web-image from: # from就如同管道一樣,把上個任務的輸出作為這個任務的輸入 - build-skaffold-web params: # 留意這些參數(shù)都是傳給Task模板的,覆蓋inputs里的參數(shù) - 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 # 第二步執(zhí)行kubectl image: lachlanevenson/k8s-kubectl command: ["kubectl"] args: - "apply" - "-f" - "${inputs.params.path}" # 這就是yaml文件的位置
要運行Pipeline,請創(chuàng)建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
執(zhí)行與查看pipeline
kubectl apply -f < name-of-file.yaml > kubectl獲取pipelineruns / tutorial-pipeline-run-1 -o yaml
總結
初學者會覺得有點繞,但是這種設計也是為了解耦合,我個人覺得優(yōu)劣如下:
優(yōu)勢
可以把k8s集群作為任務執(zhí)行引擎,這樣可以更好的利用資源,比如把線上夜間閑置資源用來跑任務,構建鏡像 離線分析 甚至機器學習。解耦做的比較好,任務模板可以拿來復用,而不需要大家都去重復定義,輸入輸出理念,一個任務的輸入作為另個任務的輸出不錯。
劣勢
有點過度設計,一些簡單的場景可能覺得配置起來有點繞了,輸入輸出依賴分布式系統(tǒng),對比drone一個pipeline中的容器是共享了一個數(shù)據(jù)卷的,這樣上個任務產(chǎn)生的文件很方便的給下個任務用,而基于集群的任務就可能得依賴git docker鏡像倉庫等做輸入輸出,有點麻煩,好的解決辦法是利用k8s分布試存儲給pipeline設置一個共享卷,方便任務間傳輸數(shù)據(jù);總體來說路子是對的而且還是有很多場景可以用的。
看完上述內(nèi)容,你們掌握kubernetes原生pipeline的示例分析的方法了嗎?如果還想學到更多技能或想了解更多相關內(nèi)容,歡迎關注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!