Pipeline on Openshift4(Tekton)

OpenShift Pipeline 是一種云原生,持續(xù)集成和交付(CI/CD)解決方案,使用Tekton構建pipeline。

實現(xiàn)了以模塊化方式從源碼到應用運行態(tài)的自動化流程, 源碼->制品->容器鏡像->應用發(fā)布。并可自定義穿插其他模塊,如代碼掃描、鏡像安全、消息推送等。

1. 模塊介紹

OpenShift Pipeline 通過自定義資源對象(CRD)以模塊化的方式構建pipeline。
主要使用的 CRD 有 task, pipeline, pipelinerun, taskrun,trigger

tekton.png

Task:
task 是在 Pipeline 中可配置的最小單元。作為 pipeline 的一部分也可獨立運行。每個還可定義多個 step,順序執(zhí)行。 比如 buildah 這個 task 就有 build,push, digest-to-results 三個 step。
task內容主要由 image 和運行腳本組成。spec.params.xx 的值由 pipeline 傳入
task 通常會設計為可重復調用。
示例

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: update-deployment
spec:
  params:
    - name: deployment
      description: The name of the deployment patch the image
      type: string
    - name: IMAGE
      description: Location of image to be patched with
      type: string
  steps:
    - name: patch
      image: image-registry.openshift-image-registry.svc:5000/openshift/cli:latest
      command: ["/bin/bash", "-c"]
      args:
        - |-
          oc patch deployment $(inputs.params.deployment) --patch='{"spec":{"template":{"spec":{
            "containers":[{
              "name": "$(inputs.params.deployment)",
              "image":"$(inputs.params.IMAGE)"
            }]
          }}}}'

piepeline:
Pipeline 由一系列 task 組成的通用工作流模板,并會定義 task 的執(zhí)行順序。

PipelineRun:
PipelineRun 是一個 Pipeline 的運行實例。PipelineRun 啟動 Pipeline,并為 Pipeline 中執(zhí)行的每個任務管理一個 TaskRun 的創(chuàng)建。

TaskRun:
PipelineRun 由 Pipeline 中每個任務的 PipelineRun 自動創(chuàng)建。它是在 Pipeline 中運行任務實例的結果。如果某個任務在 Pipeline 之外運行,它也可以被手工創(chuàng)建。

Workspace:
Workspace 是一個存儲卷,任務(Task)在運行時需要它來接收輸入或提供輸出。Task 或 Pipeline 會聲明 Workspace,一個TaskRun 或 PipelineRun 則會提供存儲卷的實際位置,存儲卷被掛載到聲明的 Workspace 上。這使得任務具有靈活性、可重復使用,并允許在多個任務間共享工作區(qū)。

多個 pipelinerun 共享存儲的時候需要注意,有的 task 初始化時候會清除之前的數(shù)據(jù),多個 pipelinerun 同時運行并共用存儲可能存在數(shù)據(jù)被清除的情況。

Trigger:
Trigger(觸發(fā)器)捕獲外部事件,如 Git 拉取請求,并處理事件有效負載以獲取關鍵信息。

2. 安裝 Red Hat OpenShift Pipelines Operator

如果離線環(huán)境,需要先執(zhí)行離線部署operatorhub
https://github.com/cai11745/ocp4-userguide 可參照《離線部署operatorhub并批量導入》

  1. 在控制臺的 Administrator 視角中,Operators → OperatorHub。
  2. 搜索 Red Hat OpenShift Pipelines Operator。點 Red Hat OpenShift Pipelines Operator 。
  3. 在 Install Operator 頁面中:
    Installation Mode 選擇 All namespaces on the cluster (default)。選擇該項會將 Operator 安裝至默認openshift-operators 命名空間,這將啟用 Operator 以進行監(jiān)視并在集群中的所有命名空間中可用。
    Approval Strategy(批準策略)選擇 Automatic。這樣可確保以后對 Operator 的升級由 Operator Lifecycle Manager (OLM) 自動進行。

Update Channel:Stable 頻道啟用 Red Hat OpenShift Pipelines Operator 最新穩(wěn)定版本的安裝。preview 頻道啟用 Red Hat OpenShift Pipelines Operator 的最新預覽版本,該版本可能包含 Stable 頻道中還未提供的功能。

點擊 Install。會看到 Installed Operators 頁面中列出的 Operator。

檢查 Status 變成 Succeeded 表示 Red Hat OpenShift Pipelines Operator 已安裝成功。

查看相關api
[root@bastion ~]# oc api-resources --api-group=tekton.dev
NAME                SHORTNAMES   APIVERSION            NAMESPACED   KIND
clustertasks                     tekton.dev/v1beta1    false        ClusterTask
conditions                       tekton.dev/v1alpha1   true         Condition
pipelineresources                tekton.dev/v1alpha1   true         PipelineResource
pipelineruns        pr,prs       tekton.dev/v1beta1    true         PipelineRun
pipelines                        tekton.dev/v1beta1    true         Pipeline
runs                             tekton.dev/v1alpha1   true         Run
taskruns            tr,trs       tekton.dev/v1beta1    true         TaskRun
tasks                            tekton.dev/v1beta1    true         Task

相關pod  
[root@bastion ~]# oc get pod -n openshift-pipelines
NAME                                             READY   STATUS    RESTARTS   AGE
tekton-operator-proxy-webhook-5c86d47c54-kpcvx   1/1     Running   0          6h42m
tekton-pipelines-controller-78f7f7449d-wrcvb     1/1     Running   0          6h42m
tekton-pipelines-webhook-7885bc985b-54pc5        1/1     Running   0          7h10m
tekton-triggers-controller-76c8d6bd-kwgrk        1/1     Running   0          7h10m
tekton-triggers-webhook-6d6cfb6568-gl779         1/1     Running   0          7h10m

3. 場景示例

使用 Red Hat OpenShift Pipelines,創(chuàng)建一個自定義的 CI/CD 解決方案來構建、測試和部署應用程序。

主要以下流程:

  • 創(chuàng)建自定義task,或使用現(xiàn)有的可重復使用的task。
  • 為應用程序創(chuàng)建并定義pipeline。
  • 使用持久化存儲添加到pipeline的workspace,以保存中間數(shù)據(jù),如代碼、制品。
  • 創(chuàng)建一個 PipelineRun 對象來實例化并調用pipeline。
  • 添加tigger以捕獲源倉庫中的事件。(本文不包含,下一篇做)

使用redhat 官網(wǎng)提供的示例, pipelines-tutorial 來演示。這個示例使用一個簡單的應用程序,它由以下部分組成:

一個前端界面 vote-ui,它的源代碼在 ui-repo Git
一個后端接口 vote-api,它的源代碼在 api-repo Git
apply-manifests 和 update-deployment 任務在 pipelines-tutorial Git

3.1 創(chuàng)建新的project

Pipelines Operator 會自動添加并配置一個名為 pipeline 的 ServiceAccount,它有足夠的權限來構建和推送鏡像。這個 ServiceAccount 由 PipelineRun 使用。

oc new-project pipelines-tutorial
oc get serviceaccount pipeline

3.2 創(chuàng)建 task

安裝 tekton client 命令 tkn

# 下載地址
https://mirror.openshift.com/pub/openshift-v4/clients/pipeline/

wget https://mirror.openshift.com/pub/openshift-v4/clients/pipeline/0.13.1/tkn-linux-amd64-0.13.1.tar.gz
chmod +x tkn 
mv tkn /usr/local/bin/
tkn version
# Client version: 0.13.1
# Pipeline version: v0.19.0
# Triggers version: v0.10.2

從 pipelines-tutorial git庫安裝 apply-manifests 和 update-deployment 任務資源,其中包含可為管道重復使用的任務列表:

oc create -f https://raw.githubusercontent.com/openshift/pipelines-tutorial/pipelines-1.3/01_pipeline/01_apply_manifest_task.yaml
oc create -f https://raw.githubusercontent.com/openshift/pipelines-tutorial/pipelines-1.3/01_pipeline/02_update_deployment_task.yaml

使用 oc get task 或者 tkn task list 命令列出創(chuàng)建的任務:

[root@bastion 01_pipeline]# oc get task
NAME                AGE
apply-manifests     22s
update-deployment   17s

[root@bastion 01_pipeline]# tkn task list
NAME                DESCRIPTION   AGE
apply-manifests                   5 minutes ago
update-deployment                 5 minutes ago

輸出會確認創(chuàng)建了 apply-manifests 和 update-deployment 任務

使用 tkn clustertasks list 命令列出由 Operator 安裝的額外集群任務,如 buildah 和 s2i-python-3

[root@bastion 01_pipeline]# tkn clustertasks list
NAME                       DESCRIPTION              AGE
buildah                    Buildah task builds...   1 day ago
buildah-pr                 Buildah task builds...   1 day ago
buildah-pr-v0-19-0         Buildah task builds...   1 day ago
buildah-v0-19-0            Buildah task builds...   1 day ago
git-cli                    This task can be us...   8 hours ago
git-clone                  These Tasks are Git...   1 day ago
......

注意: 在內網(wǎng)環(huán)境使用 buildah 集群任務,您必須確保 Dockerfile 使用內部鏡像流作為基礎鏡像。

創(chuàng)建存儲,必須。
因為每個 task 都是通過pod 執(zhí)行腳本,pod任務完成后的輸出物需要通過存儲流轉到下一階段,比如第一步拉取的代碼,第二步需要編譯,第三步需要做代碼掃描。

~ oc create -f https://raw.githubusercontent.com/openshift/pipelines-tutorial/pipelines-1.3/01_pipeline/03_persistent_volume_claim.yaml 

~ oc get pvc
NAME         STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
source-pvc   Bound    pvc-7c82cb22-65f1-47fb-9ed0-9c4ca5c4f992   500Mi      RWO            managed-nfs-storage   29s

3.3 組裝 pipeline

pipeline 由多個 task 組成,設計成可以在多個場景下進行復用。

Pipeline 通過使用 from 和 runAfter 參數(shù)來指定在不同任務間如何進行交互以及它們執(zhí)行的順序。它使用 workspaces 字段指定 Pipeline 中每個任務在執(zhí)行過程中所需的一個或多個卷。

導入示例 pipeline,此 pipeline 一共有4個階段,是fetch-repository, build-image, apply-manifests, update-deployment,分別對應4個 task: git-clone(ClusterTask),buildah(ClusterTask),apply-manifests,update-deployment。 前兩個task 是 operator 自帶的,全局屬性,后兩個task是我們剛剛創(chuàng)建的,只在當前 project 生效。

oc create -f https://raw.githubusercontent.com/openshift/pipelines-tutorial/pipelines-1.3/01_pipeline/04_pipeline.yaml

# 內容解讀
[root@bastion 01_pipeline]# cat 04_pipeline.yaml  
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: build-and-deploy
spec:
  workspaces:
  - name: shared-workspace
  params:
  - name: deployment-name    #與下文tasks 中的params.value 對應,
                            #此處將來可輸入?yún)?shù),回填到tasks.params.value
                            #如果通過web console 運行,params的內容能可視化輸入與展示,類似 openshift Template
    type: string
    description: name of the deployment to be patched
  - name: git-url
    type: string
    description: url of the git repo for the code of deployment
  - name: git-revision
    type: string
    description: revision to be used from repo of the code for deployment
    default: "pipelines-1.3"  
  - name: IMAGE
    type: string
    description: image to be build from the code
  tasks:    #tasks.name 有幾個就代表有幾個步驟,此name為自定義
  - name: fetch-repository
    taskRef:
      name: git-clone  #指定使用的task,此處使用了ClusterTask
      kind: ClusterTask
    workspaces:
    - name: output  #與clustertask git-clone 中spec.workspace.name 一致
      workspace: shared-workspace  #與此yaml文件 spec.workspace.name 一致
    params:
    - name: url    #這個name 與 ClusterTask git-clone 中的 spec.params.name 一致,
                   #將來會把下面的value 回填到 ClusterTask 中進行執(zhí)行
      value: $(params.git-url)   #與此yaml spec.params.name 
    - name: subdirectory
      value: ""
    - name: deleteExisting
      value: "true"
    - name: revision
      value: $(params.git-revision)
  - name: build-image
    taskRef:
      name: buildah
      kind: ClusterTask
    params:
    - name: TLSVERIFY
      value: "false"
    - name: IMAGE
      value: $(params.IMAGE)
    workspaces:
    - name: source    
      workspace: shared-workspace
    runAfter:    # 啟動順序
    - fetch-repository
  - name: apply-manifests
    taskRef:
      name: apply-manifests   #指定使用的task,沒寫ClusterTask就說明是當前project的task
    workspaces:
    - name: source
      workspace: shared-workspace
    runAfter:
    - build-image
  - name: update-deployment
    taskRef:
      name: update-deployment
    params:
    - name: deployment
      value: $(params.deployment-name)
    - name: IMAGE
      value: $(params.IMAGE)
    runAfter:
    - apply-manifests

Pipeline - spec.params.name 自定義,此name 輸入的 value 將傳輸?shù)?Pipeline - spec.tasks.params.value
Pipeline - spec.tasks.params.name 與 ClusterTask(Task)中 spec.params.name 一致,Pipeline - spec.tasks.params.value 內容傳輸?shù)?ClusterTask(Task) 中spec.params.name 的 value。

此處是順序比較簡單,4個 task 一個接一個執(zhí)行。

在 Web console - Pipelines 菜單可以可視化的查看與執(zhí)行 pipeline。
可視化菜單功能為 Tech preview,stable 版本還看不到。

pipeline-build-and-deploy.png

3.4 執(zhí)行 pipeline

上面是組裝了一個 pipeline,包含了4個步驟,包括 clone代碼-制作精細-發(fā)布應用,但是使用的代碼庫地址,應用名稱還未定義,需要在執(zhí)行 pipeline 時候自定義。

在 pipeline 詳情頁,點 Action - Start,會彈出輸入?yún)?shù)頁面,此處展示的內容就是 04_pipeline.yaml 中 spec.params 部分。
deployment-name: 輸入發(fā)布應用的名稱,自定義
git-url: git 代碼庫的地址 https://github.com/openshift/pipelines-vote-api.git
git-version: 分支名稱
IMAGE: 制作鏡像使用的名稱,image-registry.openshift-image-registry.svc:5000/pipelines-tutorial/vote-api 依次是內部倉庫地址,project-name,deployment-name
shared-workspace: 選擇上面創(chuàng)建的 source-pvc

pipeline-build-and-deploy-run1.png

pipeline 執(zhí)行過程,每個 task 都會通過 image 運行 pod 來執(zhí)行,如果異常可以通過頁面或者命令查看 taskrun 狀態(tài)或者查看在運行pod的event 與log

第二步的日志,根據(jù) git庫目錄下的 Dockerfile 制作鏡像,并推送到內部倉庫


pipeline-build-and-deploy-run2.png

第三步的日志,導入 git庫 k8s目錄的 deployment.yaml 和 service.yaml

pipeline-build-and-deploy-run3.png

第四步,把 deployment 的 image, 更新成第二步生成的image

除了通過頁面,也可以通過 tkn 命令執(zhí)行 pipeline ,會提示依次輸入內容

[root@bastion 01_pipeline]# tkn pipeline list
NAME               AGE              LAST RUN                  STARTED          DURATION   STATUS
build-and-deploy   51 minutes ago   build-and-deploy-54nl08   12 minutes ago   ---        Running
[root@bastion 01_pipeline]# tkn pipeline start build-and-deploy 
? Value for param `deployment-name` of type `string`? 

我這是在線環(huán)境,離線環(huán)境會遇到鏡像拉取的問題,參照官網(wǎng)。
https://access.redhat.com/documentation/zh-cn/openshift_container_platform/4.7/html/cicd/creating-applications-with-cicd-pipelines#op-mirroring-images-to-run-pipelines-in-restricted-environment_creating-applications-with-cicd-pipelines

過程中可以通過 oc get 及 tkn taskrun list 等查看狀態(tài)。

[root@bastion 01_pipeline]# oc get pipelineruns.tekton.dev 
NAME                      SUCCEEDED   REASON    STARTTIME   COMPLETIONTIME
build-and-deploy-extr7w   Unknown     Running   3m12s       
[root@bastion 01_pipeline]# oc get taskruns.tekton.dev 
NAME                                             SUCCEEDED   REASON      STARTTIME   COMPLETIONTIME
build-and-deploy-extr7w-build-image-vr96v        Unknown     Running     61s         
build-and-deploy-extr7w-fetch-repository-7kpxj   True        Succeeded   3m19s       61s
[root@bastion 01_pipeline]# oc get pod
NAME                                                       READY   STATUS      RESTARTS   AGE
build-and-deploy-extr7w-build-image-vr96v-pod-hljx8        3/3     Running     0          63s
build-and-deploy-extr7w-fetch-repository-7kpxj-pod-dbjsh   0/1     Completed   0          3m21s

完成后,vote-api 后端服務發(fā)布完成

[root@bastion 01_pipeline]# oc get pod
NAME                                                        READY   STATUS      RESTARTS   AGE
build-and-deploy-47rwhl-apply-manifests-z9mv6-pod-sq5rg     0/1     Completed   0          8m39s
build-and-deploy-47rwhl-build-image-h8kbl-pod-ztwc2         0/3     Completed   0          11m
build-and-deploy-47rwhl-fetch-repository-c5gjx-pod-f95w8    0/1     Completed   0          11m
build-and-deploy-47rwhl-update-deployment-ztzm5-pod-zm4vl   0/1     Completed   0          7m31s
vote-api-c458c6d4f-52xm2                                    1/1     Running     0          7m26s
[root@bastion 01_pipeline]# tkn taskrun list
NAME                                              STARTED          DURATION     STATUS
build-and-deploy-47rwhl-update-deployment-ztzm5   13 minutes ago   4 seconds    Succeeded
build-and-deploy-47rwhl-apply-manifests-z9mv6     14 minutes ago   1 minute     Succeeded
build-and-deploy-47rwhl-build-image-h8kbl         16 minutes ago   2 minutes    Succeeded
build-and-deploy-47rwhl-fetch-repository-c5gjx    17 minutes ago   13 seconds   Succeeded

接著按照同樣方法發(fā)布前端 vote-ui ,這次用 tkn 命令發(fā)布

tkn pipeline start build-and-deploy \
    -w name=shared-workspace,volumeClaimTemplateFile=https://raw.githubusercontent.com/openshift/pipelines-tutorial/pipelines-1.3/01_pipeline/03_persistent_volume_claim.yaml \
    -p deployment-name=vote-ui \
    -p git-url=https://github.com/openshift-pipelines/vote-ui.git \
    -p IMAGE=image-registry.openshift-image-registry.svc:5000/pipelines-tutorial/vote-ui

volumeClaimTemplateFile 參數(shù)會創(chuàng)建一個隨意名稱的pvc,和后端使用的不同,如果圖形界面去 start vote-ui pipeline,也要提前手動創(chuàng)建不同的pvc。

查看前端域名,訪問測試

[root@bastion 01_pipeline]# oc get route vote-ui --template='http://{{.spec.host}}'

http://vote-ui-pipelines-tutorial.apps.ocp4.example.com

vote-ui.png

其他 tkn 命令

# 查看已運行的 pipeline 
[root@bastion 01_pipeline]# tkn pipelinerun list
NAME                         STARTED          DURATION    STATUS
build-and-deploy-run-56kzg   15 minutes ago   5 minutes   Succeeded
build-and-deploy-47rwhl      5 hours ago      4 minutes   Succeeded

# 持續(xù)跟蹤運行日志
[root@bastion 01_pipeline]# tkn pipelinerun logs build-and-deploy-run-56kzg -f

# 將最后運行的pipelinerun 再運行一次
tkn pipeline start build-and-deploy --last

也可以通過頁面,對 pipelinerun 選擇 Action -> rerun,再次運行。

總結

1.通過 operator 自帶的 clustertask及自編task 組成 pipeline 模板,將常用參數(shù)提取為輸入項。pipeline配合輸入?yún)?shù)形成 pipelinerun 執(zhí)行流水線工作。
每個task類似jenkins的stage。

2.每個task 都會用到獨立的鏡像,在離線環(huán)境需要提前準備好鏡像,或通過 image mirror 方式。

3.demo中應用發(fā)布所使用到的yaml,存放在了git,便于管理。其實也可以通過 task 傳遞,可視化效果更好一些,就是參數(shù)會略顯繁雜。

4.當前在頁面通過start pipeline時候,pipelinerun的名稱不能自定義,不利于區(qū)分pipelinerun屬于哪個應用。

4. FAQ

4.1 task build-image 在 STEP-BUILD 失敗,workspace目錄找不到代碼

啟動pipeline 的時候,在Workspace->shared-workspace 沒有指定存儲。
需要指定已有pvc存儲,因為每個task都是獨立的pod。第一步拉取的代碼的pod完成后,在第二步 build-image 的pod時候無法獲取到。需要通過存儲流轉。

4.2 task build-image 在 STEP-PUSH fail,denied: requested access to the resource is denied

step-push
+ buildah --storage-driver=vfs push --tls-verify=false --digestfile /workspace/source/image-digest vote-api docker://vote-api
Getting image source signatures
Getting image source signatures
Getting image source signatures
Getting image source signatures
error copying layers and metadata from "containers-storage:[vfs@/var/lib/containers/storage+/var/run/containers/storage]localhost/vote-api:latest" to "docker://vote-api:latest": Error trying to reuse blob sha256:bd3ef8fb78ac28071075811b988706f81ea7f2be36c875592e87287921209862 at destination: Error checking whether a blob sha256:bd3ef8fb78ac28071075811b988706f81ea7f2be36c875592e87287921209862 exists in docker.io/library/vote-api: errors:
denied: requested access to the resource is denied
error parsing HTTP 401 response body: unexpected end of JSON input: ""

level=error msg="exit status 125"

step-digest-to-results
2021/04/14 06:00:23 Skipping step because a previous step failed

這是啟動 pipeline 時候 IMAGE name 寫的不對,如果IMAGE 只寫 vote-api 就會出現(xiàn)上面的鏡像,鏡像就會默認推送到docker.io 當然會沒有權限。
把IMAGE 寫完整即可 image-registry.openshift-image-registry.svc:5000/pipelines-tutorial/vote-api

5. 參考鏈接

https://access.redhat.com/documentation/zh-cn/openshift_container_platform/4.7/html/cicd/creating-applications-with-cicd-pipelines

https://blog.csdn.net/weixin_43902588/article/details/103269747

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容