云原生的 CI/CD 框架tekton - pipeline(一)

文章目录

    • [1. 官方介绍](#1. 官方介绍)
    • [2. 组件](#2. 组件)
      • [2.1 Tekton Pipelines](#2.1 Tekton Pipelines)
      • [2.2 部署pipeline](#2.2 部署pipeline)
      • [2.3 部署dashborad](#2.3 部署dashborad)
        • [2.3.1 task](#2.3.1 task)
        • [2.3.2 taskrun](#2.3.2 taskrun)
        • [2.3.3 Pipeline](#2.3.3 Pipeline)
        • [2.3.4 PipelineRun](#2.3.4 PipelineRun)
    • [3. 案例](#3. 案例)
      • [案例1: 拉取代码并查看readme](#案例1: 拉取代码并查看readme)
        • [step1: 创建task - 拉取代码](#step1: 创建task - 拉取代码)
        • [step2: 创建task - 查看reamde](#step2: 创建task - 查看reamde)
        • [step3: 创建task的编排 - pipeline](#step3: 创建task的编排 - pipeline)
        • [step4: 创建secrets - ssh key/username](#step4: 创建secrets - ssh key/username)
        • [step5: 创建serviceaccount](#step5: 创建serviceaccount)
        • [step6: 创建pipelinerun](#step6: 创建pipelinerun)
      • 案例2:构建和推送镜像
        • [step1: 创建task - 拉取代码](#step1: 创建task - 拉取代码)
        • [step2: 创建task - 构建代码](#step2: 创建task - 构建代码)
        • [step3: 创建task - 打包镜像](#step3: 创建task - 打包镜像)
        • [step4: 创建secret - docker 认证](#step4: 创建secret - docker 认证)
        • [step5: 创建serviceaccount](#step5: 创建serviceaccount)
        • [step6: 创建task编排 - pipeline](#step6: 创建task编排 - pipeline)
        • [step7: 创建pipelinerun](#step7: 创建pipelinerun)

1. 官方介绍

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 解决方案

2. 组件

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 项目。

2.1 Tekton Pipelines

参考链接:https://tekton.dev/docs/concepts/concept-model/

Tekton Pipeline中有5类对象,核心理念是通过定义yaml定义构建过程。

  • task:task表示一个任务,task里可以定义一系列的steps,例如编译代码、构建镜像、推送镜像等,每个step实际由一个Pod执行。
  • taskRun:task只是定义了一个模版,taskRun才真正代表了一次实际的运行,当然你也可以自己手动创建一个taskRun,taskRun创建出来之后,就会自动触发task描述的构建任务。
  • PipelineResource:表示pipeline input资源,比如github上的源码,或者pipeline output资源,例如一个容器镜像或者构建生成的jar包等,目前已经弃用。
  • Pipeline:一个或多个task、PipelineResource以及各种定义参数的集合。
  • PipelineRun:类似task和taskRun的关系,pipelineRun也表示某一次实际运行的pipeline,下发一个pipelineRun CRD实例到kubernetes后,同样也会触发一次pipeline的构建。

2.2 部署pipeline

# install
kubectl apply --filename https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml

# moinitor
kubectl get pods --namespace tekton-pipelines --watch

2.3 部署dashborad

# 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的关系

2.3.1 task

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: git@jihulab.com:cs-test-group1/kxwang/test.git
2.3.2 taskrun

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"
2.3.3 Pipeline

一个 TaskRun 只能执行一个 Task,当需要编排多个 Task 的时候就需要用到 Pipeline。

Pipeline 是一个编排 Task 的模板。

  • Pipeline 的 params 声明了执行时需要的入参。
  • Pipeline 的 spec.tasks 定义了需要编排的 Task。
  • Tasks 是一个数组,数组中的 task 并不是通过数组声明的顺序去执行的,而是通过 runAfter 来声明 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
2.3.4 PipelineRun

和 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"

3. 案例

案例1: 拉取代码并查看readme

step1: 创建task - 拉取代码

安装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
step2: 创建task - 查看reamde

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
step3: 创建task的编排 - pipeline

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
step4: 创建secrets - ssh key/username

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: <cat ~/.ssh/id_rsa | base64 -w0>
    known_hosts: <cat ~/.ssh/known_hosts | base64 -w0>

创建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: kxwang@jihulab.com
  password: xxxxxxx
step5: 创建serviceaccount

gitlab-sa.yaml

\apiVersion: 复制代码
apiVersion: v1
kind: ServiceAccount
metadata:
  name: gitlab-sa
secrets:
- name: gitlab-auth
- name: gitlab-ssh
step6: 创建pipelinerun

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: git@jihulab.com:cs-test-group1/kxwang/test.git
    - name: branch-name
      value: master

案例2:构建和推送镜像

step1: 创建task - 拉取代码

同上

step2: 创建task - 构建代码

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: {}
step3: 创建task - 打包镜像

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
step4: 创建secret - docker 认证

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: wkx_0422@163.com
  password: 123456
step5: 创建serviceaccount

gitlab-sa.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: gitlab-sa
secrets:
- name: gitlab-auth
- name: gitlab-ssh
- name: docker-credentials
step6: 创建task编排 - pipeline

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)
step7: 创建pipelinerun

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
相关推荐
年薪丰厚12 分钟前
如何在K8S集群中查看和操作Pod内的文件?
docker·云原生·容器·kubernetes·k8s·container
zhangj112513 分钟前
K8S Ingress 服务配置步骤说明
云原生·容器·kubernetes
岁月变迁呀15 分钟前
kubeadm搭建k8s集群
云原生·容器·kubernetes
墨水\\15 分钟前
二进制部署k8s
云原生·容器·kubernetes
Source、16 分钟前
k8s-metrics-server
云原生·容器·kubernetes
颜淡慕潇21 分钟前
【K8S问题系列 |19 】如何解决 Pod 无法挂载 PVC问题
后端·云原生·容器·kubernetes
ProtonBase27 分钟前
如何从 0 到 1 ,打造全新一代分布式数据架构
java·网络·数据库·数据仓库·分布式·云原生·架构
大熊程序猿3 小时前
K8s证书过期
云原生·容器·kubernetes
kaixin_learn_qt_ing9 小时前
Bazel CI
ci/cd
Karoku06612 小时前
【k8s集群应用】kubeadm1.20高可用部署(3master)
运维·docker·云原生·容器·kubernetes