更新历史:
•v1:2020.1.21 基于 Tekton Pipline v0.9.0[1]•v2(当前):2021.6.22 基于 Tekton Pipeline v0.25.0[2]
Tekton 是 Google 开源的 Kubernetes 原生CI/CD 系统, 功能强大扩展性强. 前身是 Knavite 里的 build-pipeline 项目, 后期孵化成独立的项目[3]. 并成为 CDF[4] 下的四个项目之一, 其他三个分别是 Jenkins, Jenkins X, Spinnaker.
为什么说 Tekton 是 Kubernetes 原生的, 以其基于 Kubernetes 的 CRD 定义了 Pipeline 流水线.
CRD 及说明:
•Task: 构建任务, 可以定义一些列的 steps. 每个 step 由一个 container 执行.•TaskRun: task 实际的执行, 并提供执行所需的参数. 这个对象创建后, 就会有 pod 被创建.•Pipeline: 定义一个或者多个 task 的执行, 以及 PipelineResource 和各种定义参数的集合•PipelineRun: 类似 task 和 taskrun 的关系: 一个定义一个执行. PipelineRun 则是 pipeline 的实际执行. 创建后也会创建 pod 来执行各个 task.•PipelineResource: 流水线的输入资源, 比如 github/gitlab 的源码, 某种存储服务的文件, 或者镜像等. 执行时, 也会作为 pod 的其中一个 container 来运行(比如拉取代码). PipelineResource 目前处于 Alaha,至于原因可以看Why Aren't PipelineResources in Beta?[5]•Condition: 在 pipeline 的 task 执行时通过添加 condition 来对条件进行评估, 进而判断是否执行 task. 目前是WIP的状态, 待#1137[6]的完成.
组件:
•tekton-pipelines-controller: 监控 CRD 对象(TaskRun, PipelineRun)的创建, 为该次执行创建 pod.•tekton-pipelines-webhook: 对 apiserver 提供 http 接口做 CRD 对象的校验.
文中使用的一些工具,基本都可以通过 homebrew 安装:
•jq[7] :操作 json 的命令行工具•httpie[8]:HTTP 客户端命令行工具•minikube 环境[9]
文中的 Java 项目以及 tekton 的相关 yaml 都已经提交到了 tekton-test[10].
参考上一篇文章[11], 文章中有个简单的"hello world".
到了这里相信已经安装好了 Tekton. 我们使用Spring Initializer[12]生成的项目为例, 演示如何使用 Tekton 实现 CICD.
开始之前简单整理下这个项目的 CICD 流程:
1.拉取代码2.maven 打包3.构建镜像并推送4.部署
注: 所有的操作都是在 tekton-pipelines namespace 下操作
用于构建镜像的Dockerfile
FROM openjdk:8-jdk-alpineRUN mkdir /appWORKDIR /appCOPY target/*.jar /app/app.jarENTRYPOINT ["sh", "-c", "java -Xmx128m -Xms64m -jar app.jar"]
用于部署 K8s Deployment 的 deployment.yml,同时通过创建 NodePort 类型的 Service 用于访问应用。
apiVersion: "apps/v1"kind: "Deployment"metadata:labels:app: "tekton-test"name: "tekton-test"spec:replicas: 1selector:matchLabels:app: "tekton-test"template:metadata:labels:app: "tekton-test"spec:containers:- image: "addozhang/tekton-test:latest"imagePullPolicy: "Always"livenessProbe:failureThreshold: 3httpGet:path: "/actuator/info"port: 8080scheme: "HTTP"initialDelaySeconds: 60periodSeconds: 10successThreshold: 1timeoutSeconds: 10name: "tekton-test"ports:- containerPort: 8080name: "http"protocol: "TCP"readinessProbe:failureThreshold: 3httpGet:path: "/actuator/info"port: 8080scheme: "HTTP"initialDelaySeconds: 30periodSeconds: 10successThreshold: 1timeoutSeconds: 10---apiVersion: v1kind: Servicemetadata:creationTimestamp: nulllabels:app: tekton-testname: tekton-testspec:ports:- port: 8080protocol: TCPtargetPort: 8080selector:app: tekton-testtype: NodePort
创建 ServiceAccount 用于 Pipeline 的运行。
注:这里为了方便,授予了 ClusterRole admin。
# serviceaccount.yamlapiVersion: v1kind: ServiceAccountmetadata:name: tekton-build---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata:name: pipeline-admin-bindingroleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: admin # user cluster role adminsubjects:- kind: ServiceAccountname: tekton-buildnamespace: tekton-pipelines
代码作为构建的输入, 需要提供一个 Pipeline CRD 对象来表示输入是从 git 仓库来获取代码。
访问 Tekton Hub 可以找到现成的 git-clone task[13]。
使用 kubectl 安装:
kubectl apply -f https://raw.githubusercontent.com/tektoncd/catalog/main/task/git-clone/0.4/git-clone.yaml或者使用 tekton-cli 安装:
tkn hub install task git-cloneTask source-to-image.yaml的 step maven:
spec:workspaces:- name: sourcesteps:- name: mavenimage: maven:3.5.0-jdk-8-alpineworkingDir: $(workspaces.source.path)command:- mvnargs:- clean- install- -DskipTestsvolumeMounts:- name: m2mountPath: /root/.m2volumes:- name: m2hostPath:path: /home/docker/.m2
说明:
有了代码下一步就是执行 maven 的编译打包, 在maven:3.5.0-jdk-8-alpine镜像中执行mvn的相关命令.
这里挂在了一个本地的volume, 避免每次构建重复下载依赖包, 同时里面还有settings.xml
注意: 对于 minikube, hostPath 请使用/data/.m2, 否则minikube重启后无法持久化
Task source-to-image.yaml 的 step build-and-push:
spec:params:- name: pathToDockerFiledescription: The path to the dockerfile to build (relative to the context)default: Dockerfile- name: imageUrldescription: Url of image repository- name: imageTagdescription: Tag to apply to the built imagedefault: latestworkspaces:- name: source- name: dockerconfigmountPath: /kaniko/.docker # config.json 的挂载目录steps:- name: build-and-pushimage: gcr.io/kaniko-project/executor:v1.6.0-debugcommand:- /kaniko/executorargs:- --dockerfile=$(params.pathToDockerFile)- --destination=$(params.imageUrl):$(params.imageTag)- --context=$(workspaces.source.path)
说明:
镜像的构建, 我们采用了 kaniko。
镜像仓库我们选择了Docker Hub, 推送的时候需要使用 credentials。
kaniko 需要将 docker config 的文件存在于 /kanika/.docker 目录下。这里的思路是将 docker 的 config.json,以 secret 的方式持久化,在通过先添加docker-registry类型的 secret,然后通过 workspace 的方式输入到 kaniko 运行环境中。
config.json 里面保存的 json 结构化的数据,为了方便通过 dry run 创建
kubectl create secret docker-registry dockerhub --docker-server=https://index.docker.io/v1/ --docker-username=[USERNAME] --docker-password=[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 && rm -f /tmp/config.json执行:
kubectl apply -f tasks/source-to-image.yamldeploy-to-k8s.yaml:
apiVersion: tekton.dev/v1alpha1kind: Taskmetadata:name: deploy-to-k8sspec:inputs:resources:- name: git-sourcetype: gitparams:- name: pathToYamlFiledescription: The path to the yaml file to deploy within the git sourcedefault: deployment.yamlsteps:- name: run-kubectlimage: lachlanevenson/k8s-kubectlcommand: ["kubectl"]args:- "apply"- "-f"- "/workspace/git-source/$(inputs.params.pathToYamlFile)"
说明:
•pathToYamlFile: 指定部署应用的 yaml。
执行:
kubectl apply -f tasks/deploy-to-k8s.yamlbuild-pipeline.yaml
apiVersion: tekton.dev/v1beta1kind: Pipelinemetadata:name: build-pipelinespec:params:- name: git-url- name: git-revision- name: pathToContextdescription: The path to the build context, used by Kaniko - within the workspacedefault: .- name: imageUrldescription: Url of image repository- name: imageTagdescription: Tag to apply to the built imageworkspaces:- name: git-source- name: docker-configtasks:- name: fetch-from-gittaskRef:name: git-cloneparams:- name: urlvalue: "$(params.git-url)"- name: revisionvalue: "$(params.git-revision)"workspaces:- name: outputworkspace: git-source- name: source-to-imagetaskRef:name: source-to-imageparams:- name: imageUrlvalue: "$(params.imageUrl)"- name: imageTagvalue: "$(params.imageTag)"workspaces:- name: sourceworkspace: git-source- name: dockerconfigworkspace: docker-configrunAfter:- fetch-from-git- name: deploy-to-k8staskRef:name: deploy-to-k8sparams:- name: pathToYamlFilevalue: deployment.yamlworkspaces:- name: sourceworkspace: git-sourcerunAfter:- source-to-image
执行:
kubectl apply -f tasks/deploy-to-k8s.yamlapiVersion: tekton.dev/v1beta1kind: PipelineRunmetadata:generateName: generic-pr-name: generic-pipeline-runspec:pipelineRef:name: build-pipelineparams:- name: git-revisionvalue: main- name: git-urlvalue: https://github.com/addozhang/tekton-test.git- name: imageUrlvalue: addozhang/tekton-test- name: imageTagvalue: latestworkspaces:- name: git-sourcevolumeClaimTemplate:spec:accessModes:- ReadWriteOnceresources:requests:storage: 1Gi- name: docker-configsecret:secretName: docker-configserviceAccountName: tekton-build
执行:
kubectl apply -f run/run.yaml执行流水线后, 可以看到分别创建了下面的几个 pod:
•generic-pipeline-run-deploy-to-k8s-xxx•generic-pipeline-run-fetch-from-git-xxx•generic-pipeline-run-source-to-image-xxx
以及我们的应用 tekton-test-xxx,发起请求测试:
$ http $(minikube ip):$(kubectl get svc tekton-test -o jsonpath="{.spec.ports[0].nodePort}")/hi --bodyhello world
目前 Tekton 进入 beta 阶段, 最新的版本是 0.25.0。基于 CRD 的实现让 Tekton 在实际使用中可以灵活的设计自己的 CICD 流程.
生态也越来越完善,比如 Tekton Hub[14] 提供了大量的可重用最佳实现的 Task 和 Pipeline。
下一篇,我们尝试下如何在 Jenkins 中与 Tekton Pipeline 进行交互。
更多文章:
•Tekton 的工作原理•Tekton Dashboard 安装[15]•Tekton Trigger 介绍[16]•Tekton Trigger 实战[17]
[1] v0.9.0: https://github.com/tektoncd/pipeline/tree/v0.9.0/docs#tekton-pipelines[2] v0.25.0: https://github.com/tektoncd/pipeline/tree/v0.25.0/docs#tekton-pipelines[3] 独立的项目: https://github.com/tektoncd/pipeline[4] CDF: https://cd.foundation/projects/[5] Why Aren't PipelineResources in Beta?: https://github.com/tektoncd/pipeline/blob/v0.25.0/docs/resources.md#why-arent-pipelineresources-in-beta[6] #1137: https://github.com/tektoncd/pipeline/issues/1137[7] jq: https://stedolan.github.io/jq/[8] httpie: https://httpie.io/[9] minikube 环境: https://minikube.sigs.k8s.io/docs/start/[10] tekton-test: https://github.com/addozhang/tekton-test[11] 上一篇文章: https://atbug.com/tekton-installation-and-sample/[12] Spring Initializer: https://start.spring.io/[13] git-clone task: https://hub.tekton.dev/tekton/task/git-clone[14] Tekton Hub: https://hub.tekton.dev/[15] Tekton Dashboard 安装: https://atbug.com/tekton-dashboard-installation/[16] Tekton Trigger 介绍: https://atbug.com/tekton-trigger-glance/[17] Tekton Trigger 实战: https://atbug.com/tekton-trigger-practice/
原文作者:云原生指北;如有侵权,请联系管理员删除。