<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Kubernetes 原生 CI/CD 構(gòu)建框架 Tekton 詳解!

          共 7547字,需瀏覽 16分鐘

           ·

          2021-03-08 19:54

          流水線(Pipeline)是把一個重復(fù)的過程分解為若干個子過程,使每個子過程與其他子過程并行進(jìn)行的技術(shù)。 本文主要介紹了誕生于云原生時代的流水線框架 Tekton。

          作者:FogDong(Tekton 社區(qū))

          編輯:Bach(才云)

          K8sMeetup

          什么是流水線?

          在計(jì)算機(jī)中,流水線是把一個重復(fù)的過程分解為若干個子過程,使每個子過程與其他子過程并行進(jìn)行的技術(shù),也叫 Pipeline。由于這種 s工作方式與工廠中的生產(chǎn)流水線十分相似, 因此也被稱為流水線技術(shù)。從本質(zhì)上講,流水線技術(shù)是一種時間并行技術(shù)。“構(gòu)建鏡像”過程為例:

          在每一次構(gòu)建鏡像中,我們都需要拉下代碼倉庫中的代碼,進(jìn)行代碼編譯,構(gòu)建鏡像,最后推往鏡像倉庫。在每一次代碼更改過后,這一過程都是不變的。使用流水線工具可以極大的提升這一過程的效率,只需要進(jìn)行簡單的配置便可以輕松的完成重復(fù)性的工作。這樣的過程也被稱之為 CI。
          上圖流程中使用的是 Jenkins。Jenkins 作為老牌流水線框架被大家所熟知。在云原生時代,Jenkins 也推出了 Jenkins X 作為基于 Kubernetes 的新一代流水線,但今天本文主要介紹誕生于云原生時代的流水線框架——Tekton。
          K8sMeetup

          Tekton

          Tekton 是一個基于 Kubernetes 的云原生 CI/CD 開源框架,屬于 CD 基金會的項(xiàng)目之一。Tekton 通過定義 CRD 的方式,讓用戶以靈活的自定義流水線以滿足自身 CI/CD 需求。

          基本概念
          四個基本概念
          Tekton 最主要的四個概念為:Task、TaskRun、Pipeline 以及 PipelineRun。

          • Task: Task 為構(gòu)建任務(wù),是 Tekton 中不可分割的最小單位,正如同 Pod 在 Kubernetes 中的概念一樣。在 Task 中,可以有多個 Step,每個 Step 由一個 Container 來執(zhí)行。
          • Pipeline: Pipeline 由一個或多個 Task 組成。在 Pipeline 中,用戶可以定義這些 Task 的執(zhí)行順序以及依賴關(guān)系來組成 DAG(有向無環(huán)圖)。
          • PipelineRun: PipelineRun 是 Pipeline 的實(shí)際執(zhí)行產(chǎn)物,當(dāng)用戶定義好 Pipeline 后,可以通過創(chuàng)建 PipelineRun 的方式來執(zhí)行流水線,并生成一條流水線記錄。
          • TaskRun: PipelineRun 被創(chuàng)建出來后,會對應(yīng) Pipeline 里面的 Task 創(chuàng)建各自的 TaskRun。一個 TaskRun 控制一個 Pod,Task 中的 Step 對應(yīng) Pod 中的 Container。當(dāng)然,TaskRun 也可以單獨(dú)被創(chuàng)建。
          綜上可知:Pipeline 由多個 Task 組成,每次執(zhí)行對應(yīng)生成一條 PipelineRun,其控制的 TaskRun 將創(chuàng)建實(shí)際運(yùn)行的 Pod。下面以一個簡單例子來展示這些概念。
          首先,創(chuàng)建一個最簡單的 Task,里面僅有一個 Step。在一個 ubuntu 鏡像中執(zhí)行 ls 命令。

          接著創(chuàng)建一個 Pipeline,里面引用第一步中創(chuàng)建的 Task。

          在 Pipeline 存在的前提下,就可以通過創(chuàng)建 PipelineRun 來運(yùn)行 Pipeline。

          這樣就完成了一個最簡單的 Tekton 流水線案例。每一個 PipelineRun 的創(chuàng)建,都會遵循 Pipeline 中的順序規(guī)則去啟動 Task 的 Pod。下面引入另外一個概念 PipelineResource 來完成一個稍微復(fù)雜的例子,也是 DevOps 中最常見的場景:從代碼倉庫拉取鏡像、進(jìn)行代碼構(gòu)建、并最終將構(gòu)建好的鏡像推往鏡像倉庫。
          PipelineResource
          PipelineResource 代表著一系列的資源,主要承擔(dān)作為 Task 的輸入或者輸出的作用。它有以下幾種類型:
          • git:代表一個 git 倉庫,包含了需要被構(gòu)建的源代碼。將 git 資源作為 Task 的 Input,會自動 clone 此 git 倉庫。
          • pullRequest:表示來自配置的 url(通常是一個 git 倉庫)的 pull request 事件。將 pull request 資源作為 Task 的 Input,將自動下載 pull request 相關(guān)元數(shù)據(jù)的文件,如 base/head commit、comments 以及 labels。
          • image:代表鏡像倉庫中的鏡像,通常作為 Task 的 Output,用于生成鏡像。
          • cluster:表示一個除了當(dāng)前集群外的 Kubernetes 集群。可以使用 Cluster 資源在不同的集群上部署應(yīng)用。
          • storage:表示 blob 存儲,它包含一個對象或目錄。將 Storage 資源作為 Task 的 Input 將自動下載存儲內(nèi)容,并允許 Task 執(zhí)行操作。目前僅支持 GCS。
          • cloud event:會在 TaskRun z執(zhí)行完成后發(fā)送事件信息(包含整個 TaskRun) 到指定的 URI 地址,在與第三方通信的時候十分有用。
          以上為 Tekton 目前支持的六大 PipelineResource 類型,具體的配置及使用方法詳見 PipelineResource 文檔。
          文檔地址:https://github.com/tektoncd/pipeline/blob/master/docs/resources.md
          繼續(xù)分析較復(fù)雜的流水線案例:從代碼倉庫拉取鏡像、進(jìn)行代碼構(gòu)建、并將構(gòu)建好的鏡像推往鏡像倉庫。從已有的 PipelineResource 類型可判斷,可以使用 git 類型作為代碼資源作為輸入,再用 image 類型作為鏡像資源作為輸出。有了輸入輸出后,我們可以直接使用 Kaniko 來構(gòu)建鏡像。
          Kaniko 是 Google 開源的項(xiàng)目之一,可在 Kubernetes 上無需特權(quán)模式地構(gòu)建 docker 鏡像。
          首先創(chuàng)建這兩個 PipelineResource。在這個例子中,git-input 對應(yīng)輸入,image-output 對應(yīng)輸出。params 中的參數(shù)均為該資源類型的固定參數(shù):如 git 中可以通過 revision 指定版本號,image 中可以通過 url 指定鏡像倉庫地址。
          Git-input:

          Image-output:

          在配置 PipelineResource 時,如果使用了私有倉庫,還需要配置 Service Account,詳見 configuring-authentication-for-docker。
          configuring-authentication-for-docker 地址:https://github.com/tektoncd/pipeline/blob/master/docs/auth.md#configuring-authentication-for-docker
          產(chǎn)物傳遞
          創(chuàng)建完 PipelineResource 后,需要在 Task 中引入它們作為輸入輸出。那么,這些資源是如何在 Task 間傳遞的呢?
          在 Tekton 的分區(qū)下,我們可以看到一個叫做 config-artifact-pvc 和一個叫做 config-artifact-bucket 的 Config Map。從命名就可以看出,這二者分別代表了產(chǎn)物存儲的兩種配置方式—— PVC 和存儲桶(目前支持 GCS 和 S3)
          以 PVC 為例,修改 config-artifact-pvc 需要填寫兩個值:size 以及 storageClassName。size 默認(rèn)為 5GiB,storage class name 默認(rèn)為 default。這也意味著當(dāng)我們使用 PipelineResource 進(jìn)行資源傳遞時,會自動創(chuàng)建一個 5GiB 的存儲卷掛載在 Task 上,供 PipelineResource 使用。
          在需要進(jìn)行 Task 間的資源傳遞時,這個存儲卷會被掛載在 Task 的 /pvc 目錄下。當(dāng) Task 執(zhí)行完成并且需要進(jìn)行資源傳遞(通過 inputs/outputs 指定)后,TaskRun controller 會自動添加一個拷貝文件的步驟容器,并將輸出產(chǎn)物統(tǒng)一放到 /pvc/task_name/resource_name 命名規(guī)范的目錄下。
          上面是針對產(chǎn)物需要進(jìn)行傳遞的情況下,對于目前例子而言,由于只需要一個 Task,雖然指定了 Inputs 和 Outputs,但并沒有另一個 Task 來引用這些結(jié)果。因此,在這個例子中并不會去掛載 PVC。
          對于 git 以及 storage 類型的 input,資源下載后會被 放在 /workspace/task_resource_name 下;對于 output 則會放在 /workspace/output/resource_name 下。image 類型的資源則會直接上傳到鏡像倉庫。
          了解了這些前置知識后,我們可以來創(chuàng)建 Task 了。Kaniko 需要三個參數(shù)來完成鏡像構(gòu)建:Dockerfile 的地址,context 的地址以及鏡像倉庫的地址。在下面這個例子中,我們大量使用了 params 以及 Tekton 中的變量替換。Params 用于在 TaskRun 和 Task 中傳遞參數(shù),而變量替換的格式為 $(xxx)。使用這些變量可以讓 Tekton 在運(yùn)行過程中根據(jù)規(guī)則進(jìn)行賦值。值得注意的是,Tekton 并不會提前去檢查這些變量的內(nèi)容,這就要求著我們在寫的時候需要多加注意。具體的變量編寫規(guī)則詳見:Tekton variables。
          Tekton variables 地址:https://github.com/tektoncd/pipeline/blob/master/docs/variables.md

          有了 Task 后,就能創(chuàng)建 TaskRun 來執(zhí)行 Task。注意,在 spec 中申明了 serviceAccountName 用于指定私有倉庫的權(quán)限。

          至此,一個更為復(fù)雜的流水線也構(gòu)建完成了。
          DAG
          在 Tekton 中,DAG(有向無環(huán)圖)的功能是原生支持的。只需要通過申明 runAfter 及 from 便可以便利的使 Pipeline 以 DAG 方式運(yùn)行。
          • from:當(dāng) Task 的 Inputs 依賴于上一個 Task 的 Outputs 時,可以通過 from 參數(shù)來指定
          • runAfter:當(dāng) Task 間沒有資源依賴,但需要使一個 Task 在另外一個 Task 之后運(yùn)行的話,可以使用 runAfter 來指定。

          例如在上面的例子中,任務(wù)會以下順序運(yùn)行:

          • lint-repo 和 test-app 中的 Task 沒有 from 或 runAfter 關(guān)鍵字,會同時開始執(zhí)行。

          • 一旦 test-app 完成,build-app 和 build-frontend 都會開始同時執(zhí)行,因?yàn)樗鼈?nbsp;runAfter 于 test-app

          • deploy-all 會在 build-app 和 build-frontend 都完成后才執(zhí)行,因?yàn)樗枰馁Y源 from 于這二者。

          再來看看 Tekton 是怎么樣來實(shí)現(xiàn)這段邏輯的:
          在 Pipeline 的 Controller 中,一旦監(jiān)聽到 Pipeline 的創(chuàng)建,在創(chuàng)建對應(yīng)的 TaskRun 之前,會先檢測 Pipeline 中的依賴順序并構(gòu)建 DAG 圖:

          Step 執(zhí)行順序
          Pipeline 中可以進(jìn)行對 Task 的順序控制,那么 Task 中呢?
          在 Kubernetes 中,Pod 里的 Container 是并行啟動的。而在 Tekton 中,雖然 Task 對應(yīng) Pod,Task 中的 Step 對應(yīng) Container,但 Task 中的 Step 卻是順序執(zhí)行的。要了解 Tekton 是怎么完成這樣的順序控制,首先我們來看一下一個 Tekton 的 Pod。
          在這個 Pod 中,除了用戶需要運(yùn)行的 Container,還被注入了一個 InitContainer:

          這個 InitContainer copy 了一個 entrypoint 的二進(jìn)制到 Pod 中。再看下用戶的 container,我們可以看到 Pod 的執(zhí)行命令被 Tekton 改寫了一下:

          可以看到 command 被改寫為了 entrypoint 命令,這個二進(jìn)制包在 initContainer 中被導(dǎo)入,另外還有一些啟動參數(shù):

          • -post_file:指定了 Step 完成后的文件寫入路徑。如果 Step 失敗,則寫入到 {{post_file}}.err。可以看到上面的寫入路徑為 /tekton/tools/0,最后的這個數(shù)字即為 Step 的編號。
          • -wait_file:指定了在啟動下一個 Step 之前要查看的文件路徑。它將監(jiān)聽 {{wait_file}} 和 {{wait_file}}.err。若有錯誤則跳過執(zhí)行寫入 {{post_file}}.err 并返回錯誤(exitCode >= 0);若無錯誤則執(zhí)行下一個 Step。如上例子為第一個 step,若為第二個 step,wait_ file 的地址會是 /tekton/tools/0,也就是上一個 step 的 post_file 地址。
          資源控制
          在 Kubernetes 中,一個 Pod 被調(diào)度需要節(jié)點(diǎn)滿足 Pod 中的所有 Container 的資源。如下圖:

          這個 Pod 有 4 個容器,總共需要 9 個 CPU。Kubernetes 將把這個 Pod 調(diào)度到一個擁有 9 個可用 CPU 的節(jié)點(diǎn)上。如果沒有節(jié)點(diǎn)有 9 個可用 CPU,Pod 將被調(diào)度失敗并無法啟動。
          而對于 Tekton 而言,因?yàn)?Pod 中的 Container 會順序執(zhí)行,所以只需要滿足這個 Pod 中資源最大的 Container 即可。對于同一個TaskRun,Tekton 會獲取最大請求,并讓一個 Container 去請求這些資源,其他都設(shè)為 0。
          如下,該 Pod 請求 4 個 CPU,而不是 9 個。這樣的資源控制方式更為合理且所有的 Step 容器仍保留所需要的資源。
          在有 LimitRange 限制 Container 必須有資源的的情況下,每個 Container 最小會設(shè)置為 LimitRange 的設(shè)置。

          源碼部分邏輯如下:

          數(shù)據(jù)傳遞
          除了 PipelineResource 以外,Tekton 還提供了其他數(shù)據(jù)傳遞的方式。
          PipelineResource 仍處于 Alpha 版本,它有可能會被重新設(shè)計(jì)、替換、棄用或者完全刪除。Tekton 社區(qū)鼓勵用戶用 Task 代替 PipelineResources。
          Workspace

          Workspace 與 Kubernetes 中 Volume 概念幾乎保持一致,只不過并不是 Pod 層級的而是作用于 Tekton 資源層級的。Workspace 在 Pipeline 中使用時是一個抽象的概念,實(shí)際的存儲類型需要在 PipelineRun 中指定。詳見:Workspaces。

          Workspaces 地址:https://github.com/tektoncd/pipeline/blob/master/docs/workspaces.md
          Results
          Tekton 提供了一個固定目錄用于存放 Task 的輸出:/tekton/results

          如上,該 task 將日期輸出到了 /tekton/results/current-date 中。同時,也會被作為 Results 字段加到 TaskRun 的 Status 中。這樣,其他的 Task 便可以通過 $(tasks..results.) 來獲取到該 Task 的 results。(變量替換將會實(shí)際從 TaskRun 中獲取到 Results 的值)
          其他流程控制功能
          條件判斷
          低版本可以使用 Conditions,高版本推薦使用 WhenExpressions(Conditions 將在不久后廢棄,完全替換為 WhenExpressions)。WhenExpressions 由 Input、Operator、Values 三部分組成,其中 Input 可以使用 Tekton 的 Parameter 或者 Results,Operator 目前僅支持 in 和 notin:

          錯誤重嘗
          通過 retries 來指定任務(wù)失敗后重新嘗試的次數(shù):

          退出處理
          通過 finally 指定在 pipeline 結(jié)束時執(zhí)行的 task,無論 pipeline 的結(jié)果是成功或失敗。

          取消執(zhí)行
          要取消當(dāng)前正在執(zhí)行的 PipelineRun,可以在其 Spec 中更新 Status 為取消。當(dāng) PipelineRun 被取消時,所有相關(guān)的 Pods 都被刪除。例如:

          Pipeline 暫停的邏輯與之類似,但暫停 PR 尚未合入,暫停功能也在 Tekton 今年的 Roadmap 中。
          Runs
          Runs 是一個進(jìn)行中的 feature,Run 允許實(shí)例化和執(zhí)行一個 Custom Task,這個 Custom Task 可以通過用戶自定義的 controller 來執(zhí)行。這對于用戶來說是一個非常實(shí)際的功能,可以通過自己寫的 Controller 來定義 Task 的邏輯,而不再拘泥于 Tekton 定義的 Task。


          K8S 進(jìn)階訓(xùn)練營


           點(diǎn)擊屏末  | 即刻學(xué)習(xí)
          瀏覽 43
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产主播91 | 超碰在线进入 | 国产永久性人人视频 | 国产一a毛一a毛A免费 | 人妻av中文无码 人妻-X88AⅤ |