Tekton 的前身是 Knative 项目的 build-pipeline 项目,这个项目是为了给 build 模块增加 pipeline 的功能,但是随着不同的功能加入到 Knative build 模块中,build 模块越来越变得像一个通用的 CI/CD 系统,于是,索性将 build-pipeline 剥离出 Knative,就变成了现在的 Tekton,而 Tekton 也从此致力于提供全功能、标准化的云原生 CI/CD 解决方案。
Tekton 是一个功能强大且灵活的 Kubernetes 原生开源框架,用于创建持续集成和交付(CI/CD)系统。通过抽象底层实现细节,用户可以跨多云平台和本地系统进行构建、测试和部署。
一句话总结:Tekton 是云原生的 CI/CD 框架,是云原生的的 CI/CD 解决方案。
Tekton 由一些列组件组成:
Tekton Pipelines
:是 Tekton 的基础,它定义了一组 Kubernetes CRD 作为构建块,我们可以使用这些对象来组装 CI/CD 流水线。Tekton Triggers
:允许我们根据事件来实例化流水线,例如,可以我们在每次将 PR/MR 合并到 GitHub/GitLab 仓库的时候触发流水线实例和构建工作。Tekton CLI
:提供了一个名为 tkn
的命令行界面,它构建在 Kubernetes CLI 之上,运行和 Tekton 进行交互。Tekton Dashboard
:是 Tekton Pipelines
的基于 Web 的一个图形界面,可以线上有关流水线执行的相关信息。Tekton Catalog
:是一个由社区贡献的高质量 Tekton 构建块(任务、流水线等)存储库,可以直接在我们自己的流水线中使用这些构建块。用于访问 Tekton Catalog
的 Web 图形界面工具叫Tekton Hub
。Tekton Operator
:是一个 Kubernetes Operator,可以让我们在 Kubernetes 集群上安装、更新、删除 Tekton 项目。参考链接:https://tekton.dev/docs/concepts/concept-model/
Tekton Pipeline中有5类对象,核心理念是通过定义yaml定义构建过程。
# install
kubectl apply --filename https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml
# moinitor
kubectl get pods --namespace tekton-pipelines --watch
# install
kubectl apply --filename https://storage.googleapis.com/tekton-releases/dashboard/latest/release-full.yaml
# monitor
kubectl port-forward -n tekton-pipelines service/tekton-dashboard 9097:9097
# expose port
kubectl port-forward -n tekton-pipelines service/tekton-dashboard 9097:9097
pipeline和task的关系
pipeline和pipelinerun的关系
Task 就是一个任务执行模板,之所以说 Task 是一个模板是因为 task 定义中可以包含变量,Task 在真正执行的时候需要给定变量的具体值。
如果把 Tekton 的 Task 有点儿类似于定义一个函数,Task 通过 inputs.params 定义需要哪些入参,并且每一个入参还可以指定默认值。Task 的 steps 字段表示当前 task 是有哪些步骤组成的,每一个步骤具体就是基于镜像启动一个 container 执行一些操作,container 的启动参数可以通过 task 的入参使用模板语法进行配置。
Demo1:test-task.yaml
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: test
spec:
params:
- name: username
type: string
default: "hello,cs"
steps:
- name: echo
image: alpine
script: |
#!/bin/sh
echo "$(params.username)"
Demo2:task-git.yaml
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: clone-code-test
description: This Task will clone code and search file
spec:
steps:
- name: clone-code-test
image: alpine/git
script: |
#!/bin/sh
echo "Hello World"
git clone https://gitlab.com/kaixuan.wang/app.git
cd app
cat README.md
也可以对demo2进行调整如下:
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: clone-code-test
description: This Task will clone code and search file
spec:
params:
- name: repo-url
type: string
default: "https://gitlab.com/kaixuan.wang/gitops.git"
steps:
- name: clone-code-test
image: alpine/git
script: |
#!/bin/sh
echo "Hello World"
git clone $(params.repo-url)
ls -l gitops
# params:
# - name: repo-url
# value: [email protected]:cs-test-group1/kxwang/test.git
Task 定义好以后是不能执行的,就像一个函数定义好以后需要调用才能执行一样。所以需要再定义一个 TaskRun 去执行 Task。
TaskRun 主要是负责设置 Task 需要的参数,并通过 taskRef 字段引用要执行的 Task。
Demo1:
test-task-run.yaml(赋值username)
apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
name: test-task-run #taskrun name
spec:
taskRef:
name: test
params:
- name: username
value: "Tekton"
test-task-2.yaml(不赋值)
apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
name: test-task-run-1 #taskrun name
spec:
taskRef:
name: test
通过tkn工具查看
然而在实际使用过程中,我们一般很少使用TaskRun,因为它只能给一个Task 传参,Tekton提供了给多个Task同时传参的解决方案Pipeline和PipelineRun。
Demo2:taskrun-git.yaml
apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
generateName: taskrun-git- # name: taskrun-git
spec:
taskRef:
name: clone-code
apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
generateName: taskrun-git-
spec:
taskRef:
name: clone-code
# params:
# - name: repo-url
# value: "https://gitlab.com/test-ce/group/123.git"
一个 TaskRun 只能执行一个 Task,当需要编排多个 Task 的时候就需要用到 Pipeline。
Pipeline 是一个编排 Task 的模板。
Tekton controller 在解析 CRD 的时候会解析 Task 的顺序,然后根据 runAfter 设置生成的依次树依次去执行。Pipeline 在编排 Task 的时候需要给每一个 Task 传入必须的参数,这些参数的值可以来自 Pipeline 自身的 params 设置。下面是一个Demo:
pipeline.yaml
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: test-pipeline
spec:
params:
- name: username
type: string
tasks:
- name: test-1
taskRef:
name: test
params:
- name: username
value: $(params.username)
# - name: clone-code-test
# runAfter:
# - test-1
# taskRef:
# name: clone-code-test
和 Task 一样 Pipeline 定义完成以后也是不能直接执行的,需要 PipelineRun 才能执行 Pipeline。PipelineRun 的主要作用是给 Pipeline 传入必要的入参,并执行 Pipeline。
pipelinerun.yaml
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
generateName: test-pipeline-run-
spec:
pipelineRef:
name: test-pipeline
params:
- name: username
value: "Tekton"
安装git-clone task
kubectl apply -f https://raw.githubusercontent.com/tektoncd/catalog/main/task/git-clone/0.9/git-clone.yaml
或者自己创建一个git-clone task
cat task.yaml
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: git-clone
spec:
workspaces:
- name: output
- name: ssh-directory
params:
- name: url
type: string
- name: revision
type: string
default: ""
steps:
- name: clone
image: "gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/git-init:v0.40.2"
env:
- name: PARAM_URL
value: $(params.url)
- name: PARAM_REVISION
value: $(params.revision)
- name: WORKSPACE_OUTPUT_PATH
value: $(workspaces.output.path)
- name: WORKSPACE_SSH_PATH
value: $(workspaces.ssh-directory.path)
script: |
#!/usr/bin/env sh
mkdir $HOME/.ssh
cp $WORKSPACE_SSH_PATH/* $HOME/.ssh/
chmod 400 $HOME/.ssh/*
set -eu
CHECKOUT_DIR="${WORKSPACE_OUTPUT_PATH}"
/ko-app/git-init \
-url="${PARAM_URL}" \
-revision="${PARAM_REVISION}" \
-path="${CHECKOUT_DIR}"
cd "${CHECKOUT_DIR}"
EXIT_CODE="$?"
if [ "${EXIT_CODE}" != 0 ] ; then
exit "${EXIT_CODE}"
fi
cat show-readme.yaml
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: show-readme
spec:
workspaces:
- name: source
steps:
- name: show-readme
image: alpine:latest
script: |
cat $(workspaces.source.path)/README.md
cat pipeline.yaml
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: cat-branch-readme
spec:
params:
- name: repo-url
type: string
- name: branch-name
type: string
workspaces:
- name: shared-data
- name: git-credentials
tasks:
- name: fetch-repo
taskRef:
name: git-clone
workspaces:
- name: output
workspace: shared-data
- name: ssh-directory
workspace: git-credentials
params:
- name: url
value: $(params.repo-url)
- name: revision
value: $(params.branch-name)
- name: show-readme
runAfter: ["fetch-repo"]
taskRef:
name: show-readme
workspaces:
- name: source
workspace: shared-data
secrets-ssh.yaml
apiVersion: v1
kind: Secret
metadata:
name: gitlab-ssh
annotations:
tekton.dev/git-0: jihulab.com #不需要指定协议,如果带http://或者https://会报错
type: kubernetes.io/ssh-auth
data:
ssh-privatekey:
known_hosts:
创建secrets - username
secrets-basic.yaml
apiVersion: v1
kind: Secret
metadata:
name: gitlab-auth
annotations:
tekton.dev/git-0: https://jihulab.com #需要指定协议,如果不带会报错
type: kubernetes.io/basic-auth
stringData:
username: [email protected]
password: xxxxxxx
gitlab-sa.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: gitlab-sa
secrets:
- name: gitlab-auth
- name: gitlab-ssh
cat pipelinerun.yaml
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
generateName: git-clone-checking-out-a-branch
spec:
serviceAccountName: gitlab-sa
pipelineRef:
name: cat-branch-readme
podTemplate:
securityContext:
fsGroup: 65532
workspaces:
- name: shared-data
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 256Mi
volumeMode: Filesystem
- name: git-credentials
secret:
secretName: gitlab-ssh
params:
- name: repo-url
value: [email protected]:cs-test-group1/kxwang/test.git
- name: branch-name
value: master
同上
task-build.yaml
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: build-1
spec:
workspaces:
- name: source # 名称
params:
- name: skipunit
type: string
default: "true"
steps:
- name: build
image: maven:3-jdk-8
workingDir: $(workspaces.source.path)
script: |
#/usr/bin/env sh
mvn clean package -Dmaven.test.skip=$(params.skipunit)
volumeMounts:
- name: cache
mountPath: /workspace/.m2
subPath: m2-cache
- name: cache
mountPath: /workspace/.cache
subPath: m2-cache
volumes:
- name: cache
emptyDir: {}
task-package.yaml
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: package-1
spec:
workspaces:
- name: source # 名称
params:
- name: image_dest
type: string
- name: image_tag
type: string
default: "latest"
- name: DockerfilePath
type: string
default: Dockerfile
- name: Context
type: string
default: .
steps:
- name: package
image: docker:stable
workingDir: $(workspaces.source.path)
script: |
#/usr/bin/env sh
docker login registry.ap-southeast-1.aliyuncs.com
docker build -t $(params.image_dest):$(params.image_tag) -f $(params.DockerfilePath) $(params.Context)
docker push $(params.image_dest):$(params.image_tag)
volumeMounts:
- name: dockersorck
mountPath: /var/run/docker.sock
volumes:
- name: dockersorck
hostPath:
path: /var/run/docker.sock
1、config.json(~/.docker/config.json)
{
"auths": {
"registry.ap-southeast-1.aliyuncs.com": {
"auth": "d2t4XzA0MjJAMTYzLmNvbTp3a3g3MzE1MDg4MDY="
}
}
}
2、secret-docker.yaml
apiVersion: v1
kind: Secret
metadata:
name: docker-credentials
annotations:
tekton.dev/docker-0: https://registry.ap-southeast-1.aliyuncs.com
type: kubernetes.io/basic-auth
stringData:
username: [email protected]
password: 123456
gitlab-sa.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: gitlab-sa
secrets:
- name: gitlab-auth
- name: gitlab-ssh
- name: docker-credentials
pipeline.yaml
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: clone-build-push-1
spec:
description: |
This pipeline clones a git repo, builds a Docker image with Kaniko and
pushes it to a registry
params:
- name: repo-url
type: string
- name: image_dest
type: string
- name: image_tag
type: string
workspaces:
- name: shared-data
tasks:
# 拉取代码
- name: fetch-source
taskRef:
name: git-clone
workspaces:
- name: output
workspace: shared-data
params:
- name: url
value: $(params.repo-url)
# 打包
- name: build-code
taskRef:
name: build-1
workspaces:
- name: source
workspace: shared-data
runAfter:
- fetch-source
# 构建并推送镜像
- name: package-image
runAfter: ["build-code"]
taskRef:
name: package-1
workspaces:
- name: source
workspace: shared-data
params:
- name: image_dest
value: $(params.image_dest)
- name: image_tag
value: $(params.image_tag)
pipelinerun.yaml
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
generateName: clone-build-push-run-
spec:
serviceAccountName: gitlab-sa
pipelineRef:
name: clone-build-push-1
podTemplate:
securityContext:
fsGroup: 65532
workspaces:
- name: shared-data
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 128Mi
params:
- name: repo-url
value: https://jihulab.com/cs-test-group1/kxwang/test.git
- name: image_dest
value: registry.ap-southeast-1.aliyuncs.com/my_image_repo/demo
- name: image_tag
value: v2