天天看點

開源 CI/CD 建構架構 TekTon 的深入剖析

簡介

Tekton 是一個功能強大且靈活的Kubernetes 原生開源架構,用于建立持續內建和傳遞(CI/CD)系統。 關于Tekton, 網上可以搜到很多很多介紹文檔,本文主要闡述我對Tekton的實作原理和背後的技術邏輯的一點了解。

tekton.dev

Tekton定義了Task, TaskRun, Pipeline, PipelineRun, PipelineResource 五類核心對象。Tekton通過對Task和Pipeline的抽象,我們可以定義出任意組合的pipeline模闆來完成各種各樣的CICD任務。通過TaskRun,PipelineRun,PipelineResource可以将這些模闆套用到各個實際的項目中。

實作原理

高度抽象的結構化設計使得Tekton具有非常靈活的特性。那麼Tekton是如何實作workflow的流轉的呢。
           

Tekton利用Kubernetes的List-Watch機制,在啟動時初始化了2個Controller, PipelineRunController和TaskRunController。

PipelineRunController監聽PipelineRun對象的變化。在它的reconcile邏輯中,将pipeline中所有的Task建構為一張有向無環圖(DAG),通過周遊DAG找到目前可被排程的Task節點建立對應的TaskRun對象。

TaskRunController監聽TaskRun對象的變化。在它的reconcile邏輯中将TaskRun和對應Task轉化為可執行的Pod,由kubernetes排程執行。利用Kubernetes的OwnerReference機制,pipelinerun own taskrun, taskrun own pod。pod狀态變更時觸發taskrun的reconcile邏輯,taskrun狀态變更時觸發pipelinerun的reconcile邏輯。

DAG支援

Tekton對DAG的支援相對比較簡單。在Tekton中一個Pipeline就是一張DAG,Pipeline中的多個Task可是DAG中的節點。Task預設并發執行,可以通過

RunAfter

From

關鍵字控制執行順序。

示例:

- name: lint-repo
  taskRef:
    name: pylint
  resources:
    inputs:
      - name: workspace
        resource: my-repo
- name: test-app
  taskRef:
    name: make-test
  resources:
    inputs:
      - name: workspace
        resource: my-repo
- name: build-app
  taskRef:
    name: kaniko-build-app
  runAfter:
    - test-app
  resources:
    inputs:
      - name: workspace
        resource: my-repo
    outputs:
      - name: image
        resource: my-app-image
- name: build-frontend
  taskRef:
    name: kaniko-build-frontend
  runAfter:
    - test-app
  resources:
    inputs:
      - name: workspace
        resource: my-repo
    outputs:
      - name: image
        resource: my-frontend-image
- name: deploy-all
  taskRef:
    name: deploy-kubectl
  resources:
    inputs:
      - name: my-app-image
        resource: my-app-image
        from:
          - build-app
      - name: my-frontend-image
        resource: my-frontend-image
        from:
          - build-frontend           

渲染出的執行順序為:

|            |
        v            v
     test-app    lint-repo
    /        \
   v          v
build-app  build-frontend
   \          /
    v        v
    deploy-all           

相比于Argo等專注在workflow的項目而言,Tekton支援的任務編排方式是非常有限的。常見的循環,遞歸,重試,逾時等待等政策都是沒有的。

  • 條件判斷

Tekton支援

condition

關鍵字來進行條件判斷。Condtion隻支援判斷目前Task是否執行,不能作為DAG的分支條件來進行動态DAG的渲染。

* condition檢查失敗(exitCode != 0),task不會被執行,pipelineRun狀态不會因為condition檢查失敗而失敗。
* 多個條件之間 “與” 邏輯關系
           

PipelineResource在Task間資料交換

作為CICD的工具,代碼在什麼時候Clone到WorkSpace中,如何實作的? Tekton中抽象了PipelineResource進行任務之間的資料交換,GitResource是其中最基礎的一種。用法如下。

  • 聲明一個Git類型的PipelineResource:
kind: PipelineResource
metadata:
  name: skaffold-git-build-push-kaniko
spec:
  type: git
  params:
  - name: revision
    value: v0.32.0
  - name: url
    value: https://github.com/GoogleContainerTools/skaffold           
  • 在Task中引用這個Resource做為輸入:
kind: Task
metadata:
  name: build-push-kaniko
spec:
  inputs:
    resources:
    - name: workspace
      type: git
  steps:
  - name: build-and-push
    image: registry.cn-shanghai.aliyuncs.com/kaniko-project-edas/executor:v0.17.1           
  • 代碼會被clone在/workspace目錄。

Tekton是如何處理這些PipelineResource的呢,這就要從Taskrun Controller如何建立Pod說起。

Tekton中一個TaskRun對應一個Pod,每個Pod有一系列init-containers和step-containers組成。init-container中完成認證資訊初始化,workspace目錄初始化等初始化工作。

在處理step-container時,會根據這個Task引用的資源 Append或者Insert一個step-container來處理對應的輸和輸出,如下圖所示。

Task中Step執行順序控制

Tekton源自Knative Build,在Knative Build中使用Init-container來串聯Steps保證Steps順序執行,在上面的分析中我們知道Tekton是用Containers來執行Steps,Pod的Containers是并行執行的,Tekton是如何保證Steps執行順序呢?

這是一個TaskRun建立的Pod的部分描述資訊,可以看到所有的Step都是被/tekton/tools/entrypoints封裝起來執行的。 -wait_file指定一個檔案,通過監聽檔案句柄,在探測到檔案存在時執行被封裝的Step任務。 -post_file指定一個檔案,在Step任務完成後建立這個檔案。通過檔案序列/tekton/tools/${index}來對Step進行排序。

- args:
    - -wait_file
    - /tekton/tools/0
    - -post_file
    - /tekton/tools/1
    - -termination_path
    - /tekton/termination
    - -entrypoint
    - /ko-app/git-init
    - --
    - -url
    - https://github.com/GoogleContainerTools/skaffold
    - -revision
    - v0.32.0
    - -path
    - /workspace/workspace
    command:
    - /tekton/tools/entrypoint
    image: registry.cn-shanghai.aliyuncs.com/kaniko-project-edas/git-init:v0.10.2
    name: step-git-source-skaffold-git-build-push-kaniko-rz765
  - args:
    - -wait_file
    - /tekton/tools/1
    - -post_file
    - /tekton/tools/2
    - -termination_path
    - /tekton/termination
    - -entrypoint
    - /kaniko/executor
    - --
    - --dockerfile=Dockerfile
    - --destination=localhost:5000/leeroy-web
    - --context=/workspace/workspace/examples/microservices/leeroy-web
    - --oci-layout-path=$(inputs.resources.builtImage.path)
    command:
    - /tekton/tools/entrypoint
    image: registry.cn-shanghai.aliyuncs.com/kaniko-project-edas/executor@sha256:565d31516f9bb91763dcf8e23ee161144fd4e27624b257674136c71559ce4493
    name: step-build-and-push
  - args:
    - -wait_file
    - /tekton/tools/2
    - -post_file
    - /tekton/tools/3
    - -termination_path
    - /tekton/termination
    - -entrypoint
    - /ko-app/imagedigestexporter
    - --
    - -images
    - '[{"name":"skaffold-image-leeroy-web-build-push-kaniko","type":"image","url":"localhost:5000/leeroy-web","digest":"","OutputImageDir":"/workspace/output/builtImage"}]'
    command:
    - /tekton/tools/entrypoint
    image: registry.cn-shanghai.aliyuncs.com/kaniko-project-edas/imagedigestexporter:v0.10.2
    name: step-image-digest-exporter-lvlj9
               

實踐

使用Tekton建構代碼并部署到SAE

Serverless 應用引擎(

SAE

) 是阿裡雲上一款面向應用的 Serverless PaaS 平台,幫助 PaaS 層使用者免運維 IaaS,按需使用,按量計費,實作低門檻微服務應用上雲,有效解決成本及效率問題。支援 Spring Cloud、Dubbo 和 HSF 等流行的開發架構,真正實作了 Serverless 架構和微服務架構的完美融合。

接下來将使用Tekton部署一個Spring Cloud微服務應用到SAE平台。

示例中的示範代碼位址:https://github.com/alicloud-demo/spring-cloud-demo
           
apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
  name: spring-cloud-demo
spec:
  type: git
  params:
  - name: url
    value: https://github.com/alicloud-demo/spring-cloud-demo           
  • 定義建構和部署Task

根據SAE

官方文檔

進行部署。

apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
  name: build-deploy-sae
spec:
  inputs:
    resources:
    - name: source
      type: git
  steps:
  - name: build-and-deploy
    image: maven:3.3-jdk-8
    command: ["mvn", "clean", "package", "-f", "source", "toolkit:deploy", "-Dtoolkit_profile=toolkit_profile.yaml", "-Dtoolkit_package=toolkit_package.yaml", "-Dtoolkit_deploy=toolkit_deploy.yaml"]
    securityContext:
      runAsUser: 0           
  • 定義TaskRun運作任務
apiVersion: tekton.dev/v1alpha1
kind: TaskRun
metadata:
  name: build-deploy-sae
spec:
  taskRef:
    name: build-deploy-sae
  inputs:
    resources:
    - name: source
      resourceRef:
        name: spring-cloud-demo           
  • 導入到kubernetes中運作
kubectl apply -f source-2-service-taskrun.yaml           
  • 檢視日志
kubectl logs build-deploy-sae-pod-85xdk step-build-and-deploy           

建構日志:

部署日志:

[INFO] Start to upload [provider3-1.0-SNAPSHOT.jar] using [Sae uploader].
[INFO] [##################################################] 100.0%
[INFO] Upload finished in 3341 ms, download url: [https://edas-hz.oss-cn-hangzhou.aliyuncs.com/apps/K8S_APP_ID/37adb12b-5f0c-4711-98ec-1f1e91e6b043/provider3-1.0-SNAPSHOT.jar]
[INFO] Begin to trace change order: e2499b9a-6a51-4904-819c-1838c1dd62cb
[INFO] PipelineName: Batch: 1, PipelineId:f029314a-88bb-450b-aa35-7cc550ff1329
[INFO] Waiting...
[INFO] Waiting...
[INFO] Waiting...
[INFO] Waiting...
[INFO] Waiting...
[INFO] Waiting...
[INFO] Waiting...
[INFO] Waiting...
[INFO] Deploy application successfully!
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 32:41 min
[INFO] Finished at: 2020-04-15T10:09:39+00:00
[INFO] Final Memory: 47M/190M
[INFO] ------------------------------------------------------------------------           
  • 驗證部署結果

在SAE控制台檢視變更記錄:

驗證應用通路:

總結

差別于傳統的CICD工具(Jenkins),Tekton是一套建構CICD系統的架構。Tekton不能使你立即獲得CICD的能力。但是基于Tekton可以設計出各種花式的建構部署流水線。得益于Tekton良好的抽象,這些設計出的流水線可以作為模闆在多個組織,項目間共享。 Tekton源自Knative的Build-Template項目,設計之初的一個重要目标就是使人們能夠共享和重用構成pipeline的元件,以及Pipeline本身。在Tekton的RoadMap中Tekton Catelog就是為了實作這一目标而提出的。

差別于Argo這種基于Kubernetes的Workflow工具,Tekton在工作流控制上的支援是比較弱的。一些複雜的場景比如循環,遞歸等都是不支援的。更不用說Argo在高并發和大叢集排程下的性能優化。這和Tekton的定位有關,Tekton定位于實作CICD的架構,對于CICD不需要過于複雜的流程控制。大部分的研發流程可以被若幹個最佳實踐來覆寫。而這些最佳實踐應該也必須可以在不同的組織間共享,為此Tekton設計了PipelineResource的概念。PipelineResource是Task間互動的接口,也是跨平台跨組織共享重用的元件,在PipelineResource上還可以有很多想象空間。

作者資訊:九辯,阿裡巴巴進階開發工程師,負責阿裡雲EDAS(企業級分布式應用服務)應用生命周期研發工作,長期關注雲時代微服務的部署和治理工作。