作者:阳明 2021-06-28 06:32:46
云计算
自动化 在 Tekton 中我们就可以将这些阶段直接转换成 Task 任务,clone 代码在 Tekton 中不需要我们主动定义一个任务,只需要在执行的任务上面指定一个输入的代码资源即可
前面我们讲解了使用 Jenkins 流水线来实现 Kubernetes 应用的 CI/CD,现在我们来将这个流水线迁移到 Tekton 上面来,其实整体思路都是一样的,就是把要整个工作流划分成不同的任务来执行,前面工作流的阶段划分了以下几个阶段:Clone 代码 -> 单元测试 -> Golang 编译打包 -> Docker 镜像构建/推送 -> Kubectl 部署服务。
在 Tekton 中我们就可以将这些阶段直接转换成 Task 任务,Clone 代码在 Tekton 中不需要我们主动定义一个任务,只需要在执行的任务上面指定一个输入的代码资源即可。下面我们就来将上面的工作流一步一步来转换成 Tekton 流水线,代码仓库同样还是 http://git.k8s.local/course/devops-demo.git。
虽然我们可以不用单独定义一个 Clone 代码的任务,直接使用 git 类型的输入资源即可,由于这里涉及到的任务较多,而且很多时候都需要先 Clone 代码然后再进行操作,所以最好的方式是将代码 Clone 下来过后通过 Workspace 共享给其他任务,这里我们可以直接使用 Catalog git-clone 来实现这个任务,我们可以根据自己的需求做一些定制,对应的 Task 如下所示:
- # task-clone.yaml
- apiVersion: tekton.dev/v1beta1
- kind: Task
- metadata:
- name: git-clone
- spec:
- workspaces:
- - name: output
- description: The git repo will be cloned onto the volume backing this Workspace.
- - name: basic-auth
- optional: true
- description: |
- A Workspace containing a .gitconfig and .git-credentials file. These
- will be copied to the user's home before any git commands are run. Any
- other files in this Workspace are ignored. It is strongly recommended
- to use ssh-directory over basic-auth whenever possible and to bind a
- Secret to this Workspace over other volume types.
- params:
- - name: url
- description: Repository URL to clone from.
- type: string
- - name: revision
- description: Revision to checkout. (branch, tag, sha, ref, etc...)
- type: string
- default: ""
- - name: refspec
- description: Refspec to fetch before checking out revision.
- default: ""
- - name: submodules
- description: Initialize and fetch git submodules.
- type: string
- default: "true"
- - name: depth
- description: Perform a shallow clone, fetching only the most recent N commits.
- type: string
- default: "1"
- - name: sslVerify
- description: Set the `http.sslVerify` global git config. Setting this to `false` is not advised unless you are sure that you trust your git remote.
- type: string
- default: "true"
- - name: subdirectory
- description: Subdirectory inside the `output` Workspace to clone the repo into.
- type: string
- default: ""
- - name: sparseCheckoutDirectories
- description: Define the directory patterns to match or exclude when performing a sparse checkout.
- type: string
- default: ""
- - name: deleteExisting
- description: Clean out the contents of the destination directory if it already exists before cloning.
- type: string
- default: "true"
- - name: verbose
- description: Log the commands that are executed during `git-clone`'s operation.
- type: string
- default: "true"
- - name: gitInitImage
- description: The image providing the git-init binary that this Task runs.
- type: string
- default: "cnych/tekton-git-init:v0.24.1"
- - name: userHome
- description: |
- Absolute path to the user's home directory. Set this explicitly if you are running the image as a non-root user or have overridden
- the gitInitImage param with an image containing custom user configuration.
- type: string
- default: "/root"
- results:
- - name: commit
- description: The precise commit SHA that was fetched by this Task.
- - name: url
- description: The precise URL that was fetched by this Task.
- steps:
- - name: clone
- image: "$(params.gitInitImage)"
- env:
- - name: HOME
- value: "$(params.userHome)"
- - name: PARAM_URL
- value: $(params.url)
- - name: PARAM_REVISION
- value: $(params.revision)
- - name: PARAM_REFSPEC
- value: $(params.refspec)
- - name: PARAM_SUBMODULES
- value: $(params.submodules)
- - name: PARAM_DEPTH
- value: $(params.depth)
- - name: PARAM_SSL_VERIFY
- value: $(params.sslVerify)
- - name: PARAM_SUBDIRECTORY
- value: $(params.subdirectory)
- - name: PARAM_DELETE_EXISTING
- value: $(params.deleteExisting)
- - name: PARAM_VERBOSE
- value: $(params.verbose)
- - name: PARAM_SPARSE_CHECKOUT_DIRECTORIES
- value: $(params.sparseCheckoutDirectories)
- - name: PARAM_USER_HOME
- value: $(params.userHome)
- - name: WORKSPACE_OUTPUT_PATH
- value: $(workspaces.output.path)
- - name: WORKSPACE_BASIC_AUTH_DIRECTORY_BOUND
- value: $(workspaces.basic-auth.bound)
- - name: WORKSPACE_BASIC_AUTH_DIRECTORY_PATH
- value: $(workspaces.basic-auth.path)
- script: |
- #!/usr/bin/env sh
- set -eu
- if [ "${PARAM_VERBOSE}" = "true" ] ; then
- set -x
- fi
- if [ "${WORKSPACE_BASIC_AUTH_DIRECTORY_BOUND}" = "true" ] ; then
- cp "${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/.git-credentials" "${PARAM_USER_HOME}/.git-credentials"
- cp "${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/.gitconfig" "${PARAM_USER_HOME}/.gitconfig"
- chmod 400 "${PARAM_USER_HOME}/.git-credentials"
- chmod 400 "${PARAM_USER_HOME}/.gitconfig"
- fi
- CHECKOUT_DIR="${WORKSPACE_OUTPUT_PATH}/${PARAM_SUBDIRECTORY}"
- cleandir() {
- # Delete any existing contents of the repo directory if it exists.
- #
- # We don't just "rm -rf ${CHECKOUT_DIR}" because ${CHECKOUT_DIR} might be "/"
- # or the root of a mounted volume.
- if [ -d "${CHECKOUT_DIR}" ] ; then
- # Delete non-hidden files and directories
- rm -rf "${CHECKOUT_DIR:?}"/*
- # Delete files and directories starting with . but excluding ..
- rm -rf "${CHECKOUT_DIR}"/.[!.]*
- # Delete files and directories starting with .. plus any other character
- rm -rf "${CHECKOUT_DIR}"/..?*
- fi
- }
- if [ "${PARAM_DELETE_EXISTING}" = "true" ] ; then
- cleandir
- fi
- /ko-app/git-init \
- -url="${PARAM_URL}" \
- -revision="${PARAM_REVISION}" \
- -refspec="${PARAM_REFSPEC}" \
- -path="${CHECKOUT_DIR}" \
- -sslVerify="${PARAM_SSL_VERIFY}" \
- -submodules="${PARAM_SUBMODULES}" \
- -depth="${PARAM_DEPTH}" \
- -sparseCheckoutDirectories="${PARAM_SPARSE_CHECKOUT_DIRECTORIES}"
- cd "${CHECKOUT_DIR}"
- RESULT_SHA="$(git rev-parse HEAD)"
- EXIT_CODE="$?"
- if [ "${EXIT_CODE}" != 0 ] ; then
- exit "${EXIT_CODE}"
- fi
- printf "%s" "${RESULT_SHA}" > "$(results.commit.path)"
- printf "%s" "${PARAM_URL}" > "$(results.url.path)"
一般来说我们只需要提供 output 这个个用于持久化代码的 workspace,然后还包括 url 和 revision 这两个参数,其他使用默认的即可。
单元测试阶段比较简单,正常来说也是只是单纯执行一个测试命令即可,我们这里没有真正执行单元测试,所以简单测试下即可,编写一个如下所示的 Task:
- # task-test.yaml
- apiVersion: tekton.dev/v1beta1
- kind: Task
- metadata:
- name: test
- spec:
- steps:
- - name: test
- image: golang:1.14-alpine
- command: ['echo']
- args: ['this is a test task']
然后第二个阶段是编译打包阶段,因为我们这个项目的 Dockerfile 不是使用的多阶段构建,所以需要先用一个任务去将应用编译打包成二进制文件,然后将这个编译过后的文件传递到下一个任务进行镜像构建。
我们已经明确了这个阶段要做的事情,编写任务也就简单了,创建如下所的 Task 任务,首先需要通过定义一个 workspace 把 clone 任务里面的代码关联过来:
- # task-build.yaml
- apiVersion: tekton.dev/v1beta1
- kind: Task
- metadata:
- name: build
- spec:
- workspaces:
- - name: go-repo
- mountPath: /workspace/repo
- steps:
- - name: build
- image: golang:1.14-alpine
- workingDir: /workspace/repo
- script: |
- go build -v -o app
- env:
- - name: GOPROXY
- value: https://goproxy.cn
- - name: GOOS
- value: linux
- - name: GOARCH
- value: amd64
这个构建任务也很简单,只是我们将需要用到的环境变量直接通过 env 注入了,当然直接写入到 script 中也是可以的,或者直接使用 command 来执行任务都可以,然后构建生成的 app 这个二进制文件保留在代码根目录,这样也就可以通过 workspace 进行共享了。
接下来就是构建并推送 Docker 镜像了,前面我们介绍过使用 Kaniko、DooD、DinD 3种模式的镜像构建方式,这里我们直接使用 DinD 这种模式,我们这里要构建的镜像 Dockerfile 非常简单:
- FROM alpine
- WORKDIR /home
- # 修改alpine源为阿里云
- RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories && \
- apk update && \
- apk upgrade && \
- apk add ca-certificates && update-ca-certificates && \
- apk add --update tzdata && \
- rm -rf /var/cache/apk/*
- COPY app /home/
- ENV TZ=Asia/Shanghai
- EXPOSE 8080
- ENTRYPOINT ./app
就行直接将编译好的二进制文件拷贝到镜像中即可,所以我们这里同样需要通过 Workspace 去获取上一个构建任务的制品,当然要使用 DinD 模式构建镜像,需要用到 sidecar 功能,创建一个如下所示的任务:
- # task-docker.yaml
- apiVersion: tekton.dev/v1beta1
- kind: Task
- metadata:
- name: docker
- spec:
- workspaces:
- - name: go-repo
- params:
- - name: image
- description: Reference of the image docker will produce.
- - name: registry_mirror
- description: Specific the docker registry mirror
- default: ""
- - name: registry_url
- description: private docker images registry url
- steps:
- - name: docker-build # 构建步骤
- image: docker:stable
- env:
- - name: DOCKER_HOST # 用 TLS 形式通过 TCP 链接 sidecar
- value: tcp://localhost:2376
- - name: DOCKER_TLS_VERIFY # 校验 TLS
- value: "1"
- - name: DOCKER_CERT_PATH # 使用 sidecar 守护进程生成的证书
- value: /certs/client
- - name: DOCKER_PASSWORD
- valueFrom:
- secretKeyRef:
- name: harbor-auth
- key: password
- - name: DOCKER_USERNAME
- valueFrom:
- secretKeyRef:
- name: harbor-auth
- key: username
- workingDir: $(workspaces.go-repo.path)
- script: | # docker 构建命令
- docker login $(params.registry_url) -u $DOCKER_USERNAME -p $DOCKER_PASSWORD
- docker build --no-cache -f ./Dockerfile -t $(params.image) .
- docker push $(params.image)
- volumeMounts: # 声明挂载证书目录
- - mountPath: /certs/client
- name: dind-certs
- sidecars: # sidecar 模式,提供 docker daemon服务,实现真正的 DinD 模式
- - image: docker:dind
- name: server
- args:
- - --storage-driver=vfs
- - --userland-proxy=false
- - --debug
- - --insecure-registry=$(params.registry_url)
- - --registry-mirror=$(params.registry_mirror)
- securityContext:
- privileged: true
- env:
- - name: DOCKER_TLS_CERTDIR # 将生成的证书写入与客户端共享的路径
- value: /certs
- volumeMounts:
- - mountPath: /certs/client
- name: dind-certs
- readinessProbe: # 等待 dind daemon 生成它与客户端共享的证书
- periodSeconds: 1
- exec:
- command: ["ls", "/certs/client/ca.pem"]
- volumes: # 使用 emptyDir 的形式即可
- - name: dind-certs
- emptyDir: {}
这个任务的重点还是要去声明一个 Workspace,当执行任务的时候要使用和前面构建任务同一个 Workspace,这样就可以获得上面编译成的 app 这个二进制文件了。
接下来的部署阶段,我们同样可以参考之前 Jenkins 流水线里面的实现,由于项目中我们包含了 Helm Chart 包,所以直接使用 Helm 来部署即可,要实现 Helm 部署,当然我们首先需要一个包含 helm 命令的镜像,当然完全可以自己去编写一个这样的任务,此外我们还可以直接去 hub.tekton.dev 上面查找 Catalog,因为这上面就有很多比较通用的一些任务了,比如 helm-upgrade-from-source 这个 Task 任务就完全可以满足我们的需求了:
helm tekton
这个 Catalog 下面也包含完整的使用文档了,我们可以将该任务直接下载下来根据我们自己的需求做一些定制修改,如下所示:
- # task-deploy.yaml
- apiVersion: tekton.dev/v1beta1
- kind: Task
- metadata:
- name: deploy
- spec:
- params:
- - name: charts_dir
- description: The directory in source that contains the helm chart
- - name: release_name
- description: The helm release name
- - name: release_namespace
- description: The helm release namespace
- default: ""
- - name: overwrite_values
- description: "Specify the values you want to overwrite, comma separated: autoscaling.enabled=true,replicas=1"
- default: ""
- - name: values_file
- description: "The values file to be used"
- default: "values.yaml"
- - name: helm_image
- description: "helm image to be used"
- default: "docker.io/lachlanevenson/k8s-helm:v3.3.4@sha256:e1816be207efbd342cba9d3d32202e237e3de20af350617f8507dc033ea66803" #tag: v3.3.4
- workspaces:
- - name: source
- results:
- - name: helm-status
- description: Helm deploy status
- steps:
- - name: upgrade
- image: $(params.helm_image)
- workingDir: /workspace/source
- script: |
- echo current installed helm releases
- helm list --namespace "$(params.release_namespace)"
- echo installing helm chart...
- helm upgrade --install --wait --values "$(params.charts_dir)/$(params.values_file)" --create-namespace --namespace "$(params.release_namespace)" $(params.release_name) $(params.charts_dir) --debug --set "$(params.overwrite_values)"
- status=`helm status $(params.release_name) --namespace "$(params.release_namespace)" | awk '/STATUS/ {print $2}'`
- echo ${status} | tr -d "\n" | tee $(results.helm-status.path)
因为我们的 Helm Chart 模板就在代码仓库中,所以不需要从 Chart Repo 仓库中获取,只需要指定 Chart 路径即可,其他可配置的参数都通过 params 参数暴露出去了,非常灵活,最后我们还获取了 Helm 部署的状态,写入到了 Results 中,方便后续任务处理。
最后应用部署完成后可能还需要回滚,因为可能部署的应用有错误,当然这个回滚动作最好是我们自己去触发,但是在某些场景下,比如 helm 部署已经明确失败了,那么我们当然可以自动回滚了,所以就需要判断当部署失败的时候再执行回滚,也就是这个任务并不是一定会发生的,只在某些场景下才会出现,我们可以在流水线中通过使用 WhenExpressions 来实现这个功能,之前版本中是使用 Conditions,不过已经废弃了。要只在满足某些条件时运行任务,可以使用 when 字段来保护任务执行,when 字段允许你列出对 WhenExpressions 的一系列引用。
WhenExpressions 由 Input、Operator 和 Values 几部分组成:
当在一个 Task 任务中配置了 WhenExpressions,在执行 Task 之前会评估声明的 WhenExpressions,如果结果为 True,则执行任务,如果为 False,则不会执行该任务。
我们这里创建的回滚任务如下所示:
- # task-rollback.yaml
- apiVersion: tekton.dev/v1beta1
- kind: Task
- metadata:
- name: rollback
- spec:
- params:
- - name: release_name
- description: The helm release name
- - name: release_namespace
- description: The helm release namespace
- default: ""
- - name: helm_image
- description: "helm image to be used"
- default: "docker.io/lachlanevenson/k8s-helm:v3.3.4@sha256:e1816be207efbd342cba9d3d32202e237e3de20af350617f8507dc033ea66803" #tag: v3.3.4
- steps:
- - name: rollback
- image: $(params.helm_image)
- script: |
- echo rollback current installed helm releases
- helm rollback $(params.release_name) --namespace $(params.release_namespace)
现在我们的整个工作流任务都已经创建完成了,接下来我们就可以将这些任务全部串联起来组成一个 Pipeline 流水线了,将上面定义的几个 Task 引用到 Pipeline 中来,当然还需要声明 Task 中用到的 resources 或者 workspaces 这些数据:
- # pipeline.yaml
- apiVersion: tekton.dev/v1beta1
- kind: Pipeline
- metadata:
- name: pipeline
- spec:
- workspaces: # 声明 workspaces
- - name: go-repo-pvc
- params:
- # 定义代码仓库
- - name: git_url
- - name: revision
- type: string
- default: "master"
- # 定义镜像参数
- - name: image
- - name: registry_url
- type: string
- default: "harbor.k8s.local"
- - name: registry_mirror
- type: string
- default: "https://ot2k4d59.mirror.aliyuncs.com/"
- # 定义 helm charts 参数
- - name: charts_dir
- - name: release_name
- - name: release_namespace
- default: "default"
- - name: overwrite_values
- default: ""
- - name: values_file
- default: "values.yaml"
- tasks: # 添加task到流水线中
- - name: clone
- taskRef:
- name: git-clone
- workspaces:
- - name: output
- workspace: go-repo-pvc
- params:
- - name: url
- value: $(params.git_url)
- - name: revision
- value: $(params.revision)
- - name: test
- taskRef:
- name: test
- - name: build # 编译二进制程序
- taskRef:
- name: build
- runAfter: # 测试任务执行之后才执行 build task
- - test
- - clone
- workspaces: # 传递 workspaces
- - name: go-repo
- workspace: go-repo-pvc
- - name: docker # 构建并推送 Docker 镜像
- taskRef:
- name: docker
- runAfter:
- - build
- workspaces: # 传递 workspaces
- - name: go-repo
- workspace: go-repo-pvc
- params: # 传递参数
- - name: image
- value: $(params.image)
- - name: registry_url
- value: $(params.registry_url)
- - name: registry_mirror
- value: $(params.registry_mirror)
- - name: deploy # 部署应用
- taskRef:
- name: deploy
- runAfter:
- - docker
- workspaces:
- - name: source
- workspace: go-repo-pvc
- params:
- - name: charts_dir
- value: $(params.charts_dir)
- - name: release_name
- value: $(params.release_name)
- - name: release_namespace
- value: $(params.release_namespace)
- - name: overwrite_values
- value: $(params.overwrite_values)
- - name: values_file
- value: $(params.values_file)
- - name: rollback # 回滚
- taskRef:
- name: rollback
- when:
- - input: "$(tasks.deploy.results.helm-status)"
- operator: in
- values: ["failed"]
- params:
- - name: release_name
- value: $(params.release_name)
- - name: release_namespace
- value: $(params.release_namespace)
整体流程比较简单,就是在 Pipeline 需要先声明使用到的 Workspace、Resource、Params 这些资源,然后将声明的数据传递到 Task 任务中去,需要注意的是最后一个回滚任务,我们需要根据前面的 deploy 任务的结果来判断是否需要执
当前标题:使用Tekton重构自动化流水线
URL地址:http://www.shufengxianlan.com/qtweb/news3/387103.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联