云原生的 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
相关推荐
Elastic 中国社区官方博客13 小时前
使用 Ollama 和 Kibana 在本地为 RAG 测试 DeepSeek R1
大数据·数据库·人工智能·elasticsearch·ai·云原生·全文检索
Linux运维老纪1 天前
windows部署deepseek之方法(The Method of Deploying DeepSeek on Windows)
linux·人工智能·分布式·云原生·运维开发·devops
Elastic 中国社区官方博客1 天前
Elastic Cloud Serverless 获得主要合规认证
大数据·数据库·elasticsearch·搜索引擎·云原生·serverless·全文检索
超级阿飞1 天前
在K8s中部署动态nfs存储provisioner
云原生·容器·kubernetes·nfs
柠檬豆腐脑2 天前
从前端到全栈:Jenkins 自动化部署 Node.js后端+ Vue.js 前端
前端·ci/cd·jenkins
赵渝强老师2 天前
【赵渝强老师】K8s中Pod探针的TCPSocketAction
云原生·容器·kubernetes
努力的小T2 天前
Linux二进制部署K8s集群的平滑升级教程
linux·运维·服务器·云原生·容器·kubernetes·云计算
2的n次方_2 天前
Eureka 服务注册和服务发现的使用
spring boot·spring cloud·云原生·eureka·服务发现
赵渝强老师3 天前
【赵渝强老师】K8s中Pod探针的ExecAction
云原生·容器·kubernetes
vibag3 天前
Kubernetes(一)
java·云原生·容器·kubernetes