Pipelines

Pipeline 是按定义顺序执行的一组 Task,用于实现 CI/CD 工作流。Pipeline 定义了 Task 的执行流程,包括其依赖关系、参数和工作区,使您能够创建复杂的自动化工作流。

为什么需要 Pipeline

传统 CI/CD 面临的挑战

传统 CI/CD 系统在创建复杂工作流时通常面临以下挑战:

  • 复杂性管理:难以管理不同阶段之间的依赖关系
  • 可复用性:跨项目复用工作流组件的能力有限
  • 灵活性:难以使工作流适应不同需求
  • 可见性:对工作流执行情况和进度的了解有限

Tekton 的解决方案

Tekton Pipelines 通过以下方式应对这些挑战:

  • 声明式定义:Pipeline 定义为 Kubernetes Custom Resource
  • Task 编排:Pipeline 管理 Task 之间的执行顺序和依赖关系
  • 数据共享:Pipeline 通过 Workspaces 和 Results 促进 Task 之间的数据共享
  • 可复用性:Pipeline 组件可以跨项目共享和复用
  • 灵活性:Pipeline 支持条件执行和动态参数

优势

  • 模块化:将复杂工作流拆分为可复用的 Task
  • 依赖管理:定义清晰的 Task 之间的依赖关系
  • 并行执行:并发执行相互独立的 Task
  • 条件执行:根据条件运行 Task
  • 结果共享:通过 Results 在 Task 之间传递数据
  • 工作区共享:通过 Workspaces 在 Task 之间共享文件和数据
  • 可复用性:创建可复用的工作流模板

场景

Pipeline 适用于各种场景,包括:

  • CI/CD 工作流:构建、测试和部署应用程序
  • 多环境部署:部署到开发、预发布和生产环境
  • 复杂构建流程:管理构建步骤之间的依赖关系
  • 发布管理:协调多个组件之间的发布活动
  • 基础设施自动化:编排基础设施的预配和配置

Pipeline 执行模型

通过 PipelineRun 执行 Pipeline 时:

  1. Tekton 分析 Pipeline,以确定 Task 的执行顺序
  2. 没有依赖关系的 Task 会立即开始执行
  3. 具有依赖关系的 Task 会等待其依赖项完成
  4. 可以并行运行的 Task 会并发执行
  5. 当所有 Task 都已完成,或关键 Task 失败时,Pipeline 执行完成

核心概念

Task 依赖关系

Pipeline 中的 Task 可以通过以下两种方式相互依赖:

  1. 顺序依赖:使用 runAfter 字段指定某个 Task 应在另一个 Task 之后运行
  2. 数据依赖:某个 Task 使用另一个 Task 的 Results

示例:

apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
  name: order-tasks
spec:
  tasks:
    - name: task1
      taskRef:
        name: task1
    - name: task2
      taskRef:
        name: task2
      runAfter:
        - task1
      params:
        - name: param1
          value: "$(tasks.task1.results.result)"
    - name: task3
      taskRef:
        name: task3
      params:
        - name: param1
          value: "$(tasks.task2.results.result)"

Parameters

Parameters 允许你在执行期间向 Pipeline 传递值。你可以使用它们自定义 Pipeline 中 Task 的行为。

使用场景

  • 配置构建选项
  • 指定部署目标
  • 设置版本号
  • 控制功能标志

原则

Parameters:

  • 在 Pipeline 规范中声明
  • 创建 PipelineRun 时传递
  • 可供 Pipeline 中的 Task 使用
  • 可以具有默认值

配置示例

apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
  name: build-and-deploy
spec:
  params:
    - name: image-name
      type: string
      description: The name of the image to build
    - name: environment
      type: string
      description: The environment to deploy to
      default: "development"
  tasks:
    - name: build
      taskRef:
        name: build-image
      params:
        - name: image
          value: "$(params.image-name)"

Workspaces

Workspaces 允许 Pipeline 中的 Task 共享数据。它们在 Pipeline 级别声明,然后映射到各个 Task。

使用场景

  • 在 Task 之间共享源代码
  • 在 Task 之间传递构建工件
  • 共享配置文件
  • 在多次 Pipeline 执行之间维护状态

原则

Pipeline 中的 Workspaces:

  • 在 Pipeline 规范中声明
  • 映射到 Task 的 Workspaces
  • 创建 PipelineRun 时绑定到实际存储
  • 可以由多个 Task 共享

配置示例

apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
  name: build-test-deploy
spec:
  workspaces:
    - name: source-code
      description: The workspace containing the source code
  tasks:
    - name: fetch-source
      taskRef:
        name: git-clone
      workspaces:
        - name: output
          workspace: source-code
    - name: build
      taskRef:
        name: build-app
      workspaces:
        - name: source
          workspace: source-code
      runAfter:
        - fetch-source

Results

Results 允许 Task 生成输出值,供 Pipeline 中的其他 Task 使用。

使用场景

  • 传递构建版本信息
  • 共享生成的工件路径
  • 传递测试结果
  • 传递部署 URL

原则

Pipeline 中的 Results:

  • 由 Task 生成
  • 使用 $(tasks.taskName.results.resultName) 语法引用
  • 作为后续 Task 的输入
  • 可以包含在 Pipeline results 中

配置示例

apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
  name: build-and-deploy
spec:
  tasks:
    - name: generate-version
      taskRef:
        name: semver
      results:
        - name: version
    - name: build
      taskRef:
        name: build-image
      params:
        - name: version
          value: "$(tasks.generate-version.results.version)"
      runAfter:
        - generate-version
  results:
    - name: build-version
      value: "$(tasks.generate-version.results.version)"

Finally Tasks

Finally Tasks 会在 Pipeline 中的所有其他 Task 完成后执行,无论执行成功还是失败。它们适用于清理操作或发送通知。

使用场景

  • 清理资源
  • 发送通知
  • 归档日志
  • 生成报告

原则

Finally Tasks:

  • 在所有其他 Task 完成后运行
  • 无论 Pipeline 成功还是失败都会运行
  • 不能依赖其他 Task
  • 不能被其他 Task 依赖

配置示例

apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
  name: build-test-deploy
spec:
  tasks:
    - name: build
      taskRef:
        name: build-app
    - name: test
      taskRef:
        name: run-tests
      runAfter:
        - build
  finally:
    - name: cleanup
      taskRef:
        name: cleanup-resources
    - name: notify
      taskRef:
        name: send-notification

条件执行

可以使用 when 字段有条件地执行 Task,该字段允许你根据 Parameters 或 Results 指定条件。

使用场景

  • 仅在特定分支上部署
  • 根据代码更改运行测试
  • 根据用户输入执行 Task
  • 根据之前的结果跳过 Task

原则

条件执行:

  • 使用 when 字段定义
  • 可以引用 Parameters 和 Results
  • 支持各种运算符(in、notin)
  • 可以组合多个条件

配置示例

apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
  name: build-test-deploy
spec:
  params:
    - name: environment
      type: string
  tasks:
    - name: build
      taskRef:
        name: build-app
    - name: deploy-to-production
      taskRef:
        name: deploy
      runAfter:
        - build
      when:
        - input: "$(params.environment)"
          operator: in
          values: ["production"]

约束和限制

  • Pipelines 中的 Tasks 之间不能存在循环依赖
  • Pipeline 在执行期间不能修改自身定义
  • Task Results 必须先生成,才能被其他 Tasks 使用
  • Task Results 的大小受到限制(通常为几 KB)
  • Pipelines 处理动态创建 Task 的能力有限

参考资料