提到运维自动化,我们就不得不提起 Jenkins 这个工具,它是一个功能强大且灵活的持续集成工具,适用于各种规模的软件项目,并能够通过自动化和集成化的方式提高软件开发和测试的效率。
现在,你还在 Jenkins 上点点吗?
那就太 OUT 了!快来试试 Tekton 的灵活自动化吧。
Tekton是一个用于构建CI/CD(持续集成和持续交付)系统的云原生解决方案,也是一个强大的、灵活的开源框架,允许开发者构建、测试和发布应用。它由Tekton Pipelines(提供构建块)和支持组件(如Tekton CLI和Tekton Catalog)组成,是一个完整的生态系统。
Tekton在Kubernetes集群上作为扩展安装和运行,包含一组Kubernetes自定义资源,这些资源定义了可以为pipelines创建和重用的构建块。Tekton实体具有高度的可定制性、可重复使用性和可扩展性,使得用户可以根据需要灵活定义和扩展CI/CD流水线。
Tekton最初是Knative的子项目build-pipeline,主要用于给Knative的build模块增加pipeline功能。后来独立出来,成为一个通用的CI/CD工具,现在是Linux基金会项目CD基金会的一部分。
官网:https://tekton.dev/
/tekton/debug/scripts
和/tekton/debug/info/step-no
,方便开发者进行调试和问题定位。Tekton的主要组件包括:
最基本的四个概念:Task、TaskRun、Pipeline、PipelineRun。
Tekton 和 Jenkins 在多个方面存在显著的差异!
总的来说,Tekton和Jenkins各有其优势和应用场景。选择哪一个工具取决于团队的具体需求、技术栈以及运行环境。
在后面的介绍中会给大家提供一些建议供实际参考使用。
Tekton 是基于 Kubernetes 的,因此需要一个运行正常的 K8s 环境。
访问 Tekton 的官方文档或 GitHub 仓库(https://github.com/tektoncd/pipeline#required-kubernetes-version),选择与你的 K8s 集群版本相匹配的 Tekton 版本。
版本不匹配可能会导致部署失败,出现如“Version check failed, kubernetes version xxx is not compatible”的错误日志。
由于国内的网络原因,无法正常访问 gcr.io 上面的镜像,所以需要将需要的镜像文件下载下来,放到自己的镜像仓库中。
访问 Tekton 的官方存储库,下载用于 Kubernetes 环境部署的 yaml 文件。可以从 https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml 下载最新的release.yaml文件。
#Tekton controller
wget https://storage.googleapis.com/tekton-releases/pipeline/previous/v0.32.3/release.yaml -O tekton-pipeline-release.yaml
#Tekton Dashboard
wget https://github.com/tektoncd/dashboard/releases/download/v0.25.0/tekton-dashboard-release.yaml -O tekton-dashboard-release.yaml
在 mac/linux 的工作机器上,执行如下代码(如果你用的 Windows,可以通过安装 gnu 的命令行工具来获取 grep, awk 的工具。
grep -Eo "gcr.io([^\" ]*)" tekton-pipeline-release.yaml | awk '{print "docker pull "$0}' > pull.sh
grep -Eo "gcr.io([^\" ]*)" tekton-pipeline-release.yaml | awk -F"@" '{origin = $0;gsub("gcr.io/","",$1);print "docker tag " origin " my-registry.cn-beijing.cr.aliyuncs.com/gcrio/"$1 ";\ndocker push my-registry.cn-beijing.cr.aliyuncs.com/gcrio/" $1}' > tag.push.sh
source pull.sh
source push.sh
然后更改 tekton-pipeline-release 中的地址为自己的镜像仓库(Linux):
sed -i "s/gcr.io/my-registry.cn-beijing.cr.aliyuncs.com\/gcrio/g" tekton-pipeline-release.yaml
mac 上这样运行(如果 mac 上面安装了 gnu sed,可以直接执行上面的 sed 命令):
sed -i "" "s/gcr.io/my-registry.cn-beijing.cr.aliyuncs.com\/gcrio/g" tekton-pipeline-release.yaml
然后编辑 tekton-pipeline-release.yaml 里面的内容,去掉镜像仓库中的 SHA256,通过版本号或者 latest 来引用。
kubectl create namespace tekton-pipelines
kubectl apply -f tekton-pipeline-release.yaml
dashboard 用到的镜像目前只有1个。直接生成 docker pull, docker tag, docker push 命令, 输出到 console, 然后手工执行这些命令即可:
grep -Eo "gcr.io([^\" ]*)" tekton-dashboard-release.yaml | awk '{print "docker pull "$0}' grep -Eo "gcr.io([^\" ]*)" tekton-dashboard-release.yaml | awk -F"@" '{origin = $0;gsub("gcr.io/","",$1);print "docker tag " origin " my-registry.cn-beijing.cr.aliyuncs.com/gcrio/"$1 ";\ndocker push my-registry.cn-beijing.cr.aliyuncs.com/gcrio/" $1}'
拷贝前面两个命令的输出, 执行一下命令(docker pull、docker push)。
然后替换文件中的镜像地址(Linux):
sed -i "s/gcr.io/my-registry.cn-beijing.cr.aliyuncs.com\/gcrio/g" tekton-dashboard-release.yaml
mac 上这样运行:
sed -i "" "s/gcr.io/my-registry.cn-beijing.cr.aliyuncs.com\/gcrio/g" tekton-dashboard-release.yaml
然后部署 tekton dashboard:
kubectl apply -f tekton-dashboard-release.yaml
检查 pod 的状态:
kubectl get pods --namespace tekton-pipelines
可以看到如下的输出
pod 正常 running 之后,转发集群端口到本地,即可通过本地访问:
kubectl --namespace tekton-pipelines port-forward svc/tekton-dashboard 9097:9097
然后就可以本地访问 Dashboard: http://localhost:9097
创建一个最简单的 task 名称为 hello, 这个 task 使用 alpine 的镜像启动一个容器,执行指定脚本。
#hello-world.yaml 文件内容, 定义名称为 hello 的 task
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: hello
spec:
steps:
- name: echo
image: alpine
script: |
#!/bin/sh
echo "Hello World"
部署 Task
kubectl apply --filename hello-world.yaml
创建一个 TaskRun 来执行 hello 这个 Task
#hello-world-run.yaml
apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
name: hello-task-run
spec:
taskRef:
name: hello
在集群中运行 task:
kubectl apply --filename hello-world-run.yaml
基于Kubernetes 服务部署 Tekton Pipeline 实例,部署完成后使用tekton来完成源码拉取、应用打包、镜像推送和应用部署。
本文实现一个 golang-helloworld 项目 CI/CD 的完整流程,具体包括以下步骤:
镜推送到外部镜像仓库需要进行认证,创建登录阿里云ACR仓库的secret
kubectl create secret docker-registry aliyun-acr \
--docker-server=https://registry.cn-shenzhen.aliyuncs.com \
--docker-username=<your-username> \
--docker-password=<your-password> \
--dry-run=client -o json | jq -r '.data.".dockerconfigjson"' | base64 -d > /tmp/config.json
kubectl create secret generic docker-config --from-file=/tmp/config.json
创建kubernetes secret
kubectl create secret generic kubernetes-config --from-file=/root/.kube/config
创建serviceAccount
$ cat serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: build-bot
secrets:
- name: docker-config
- name: kubernetes-config
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: tekton-kubectl-role
rules:
- apiGroups:
- "*"
resources:
- pods
- deployments
- deployments/scale
- deployments/status
verbs:
- get
- list
- watch
- create
- delete
- patch
- update
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: tekton-kubectl-binding
subjects:
- kind: ServiceAccount
name: build-bot
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: tekton-kubectl-role
应用yaml文件
kubectl apply -f serviceaccount.yaml
在执行镜像构建前Dockerfile存放在git仓库中,需要将代码克隆到本地,需要安装git-clone task,这里使用官方task。
kubectl apply -f \
https://raw.githubusercontent.com/tektoncd/catalog/main/task/git-clone/0.9/git-clone.yaml
创建kaniko-build task,用于构建dokcer镜像,基于官方kaniko-task改造。
$ cat kaniko-build-task.yaml
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: kaniko-build
spec:
params:
- name: IMAGE_URL
description: Name (reference) of the image to build.
- name: IMAGE_TAG
description: Tag to apply to the built image
default: latest
- name: DOCKERFILE
description: Path to the Dockerfile to build.
default: ./Dockerfile
- name: CONTEXT
description: The build context used by Kaniko.
default: ./
- name: EXTRA_ARGS
type: array
default: []
- name: BUILDER_IMAGE
description: The image on which builds will run (default is v1.5.1)
default: gcr.io/kaniko-project/executor:v1.5.1@sha256:c6166717f7fe0b7da44908c986137ecfeab21f31ec3992f6e128fff8a94be8a5
workspaces:
- name: source
description: Holds the context and Dockerfile
- name: dockerconfig
description: Includes a docker `config.json`
optional: true
mountPath: /kaniko/.docker
results:
- name: IMAGE_DIGEST
description: Digest of the image just built.
- name: IMAGE_URL
description: URL of the image just built.
steps:
- name: build-and-push
workingDir: $(workspaces.source.path)
image: $(params.BUILDER_IMAGE)
args:
- $(params.EXTRA_ARGS)
- --dockerfile=$(params.DOCKERFILE)
- --context=$(workspaces.source.path)/$(params.CONTEXT)
- --destination=$(params.IMAGE_URL):$(params.IMAGE_TAG)
- --digest-file=$(results.IMAGE_DIGEST.path)
securityContext:
runAsUser: 0
应用yaml文件
kubectl apply -f kaniko-build-task.yaml
创建kubernetes-deploy task,用于部署yaml文件到kubernetes集群。
$ cat kubernetes-deploy-task.yaml
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: kubernetes-deploy
spec:
workspaces:
- name: manifest-dir
- name: kubeconfig-dir
mountPath: /root/.kube
params:
- name: pathToYamlFile
description: The path to the yaml file to deploy within the git source
default: deployment.yaml
- name: IMAGE_URL
- name: IMAGE_TAG
- name: KUBECTL_IMAGE
default: docker.io/bitnami/kubectl:latest
steps:
- name: run-kubectl
image: $(params.KUBECTL_IMAGE)
workingDir: $(workspaces.manifest-dir.path)
script: |
sed -i s#IMAGE#$(params.IMAGE_URL)#g $(params.pathToYamlFile)
sed -i s#TAG#$(params.IMAGE_TAG)#g $(params.pathToYamlFile)
kubectl apply -f $(params.pathToYamlFile)
应用yaml文件
kubectl apply -f kubernetes-deploy-task.yaml
$ cat pipeline-run.yaml
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: devops-hello-world-pipeline
spec:
workspaces:
- name: shared-data
- name: docker-config
- name: kubernetes-config
params:
# git-clone
- name: git_url
type: string
- name: revision
type: string
- name: gitInitImage
type: string
# kaniko-build
- name: dockerfile
type: string
description: reference of the image to build
- name: builder_image
type: string
description: reference of the image to build
- name: image_url
description: Url of image repository
- name: image_tag
description: Tag to apply to the built image
default: latest
# kubernetes-deploy
- name: kubectl_image
type: string
tasks:
- name: clone
taskRef:
name: git-clone
workspaces:
- name: output
workspace: shared-data
params:
- name: url
value: $(params.git_url)
- name: revision
value: $(params.revision)
- name: gitInitImage
value: $(params.gitInitImage)
- name: build-push-image
params:
- name: DOCKERFILE
value: $(params.dockerfile)
- name: IMAGE_URL
value: $(params.image_url)
- name: IMAGE_TAG
value: $(tasks.clone.results.commit)
- name: BUILDER_IMAGE
value: $(params.builder_image)
taskRef:
name: kaniko
runAfter:
- clone
workspaces:
- name: source
workspace: shared-data
- name: dockerconfig
workspace: docker-config
- name: deploy-to-k8s
taskRef:
name: kubernetes-deploy
params:
- name: KUBECTL_IMAGE
value: $(params.kubectl_image)
- name: IMAGE_URL
value: $(params.image_url)
- name: IMAGE_TAG
value: $(tasks.clone.results.commit)
- name: pathToYamlFile
value: deployment.yaml
workspaces:
- name: manifest-dir
workspace: shared-data
- name: kubeconfig-dir
workspace: kubernetes-config
runAfter:
- build-push-image
---
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
generateName: devops-hello-world-pipeline-run-
spec:
serviceAccountName: build-bot
pipelineRef:
name: devops-hello-world-pipeline
params:
# git-clone
- name: git_url
value: https://gitee.com/willzhangee/tekton-golang-demo.git
- name: revision
value: master
- name: gitInitImage
#value: gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/git-init:latest
value: dyrnq/tektoncd-pipeline-cmd-git-init:latest
# kaniko
- name: dockerfile
value: ./Dockerfile
- name: builder_image
# value: gcr.io/kaniko-project/executor:v1.5.1@sha256:c6166717f7fe0b7da44908c986137ecfeab21f31ec3992f6e128fff8a94be8a5
value: docker.io/bitnami/kaniko:latest
- name: image_url
value: registry.cn-shenzhen.aliyuncs.com/cnmirror/devops-hello-world
- name: image_tag
value: latest
# kubernetes-deploy
- name: kubectl_image
value: 'docker.io/bitnami/kubectl:latest'
workspaces:
- name: shared-data
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
storageClassName: openebs-hostpath
resources:
requests:
storage: 1Gi
- name: docker-config
secret:
secretName: docker-config
- name: kubernetes-config
secret:
secretName: kubernetes-config
gitInitImage# 执行git clone任务的镜像,官方镜像无法访问,推荐在docekrhub中查找替代镜像。
builder_image #执行kaniko 构建任务的镜像,官方镜像无法访问,推荐在docekrhub中查找替代镜像。
image_url #最终构建的应用镜像。
serviceAccountName #指定serviceAccountName用于认证。
shared-data workspace #用于在不同任务之间共享数据,PipelineRun中定义了volumeClaimTemplate类型的workspaces,能够动态申请所需的持久卷,使用kubectl get storageclass命令,确认k8s集群有默认可用的storageclass资源可用,本示例输出为openebs-hostpath (default)。
docker-config workspace #用于镜像仓库认证的secret卷,将secret中的`config.json挂载到/kaniko/.docker`下。
kubernetes-config #用于访问kubernetes,挂载到/root/.kube目录下。
应用yaml文件
kubectl create -f pipeline-run.yaml
查看pipelinerun执行结果
连接到kubernetes 确认部署的应用
root@kube001:~# kubectl get pods -l run=go-web-app
NAME READY STATUS RESTARTS AGE
go-web-app-79454cfdd7-dcz7p 1/1 Running 0 64s
查看镜像信息
root@kube001:~# kubectl get pods go-web-app-79454cfdd7-dcz7p -o jsonpath='{.spec.containers[0].image}'
registry.cn-shenzhen.aliyuncs.com/cnmirror/devops-hello-world:927ec5cc665690ad798ffbbd02a8db520692951e
Tekton是一个开源的、云原生的CI/CD框架,旨在为容器化环境下的持续集成和持续交付提供强大的工具和功能支持。通过使用Tekton,开发人员可以实现以下目标:
此外,Tekton还提供了其他一些有用的特性,如断点调试支持、Matrix语法(用于不同参数、环境的交叉验证)以及Result API(用于管理运行任务的pod资源)等。这些特性进一步增强了Tekton的灵活性和可扩展性,使得它成为一个强大的CI/CD工具。
如果你的应用大部分都是云原生环境的应用,部署于 k8s 之上,且团队中有人对于 k8s/docker 比较熟悉,推荐使用 Tekton 来作为 CICD 的基础设施。
如果不是云原生应用,或者团队对于 k8s/docker 不够熟悉, 建议使用 Jenkins 来做 CICD。