日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
一篇帶給你Tekton系列之理論篇

一篇帶給你Tekton系列之理論篇

作者:?jiǎn)炭?2022-03-08 08:32:43
云計(jì)算
云原生 Tekton是開源的云原生CI/CD項(xiàng)目,是基于Kubernetes CRD來定義Pipeline,功能強(qiáng)大并且很容易擴(kuò)展。

上一篇文章我們介紹了Tekton的安裝并且做了簡(jiǎn)單的測(cè)試,但是我們并不知其所以然,而這篇文章主要帶大家來了解以及學(xué)習(xí)所以然。

Tekton是開源的云原生CI/CD項(xiàng)目,是基于Kubernetes CRD來定義Pipeline,功能強(qiáng)大并且很容易擴(kuò)展。

在上篇文章中,我們安裝完Tekton之后,可以看到安裝的CRD如下:

# kubectl get crd | grep tekton
clustertasks.tekton.dev 2022-02-28T06:15:38Z
conditions.tekton.dev 2022-02-28T06:15:38Z
extensions.dashboard.tekton.dev 2022-02-28T06:18:40Z
pipelineresources.tekton.dev 2022-02-28T06:15:38Z
pipelineruns.tekton.dev 2022-02-28T06:15:38Z
pipelines.tekton.dev 2022-02-28T06:15:38Z
runs.tekton.dev 2022-02-28T06:15:38Z
taskruns.tekton.dev 2022-02-28T06:15:38Z
tasks.tekton.dev 2022-02-28T06:15:38Z

其中Task、TaskRun、Pipeline、PipelineRun、PipelineResource、Condition作為其核心CRD,這里主要介紹它們。

  • Task:定義構(gòu)建任務(wù),它由一系列有序steps構(gòu)成。每個(gè)step可以定義輸入和輸出,且可以將上一個(gè)step的輸出作為下一個(gè)step的輸入。每個(gè)step都會(huì)由一個(gè)container來執(zhí)行。
  • TaskRun:Task用于定義具體要做的事情,并不會(huì)真正的運(yùn)行,而TaskRun就是真正的執(zhí)行者,并且會(huì)提供執(zhí)行所需需要的參數(shù),一個(gè)TaskRun就是一個(gè)Pod。
  • Pipeline:顧名思義就是流水線,它由一系列Tasks組成。就像Task中的step一樣,上一個(gè)Task的輸出可以作為下一個(gè)Task的輸入。
  • PipelineRun:Pipeline的實(shí)際執(zhí)行,創(chuàng)建后會(huì)創(chuàng)建Pod來執(zhí)行Task,一個(gè)PipelineRun中有多個(gè)Task。
  • PipelineResource:主要用于定義Pipeline的資源,常見的如Git地址、Docker鏡像等。
  • Condition:它主要是在Pipeline中用于判斷的,Task的執(zhí)行與否通過Condition的判斷結(jié)果來決定。

Tips:PipelineResource和Condition都會(huì)被廢棄。但是在低版本中還是會(huì)繼續(xù)使用,所以這里會(huì)簡(jiǎn)單介紹一下。

如上圖所示,一個(gè)Pipeline是由許多Task組成,每個(gè)Task又由許多step組成。在實(shí)際工作中,我們可以靈活定義各種Task,然后根據(jù)需要任意組合Task形成各類Pipeline來完成不同的需求。

實(shí)現(xiàn)原理

上面大致介紹了Tekton的主要CRD以及它們所具備的能力,那么,Tekton是如何把這些CRD串聯(lián)起來的呢?

我們?cè)诎惭b完Tekton后,可以看到如下兩個(gè)Pod。

# kubectl get po -n tekton-pipelines 
NAME READY STATUS RESTARTS AGE
tekton-pipelines-controller-75c456df85-qxvq2 1/1 Running 0 2d22h
tekton-pipelines-webhook-5bc8d6b7c4-w6pdn 1/1 Running 0 2d22h

一個(gè)是tekton-pipelines-controller,一個(gè)是tekton-pipelines-webhook。其實(shí)從命名方式就可以看出,一個(gè)是tekton的控制器,用于監(jiān)聽CRD對(duì)象,一個(gè)是tekton的網(wǎng)絡(luò)鉤子,用于做CRD校驗(yàn),其中tekton-pipelines-controller就是Tekton的核心實(shí)現(xiàn)Pod。

tekton-pipelines-controller在啟動(dòng)的時(shí)候會(huì)初始化兩個(gè)Controller:PipelineRunController以及TaskRunController。我們可以通過main.go(cmd/controller/main.go)看到,如下:

......
go func() {
// start the web server on port and accept requests
log.Printf("Readiness and health check server listening on port %s", port)
log.Fatal(http.ListenAndServe(":"+port, mux))
}()
ctx = filteredinformerfactory.WithSelectors(ctx, v1beta1.ManagedByLabelKey)
sharedmain.MainWithConfig(ctx, ControllerLogKey, cfg,
taskrun.NewController(opts, clock.RealClock{}),
pipelinerun.NewController(opts, clock.RealClock{}),
)
}

如上所示會(huì)通過taskrun.NewController和pipelinerun.NewController來進(jìn)行初始化,然后通過sharedmain.MainWithConfig調(diào)用controller.StartAll來啟動(dòng)所有Controller。

PipelineRunController通過監(jiān)聽PipelineRun對(duì)象的變化,然后從PipelineSpec中獲取Task列表并構(gòu)建成一張有向無環(huán)圖(DAG),然后通過遍歷DAG找到可被調(diào)度的Task節(jié)點(diǎn)創(chuàng)建對(duì)應(yīng)的TaskRun對(duì)象。具體可以通過(pkg/reconciler/pipelinerun/pipelinerun.go)中的reconcile方法進(jìn)行查看。

TaskRunController監(jiān)聽到TaskRun對(duì)象的變化,就會(huì)將TaskRun中的Task轉(zhuǎn)化為Pod,由Kubernetes調(diào)度執(zhí)行??梢酝ㄟ^(pkg/reconciler/taskrun/taskrun.go)中的reconcile方法進(jìn)行查看。

利用 Kubernetes 的 OwnerReference 機(jī)制, PipelineRun Own TaskRun、TaskRun Own Pod、Pod 狀態(tài)變更時(shí),觸發(fā) TaskRun 的 reconcile 邏輯, TaskRun 狀態(tài)變更時(shí)觸發(fā) PipelineRun 的 reconcile 邏輯。

當(dāng)TaskRun的Pod變成running過后,就會(huì)通知第一個(gè)step容器來執(zhí)行(通過一個(gè)名叫entrypoint的二進(jìn)制文件來完成)。

當(dāng)然這個(gè)entrypoint二進(jìn)制文件也有運(yùn)行條件的,當(dāng)且僅當(dāng)pipeline的狀態(tài)的annotation通過Kubernetes Download Api以文件的方式注入到step container后才會(huì)啟動(dòng)提供的命令。這句話是不是有點(diǎn)繞?按照官方的說法是:Tekton Pipeline是通過Kubernetes Annotation來跟蹤Pipeline的狀態(tài),而且這些annotations會(huì)通過Kubernetes Download Api以文件的方式注入到Step Container中,Step Container中的entrypoint會(huì)監(jiān)聽著這些文件,當(dāng)特定的annotation以文件的形式注入進(jìn)來過后,entrypoint才會(huì)去執(zhí)行命令。比方說,一個(gè)Task中有兩個(gè)step,第二個(gè)step中的entrypoint會(huì)等待,直到annotation以文件的形式告訴它第一個(gè)step已經(jīng)完成。

我們來梳理一下整體的流程,如下:

  1. 用戶通過client創(chuàng)建PipelineRun資源。
  2. PipelineRunController監(jiān)聽到PipelineRun資源,就把里面的Task組成DAG(有向無環(huán)圖),遍歷DAG得到Task,并創(chuàng)建TaskRun。
  3. TaskRunController監(jiān)聽到TaskRun資源,就會(huì)通過Kubernetes將Task轉(zhuǎn)化為Pod啟動(dòng)(Task受Condition條件控制)。
  4. Pod啟動(dòng)后會(huì)運(yùn)行Task中的每一個(gè)Step完成具體的指令。
  5. 運(yùn)行完成后Pod會(huì)變成Completed狀態(tài),同時(shí)也會(huì)更新PipelineRun的狀態(tài)。

到此一個(gè)Pipeline就運(yùn)行完成了。

PipelineResources

這里將PipelintResource提到最前面來說明,主要是后面的操作有需要它的地方。

PipelineResource用于定義資源的信息,雖然會(huì)被棄用,但是在舊版本中依然會(huì)使用。

PipelineResource的定義很簡(jiǎn)單,如下:

apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
name: hello-word-resource
spec:
type: git
params:
- name: url
value: https://gitee.com/coolops/springboot-helloworld.git

在TaskRun中就可以引用hello-word-resource資源得到具體的git地址。

TasksTask就是一個(gè)任務(wù)模板,Task的定義中可以包含變量,在真正執(zhí)行的時(shí)候需要給變量賦值。

Task

通過input.params定義入?yún)?,每一個(gè)入?yún)⑦€可以指定默認(rèn)值,在每一個(gè)step中可以$(params.A)引用變量。steps字段表示當(dāng)前Task有哪些步驟組成,每一個(gè)step都會(huì)通過定義一個(gè)container來執(zhí)行具體的操作。

Task主要包括以下元素:

  • Parameters:用于定義params參數(shù)。
  • Resources:定義輸入、輸出資源,老版本由PipelineResources定義,不過在新版本中PipelineResources將被棄用。
  • Steps:定義具體的操作步驟。
  • Workspaces:定義工作區(qū),Task可以共享工作區(qū)。
  • Results:定義結(jié)果輸出,可以用于展示或者給另外的Task使用。

Task的定義如下:

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: maven-build
spec:
resources:
inputs:
- name: repo
type: git
steps:
- name: build
image: maven:3.3-jdk-8
command:
- mvn clean package
workingDir: /workspace/repo

再定義一個(gè)構(gòu)建Dokcer鏡像并推送到Hub的Task,如下:

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: build-and-push-image
spec:
params:
- name: pathToDockerfile
type: string
default: /workspace/repo/Dockerfile
description: define Dockerfile path
- name: pathToContext
type: string
default: /workspace/repo
description: Docker deamon build context
- name: imageRepo
type: string
default: registry.cn-hangzhou.aliyuncs.com
description: docker image repo
resources:
inputs:
- name: repo
type: git
outputs:
- name: builtImage
type: image
steps:
- name: build-image
image: docker:stable
scripts: |
#!/usr/bin/env sh
docker login $(params.imageRepo)
docker build -t $(resources.outputs.builtImage.url) -f $(params.pathToDockerfile) $(params.pathToContext)
docker push $(resources.outputs.builtImage.url)
volumeMounts:
- name: dockersock
mountPath: /var/run/docker.sock
volumes:
- name: dockersock
hostPath:
path: /var/run/docker.sock

如上,我們可以通過直接編寫shell腳本的方式來實(shí)現(xiàn)需求,而且使用docker構(gòu)建鏡像需要sock文件,可以像pod掛載那樣掛載需要的東西。

step還有其他的配置,比如為某個(gè)step設(shè)置超時(shí)時(shí)間,如下:

steps:
- name: sleep-then-timeout
image: ubuntu
script: |
#!/usr/bin/env bash
echo "I am supposed to sleep for 60 seconds!"
sleep 60
timeout: 5s

更多的操作可以通過(https://tekton.dev/docs/pipelines/tasks/)進(jìn)行學(xué)習(xí)研究。

TaskRuns

Task在定義好之后,并不會(huì)被執(zhí)行,就像我們定義了一個(gè)函數(shù),如果沒被調(diào)用的話,這個(gè)函數(shù)就不會(huì)被執(zhí)行一樣。而TaskRun就可以就好似調(diào)用方,用它來執(zhí)行Task里的具體內(nèi)容。

TaskRun會(huì)設(shè)置Task需要的參數(shù),并通過taskRef字段來引用Task,如下:

apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
name: build-and-push-image
spec:
params:
- name: imageRepo
value: registry.cn-zhangjiakou.aliyuncs.com
taskRef:
name: build-and-push-image # 關(guān)聯(lián)定義好的task
resources:
inputs:
- name: repo # 指定輸入的倉(cāng)庫(kù)資源
resourceRef:
name: hello-word-resource
outputs: # 指定輸出的鏡像資源
- name: builtImage
resourceRef:
name: hello-word-image

通過如上的定義,就將build-and-push-image的Task進(jìn)行關(guān)聯(lián),并且通過resources定義Task需要的sources參數(shù),然后通過parms來定義參數(shù),該參數(shù)會(huì)替代掉Task中的默認(rèn)參數(shù)。

在實(shí)際中,基本不會(huì)去定義TaskRun,除非自己去測(cè)試某個(gè)Task是否正常。

Pipelines

一個(gè)TaskRun只能執(zhí)行一個(gè)Task,當(dāng)我們需要同時(shí)編排許多Task的時(shí)候,就需要使用Pipeline了,就像使用Jenkinsfile來編排不同的任務(wù)一樣。

Pipeline是一個(gè)編排Task的模板,通過spec.params來聲明執(zhí)行時(shí)需要的入?yún)?,通過spec.tasks來編排具體的task,除此之外還可以通過runAfter來控制Task的先后順序。

先定義一個(gè)簡(jiǎn)單的Pipeline,如下:

apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: build-and-push-image
spec:
resources:
- name: repo
type: git
- name: builtImage
type: image
tasks:
# 構(gòu)建并推送 Docker 鏡像
- name: build-and-push-image
taskRef:
name: build-and-push-image
resources:
inputs:
- name: repo # Task 輸入名稱
resource: repo # Pipeline 資源名稱
outputs:
- name: builtImage
resource: builtImage

上面定義的Pipeline關(guān)聯(lián)了build-and-push-image Task,該Task所需要的輸入輸出參數(shù),通過Pipeline的spec.resources定義,這里的spec.resources依然依賴PipelineResources中定義的具體資源。

上面提到過,如果要在Pipeline中控制Task順序,則要使用runAfter參數(shù),如下:

- name: test-app
taskRef:
name: make-test
resources:
inputs:
- name: workspace
resource: my-repo
- name: build-app
taskRef:
name: kaniko-build
runAfter:
- test-app
resources:
inputs:
- name: workspace
resource: my-repo

如上build-app的Task依賴test-app的Task。

除此之外,還可以將上個(gè)Task的輸出作為下一個(gè)Task的輸入,如下。

- name: build-app
taskRef:
name: build-push
resources:
outputs:
- name: image
resource: my-image
- name: deploy-app
taskRef:
name: deploy-kubectl
resources:
inputs:
- name: image
resource: my-image
from:
- build-app

如上通過from關(guān)鍵字來引入其他Task的輸出。

如果要在Pipeline中使用條件判斷,也可以像以下方式使用when關(guān)鍵字。

tasks:
- name: deploy-to-dev
when:
- input: "$(params.branch)"
operator: in
values: ["dev"]
taskRef:
name: deploy-to-dev
---
tasks:
- name: deploy-to-test
when:
- input: "$(params.branch)"
operator: in
values: ["test"]
taskRef:
name: deploy-to-test

注意:when和condition不能同時(shí)在一個(gè)Task中使用,不然會(huì)被認(rèn)定為無效。

還有一個(gè)關(guān)鍵字和when效果一樣,就是condition。

condition的作用就是用一些條件來保護(hù)Task,只有在滿足條件的情況下才會(huì)運(yùn)行Task。在Task運(yùn)行之前,會(huì)對(duì)所有的條件進(jìn)行判斷,只有全部條件成功,才會(huì)運(yùn)行Task,否則不會(huì)允許。

如下定義一個(gè)簡(jiǎn)單的條件語句。

tasks:
- name: deploy-if-branch-is-master
conditions:
- conditionRef: is-master-branch
params:
- name: branch-name
value: my-value
taskRef:
name: deploy

當(dāng)然條件約束僅針對(duì)當(dāng)前的Task,如果其他Task不受當(dāng)前Task影響,則不受約束。

更多的使用方式見(https://tekton.dev/docs/pipelines/pipelines/)。

PipelineRuns

Pipeline和Task一樣,單純的定義完并不會(huì)運(yùn)行,Pipeline需要借助PipelineRun來完成真正的執(zhí)行。

PipelineRun會(huì)自動(dòng)為Pipeline中定義的Task創(chuàng)建對(duì)應(yīng)的TaskRun。

下面定義一個(gè)簡(jiǎn)單的PipelineRun。

apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: build-and-push-image
spec:
pipelineRef:
name: build-and-push-image
resources:
- name: repo
resourceRef:
name: demo-git
- name: builtImage
resourceRef:
name: harbor-image

其中spec.pipelineRef用來關(guān)聯(lián)定義的Pipeline,spec.resources用來給Pipeline傳遞參數(shù)。

上面的repo和builtImage參數(shù)依然需要通過PipelineResources定義。不過在新版本,也可以通過resourceSpec來進(jìn)行定義,如下。

apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: build-and-push-image
spec:
pipelineRef:
name: build-and-push-image
resources:
- name: repo
resouorceSpec:
type: git
params:
- name: url
value: https://gitee.com/coolops/springboot-helloworld.git
- name: builtImage
resouorceSpec:
type: image
params:
- name: url
value: registry.cn-hangzhou.aliyuncs.com/coolops/helloworld:latest

Conditions

condition用于在Pipeline中進(jìn)行條件判斷,不過在新版本中會(huì)被廢棄,使用上面介紹的when替代,這里不再做多的介紹了。

鑒權(quán)管理

上面介紹了主要的CRD以及它們的使用方式,但是還有一種是需要我們關(guān)注的,比如代碼倉(cāng)庫(kù)的密碼怎么管理?鏡像倉(cāng)庫(kù)的密碼怎么管理?因?yàn)檫@些都是在實(shí)際工作中需要使用的。

Tekton通過在PipelineRun中指定ServiceAccount來實(shí)現(xiàn)。不過Tekton要求定義的每個(gè)Secret都需要指定對(duì)應(yīng)的annotation。目前支持的annotation有以下兩種:

  • Git:tekton.dev/git-**0:** https**:**//github.com。
  • Docker:tekton.dev/docker-**0:** https**:**//gcr.io。

目前這兩種分別支持以下類型。

Tekton到底是如何使用到這些secret的呢?

原來,為了使用這些Secret,Tekton在實(shí)例化Pod的時(shí)候就會(huì)執(zhí)行憑證初始化, Tekton會(huì)將具體的Secret進(jìn)行關(guān)聯(lián)并聚合到/tekton/creds目錄中,之后才會(huì)執(zhí)行具體的Task步驟。

下面我們具體操作一下,以鏡像倉(cāng)庫(kù)為例。

(1)創(chuàng)建secret:

apiVersion: v1
kind: Secret
metadata:
name: docker-registry-secret
annotations:
tekton.dev/docker-0: https://gcr.io # Described below
type: kubernetes.io/basic-auth
stringData:
username:
password:

其中tekton.dev/docker-0: [https://gcr.io](https://gcr.io)用來指定對(duì)應(yīng)的倉(cāng)庫(kù)地址。

(2)創(chuàng)建seviceaccount:

apiVersion: v1
kind: ServiceAccount
metadata:
name: docker-registry-sa
secrets:
- name: docker-registry-secret

(3)在PipelineRun中引用:

apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: demo-pipeline
namespace: default
spec:
serviceAccountName: docker-registry-sa
pipelineRef:
name: demo-pipeline

如果需要同時(shí)使用多個(gè)serviceaccount怎么辦呢?比如我們?cè)谝粭l完成的Pipeline中,在拉取代碼的時(shí)候會(huì)用到Git的賬戶,在推送鏡像的時(shí)候會(huì)用到鏡像倉(cāng)庫(kù)的賬戶。

這時(shí)候我們就不能用serviceAccountName了,而是需要使用serviceAccountNames。serviceAccountNames是一個(gè)List,可以指定Task關(guān)聯(lián)具體的serviceaccount,如下。

apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: demo-pipeline
namespace: default
spec:
serviceAccountNames:
- taskName: build-app
serviceAccountName: gitlab-sa
- taskName: push-image
serviceAccountName: docker-registry-sa
pipelineRef:
name: demo-pipeline

到這里基本的資源以及介紹完了,弄懂這篇文章,寫一個(gè)簡(jiǎn)單的Pipeline應(yīng)該不成問題,后續(xù)的文章會(huì)分享具體的實(shí)踐。


當(dāng)前名稱:一篇帶給你Tekton系列之理論篇
網(wǎng)頁鏈接:http://www.dlmjj.cn/article/dhjidjj.html