上一篇文件 Tekton介绍 介绍了Tekton、Tekton的安装教程、以及使用Tekton实现简单的HelloWorld,这篇文章通过复杂的项目实现完整的CI/CD流程来了解Tekton的使用。
本文实现一个 springboot 项目 CI/CD 的完整流程,具体包括以下步骤:
在实际使用过程中,helm可能被设计的比较小,每个微服务单独一个,便于独立交付。而要执行完整的部署操作,有一些全局的编排文件,放在helm chart中就不太合适,往往通通过 kubectl apply -f 命令一次创建创建好就完成了,比如:拉取镜像的secret信息、istio的gateway信息。这时就可以用一个单独的执行 kubectl 命令的 Task 来做。
使用到的材料、工具:
整条流水线包括四个Task:
用到了三个外部资源:
镜像构建完成后,生成的镜像url信息(包括tag),动态的传递到下一个Task,helm 部署时,通过指定 --set 参数,完成新应用的部署
.
├── gcp-git-resource.yaml
├── gcp-git-secret.yaml
├── gcp-helm-git-resource.yaml
├── gcp-helm-task.yaml
├── gcp-image-resource.yaml
├── gcp-image-secret.yaml
├── gcp-kubectl-task.yaml
├── gcp-maven-kaniko-task.yaml
├── gcp-pipeline.yaml
├── gcp-pipelinerun.yaml
├── gcp-unittest-task.yaml
└── serviceaccount.yaml
首先通过PipelineResource
定义源代码的配置信息,存在在 gcp-git-resource.yaml 文件中
apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
name: gcp-git-resource
namespace: tekton-pipelines
spec:
type: git
params:
- name: url
value: http://gitlab.xxx.com/project/xxx.git
- name: revision
value: master
如果git仓库不是公开的,需要定义账号密码信息,存放在 gcp-git-secret.yaml 文件中
annotations 中的 tekton.dev/git-0 指定了将此账号密码信息应用于哪个域名下的git仓库
apiVersion: v1
kind: Secret
metadata:
name: gcp-git-secret
namespace: tekton-pipelines
annotations:
tekton.dev/git-0: http://gitlab.xxx.com
type: kubernetes.io/basic-auth
stringData:
username: username
password: "********"
存放在 gcp-helm-git-resource.yaml 文件中
apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
name: gcp-helm-git-resource
namespace: tekton-pipelines
spec:
type: git
params:
- name: url
value: http://gitlab.xxx.com/xxx/manifests.git
- name: revision
value: dev
存放在 gcp-image-resource.yaml 文件中
apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
name: gcp-image-resource
namespace: tekton-pipelines
spec:
type: image
params:
- name: url
value: xxx-registry.cn-beijing.cr.aliyuncs.com/project/app
存放在 gcp-image-secret.yaml 文件中
apiVersion: v1
kind: Secret
metadata:
name: gcp-image-secret
namespace: tekton-pipelines
annotations:
tekton.dev/docker-0: http://xxx-registry.cn-beijing.cr.aliyuncs.com/v1/
type: kubernetes.io/basic-auth
stringData:
username: username
password: ******
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: gcp-maven-test
namespace: tekton-pipelines
spec:
resources:
inputs:
- name: src-git-repo
type: git
steps:
- name: maven-test
image: maven:3.5.0-jdk-8-alpine
workingDir: /workspace/src-git-repo
command:
- mvn
args:
- test
volumeMounts:
- name: m2
mountPath: /root/.m2
volumes:
- name: m2
hostPath:
path: /root/.m2
该 Task 定义了两个 Step:
构建镜像使用的是google开源的kaniko,因为使用docker构建,存在 docker in docker 的问题,docker构建需要docker daemon进程,因此需要挂载宿主机的 docker.sock 文件,这样不安全。kaniko 这个镜像构建工具特别轻量化,不像 docker 一样依赖一个 daemon 进程。
使用到两个资源文件:
文件中还定义了一个名为 DOCKER_CONFIG
的环境变量,这个变量是用于 Kaniko 去查找 Docker 认证信息的
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: gcp-maven-kaniko-build
namespace: tekton-pipelines
spec:
params:
- name: imageTag
type: string
resources:
inputs:
- name: src-git-repo
type: git
outputs:
- name: image-repo
type: image
steps:
- name: maven-build
image: maven:3.5.0-jdk-8-alpine
workingDir: /workspace/src-git-repo
command:
- mvn
args:
- clean
- package
volumeMounts:
- name: m2
mountPath: /root/.m2
- name: kaniko-build
image: cnych/kaniko-executor:v0.22.0
workingDir: /workspace/kaniko
env:
- name: DOCKER_CONFIG
value: /tekton/home/.docker
command:
- /kaniko/executor
- --dockerfile=$(resources.inputs.src-git-repo.path)/Dockerfile
- --context=$(resources.inputs.src-git-repo.path)
- --destination=$(resources.outputs.image-repo.url):$(params.imageTag)
- --insecure
- --skip-tls-verify
- --skip-tls-verify-pull
- --insecure-pull
volumes:
- name: m2
hostPath:
path: /root/.m2
该 Task 使用了 lachlanevenson/k8s-kubectl 这个镜像,内部预装了 kubectl 工具,参数是需要执行的脚本内容。
定义参数使用 params 字段设置,引用该参数的语法格式为 $(xxx)
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: gcp-kubectl-deploy
namespace: tekton-pipelines
spec:
params:
- name: script_body
type: string
default: "kubectl version"
steps:
- name: kubectl-deploy
image: lachlanevenson/k8s-kubectl
script: |
$(params.script_body)
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: gcp-helm-deploy
namespace: tekton-pipelines
spec:
params:
- name: release_namespace
default: "tekton-pipelines"
- name: charts_dir
default: "autotest/cloudsandbox-charts"
- name: release_name
default: "scheduler-ast"
- name: values_file
default: "autotest/cloudsandbox-ast-slave.yaml"
- name: imageTag
default: "latest"
resources:
inputs:
- name: helm-git-repo
type: git
- name: image-repo
type: image
steps:
- name: deploy-chart
image: docker.io/lachlanevenson/k8s-helm:v3.3.4
workingDir: /workspace/helm-git-repo
script: |
echo current installed helm releases
helm list --namespace "$(params.release_namespace)"
echo installing helm chart...
helm upgrade --install --wait --values "$(params.values_file)" --namespace "$(params.release_namespace)" $(params.release_name) $(params.charts_dir) --set "deploy.init_copyfiles_image=$(resources.inputs.image-repo.url):$(params.imageTag)"
serviceaccount 定义了需要访问k8s资源的权限, 引用 git 和 image 的 secret
apiVersion: v1
kind: ServiceAccount
metadata:
name: build-bot
namespace: tekton-pipelines
secrets:
- name: gcp-git-secret
- name: gcp-image-secret
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: gcp-pipeline
namespace: tekton-pipelines
spec:
params:
- name: imageTag
default: v0.0.2
- name: kubectl_script
type: string
resources:
- name: src-git-repo
type: git
- name: image-repo
type: image
- name: helm-git-repo
type: git
tasks:
- name: gcp-maven-test
taskRef:
name: gcp-maven-test
resources:
inputs:
- name: src-git-repo
resource: src-git-repo
- name: gcp-maven-kaniko-build
taskRef:
name: gcp-maven-kaniko-build
params:
- name: imageTag
value: $(params.imageTag)
resources:
inputs:
- name: src-git-repo
resource: src-git-repo
outputs:
- name: image-repo
resource: image-repo
- name: gcp-kubectl-deploy
taskRef:
name: gcp-kubectl-deploy
params:
- name: script_body
value: $(params.kubectl_script)
- name: gcp-helm-deploy
taskRef:
name: gcp-helm-deploy
params:
- name: imageTag
value: $(params.imageTag)
resources:
inputs:
- name: helm-git-repo
resource: helm-git-repo
- name: image-repo
resource: image-repo
from:
- gcp-maven-kaniko-build
pipeline 是流水线模板,真正执行需要定义 pipelineRun 对象。
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
namespace: tekton-pipelines
generateName: gcp-pipeline-run-
spec:
serviceAccountName: build-bot
pipelineRef:
name: gcp-pipeline
params:
- name: imageTag
value: v0.0.3
- name: kubectl_script
value: "kubectl get pod"
resources:
- name: src-git-repo
resourceRef:
name: gcp-git-resource
- name: image-repo
resourceRef:
name: gcp-image-resource
- name: helm-git-repo
resourceRef:
name: gcp-helm-git-resource
kubectl apply -f gcp-git-resource.yaml \
gcp-git-secret.yaml \
gcp-helm-git-resource.yaml \
gcp-helm-task.yaml \
gcp-image-resource.yaml \
gcp-image-secret.yaml \
gcp-kubectl-task.yaml \
gcp-maven-kaniko-task.yaml \
gcp-pipeline.yaml \
gcp-unittest-task.yaml \
serviceaccount.yaml
kubect create -f gcp-pipelinerun.yaml
后面几个是 tekton 系统本身的pod,前面四个pod 分别对应 pipeline中的四个 pod
> kubectl get pod -n tekton-pipelines
NAME READY STATUS RESTARTS AGE
gcp-pipeline-run-1618836739877-gcp-helm-deploy-glrg2-pod-wrqbv 0/2 Completed 0 37m
gcp-pipeline-run-1618836739877-gcp-kubectl-deploy-wlplk-p-5twxq 0/1 Completed 0 39m
gcp-pipeline-run-1618836739877-gcp-maven-kaniko-build-2k8-ccgtf 0/5 Completed 0 39m
gcp-pipeline-run-1618836739877-gcp-maven-test-q7rbz-pod-2v5xq 0/2 Completed 0 39m
tekton-dashboard-7b8db5fd75-2wkhj 1/1 Running 1 4d10h
tekton-pipelines-controller-544957d9d8-p65zr 1/1 Running 1 4d10h
tekton-pipelines-webhook-54cb64d5f7-k6qbw 1/1 Running 1 4d10h