PipelineRuns

PipelineRun 是一种 Kubernetes 自定义资源,用于实例化一个 Pipeline 以供执行。PipelineRuns 负责执行 Pipeline 中定义的 Tasks 并管理其生命周期,从而提供一种运行端到端 CI/CD 工作流的方式。

为什么需要 PipelineRuns

CI/CD 工作流挑战

在 CI/CD 系统中,工作流执行会面临多种挑战:

  • 工作流编排:需要按特定顺序协调多个任务
  • 资源协调:需要管理多个任务之间的资源
  • 数据共享:需要在工作流中的任务之间共享数据
  • 执行跟踪:需要跟踪整个工作流的进度
  • 错误处理:需要在任务级和工作流级处理失败
  • 可审计性:需要保留所有工作流执行的记录

Tekton 的解决方案

Tekton PipelineRuns 通过以下方式解决这些挑战:

  • 工作流实例:每个 PipelineRun 表示一次具有特定输入的 Pipeline 执行
  • 编排:PipelineRuns 根据依赖关系管理 Tasks 的执行顺序
  • 资源绑定:PipelineRuns 将实际资源绑定到 Pipeline 的需求上
  • 状态跟踪:PipelineRuns 跟踪每个 Task 的执行状态
  • 结果传递:PipelineRuns 支持在 Tasks 之间共享结果
  • Kubernetes 集成:PipelineRuns 利用 Kubernetes 进行资源管理和调度

优势

  • 隔离性:每个 PipelineRun 独立执行,支持同一 Pipeline 的并行运行
  • 可追溯性:PipelineRuns 提供详细的执行历史和日志
  • 灵活性:PipelineRuns 可以覆盖 Pipeline 参数和 workspace 绑定
  • 可复用性:同一个 Pipeline 可以通过不同的 PipelineRuns 使用不同输入来执行
  • 集成性:PipelineRuns 可以通过 Kubernetes API 由各种系统触发
  • 可观测性:可以通过 Kubernetes 工具监控 PipelineRun 的状态和日志

场景

PipelineRuns 适用于多种场景,包括:

  • Application CI/CD:构建、测试和部署应用
  • Infrastructure as Code:配置和管理基础设施
  • 发布管理:协调复杂的发布流程
  • 定时工作流:按计划运行工作流
  • 事件驱动工作流:响应外部事件触发工作流

约束与限制

  • PipelineRuns 在单个 Kubernetes 集群内执行
  • 启动后,PipelineRun 参数不能修改
  • PipelineRuns 对失败的 Tasks 具有有限的重试能力
  • PipelineRun 的执行时间受 Kubernetes pod 超时限制
  • PipelineRuns 一旦开始执行就不能暂停(除 "finally" tasks 外)

原则

PipelineRun 执行模型

当创建 PipelineRun 时:

  1. Tekton 验证 PipelineRun 规范
  2. Tekton 为 Pipeline 中的每个 Task 创建 TaskRuns
  3. TaskRuns 根据其依赖关系执行
  4. 来自 Tasks 的结果会被收集,并可供后续 Tasks 使用
  5. 随着每个 TaskRun 完成,PipelineRun 状态会更新
  6. 在所有其他 Tasks 完成或失败后,执行 "finally" Tasks
  7. 当所有 TaskRuns 完成时,PipelineRun 完成

PipelineRun 状态

PipelineRun 的状态提供有关执行的详细信息:

  1. 总体状态(Running、Succeeded、Failed 等)
  2. 开始和完成时间
  3. 各个 TaskRun 的状态
  4. Task 结果
  5. 失败原因(如果适用)
  6. 用于访问日志的 TaskRun 名称

配置示例

基本 PipelineRun 示例

apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  name: build-deploy-app-run
spec:
  pipelineRef:
    name: build-deploy-app
  params:
    - name: image-name
      value: my-registry/my-app:latest
    - name: deployment-name
      value: my-app
  workspaces:
    - name: source
      persistentVolumeClaim:
        claimName: app-source-pvc

使用内嵌 Pipeline 定义的 PipelineRun

apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  name: simple-pipeline-run
spec:
  pipelineSpec:
    params:
      - name: message
        type: string
    tasks:
      - name: print-message
        taskSpec:
          params:
            - name: message
              type: string
          steps:
            - name: print
              image: ubuntu
              script: |
                echo "$(params.message)"
        params:
          - name: message
            value: "$(params.message)"
  params:
    - name: message
      value: "Hello, Tekton Pipeline!"

重要参数

Timeout

Timeout 允许设置 PipelineRun 执行的最长持续时间。

使用场景

  • 防止长时间运行的 Pipelines 无限占用资源
  • 确保 CI/CD 工作流在合理时间内完成
  • 处理卡住或死锁的 Tasks
  • 为 Pipeline 执行的不同阶段设置不同的超时限制

原则

Timeout 的特点如下:

  • 在 PipelineRun 规范中使用 timeouts 字段指定(旧的 timeout 字段已弃用)
  • 应用于整个 PipelineRun 执行或特定部分(tasks、finally)
  • 从第一个 Task 开始到最后一个 Task 完成进行计时
  • 如果超出,将导致 PipelineRun 失败
  • 必须遵循约束:timeouts.pipeline >= timeouts.tasks + timeouts.finally
  • 重要:如果任何子字段设置为 "0",则该部分没有超时。要将 timeouts.taskstimeouts.finally 设置为 "0",还必须将 timeouts.pipeline 也设置为 "0"

Timeout 字段

  • pipeline:整个 PipelineRun 的最大持续时间
  • tasks:所有非 finally tasks 的最大持续时间
  • finally:所有 finally tasks 的最大持续时间

配置示例

示例 1:标准 timeout 配置

apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  name: build-deploy-with-timeout
spec:
  pipelineRef:
    name: build-deploy-app
  timeouts:
    pipeline: "1h"    # Total pipeline timeout
    tasks: "45m"      # Timeout for all regular tasks
    finally: "15m"    # Timeout for finally tasks
  params:
    - name: image-name
      value: my-registry/my-app:latest

示例 2:tasks 和 finally 不设置 timeout(要求 pipeline timeout 为 0)

apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  name: build-deploy-no-timeout
spec:
  pipelineRef:
    name: build-deploy-app
  timeouts:
    pipeline: "0"     # No overall timeout
    tasks: "0"        # No timeout for regular tasks
    finally: "0"      # No timeout for finally tasks
  params:
    - name: image-name
      value: my-registry/my-app:latest

注意

  • 示例 1 满足约束:pipeline (1h) >= tasks (45m) + finally (15m)
  • 示例 2 展示了如何通过将所有值设为 "0" 来禁用 timeout

ServiceAccount

ServiceAccount 允许指定用于身份验证的 Kubernetes ServiceAccount。

使用场景

  • 为访问私有容器镜像仓库提供凭据
  • 与云提供商进行身份验证
  • 授权访问 Kubernetes 资源
  • 为 Git 操作提供凭据

原则

ServiceAccounts:

  • 可在 PipelineRun 级别为所有 Tasks 指定
  • 可通过 taskRunSpecs 映射到特定 Tasks
  • 通过 Kubernetes secrets 提供凭据
  • 支持对外部资源的安全访问

配置示例

apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  name: build-deploy-with-service-account
spec:
  pipelineRef:
    name: build-deploy-app
  taskRunTemplate:
    serviceAccountName: pipeline-service-account
  params:
    - name: image-name
      value: my-registry/my-app:latest

Pod Template

Pod Template 允许指定一个 Pod template,作为执行每个 Task 的 Pod 配置基础。

TIP

有关 Pod Templates 的更多信息,请参阅 Pod Templates

使用场景

  • 为特定硬件需求设置 node selectors
  • 为专用节点配置 tolerations
  • 指定 security contexts 以增强安全性
  • 在 Pod 级别设置资源限制和请求
  • 配置 affinity 规则以更好地利用资源
  • 为 Pods 添加自定义注解或标签

原则

Pod Templates:

  • 默认应用于 PipelineRun 中的所有 Tasks,除非被 taskRunSpecs 覆盖
  • 遵循 Kubernetes Pod template 规范
  • 可被 taskRunSpecs 中针对特定 Task 的配置覆盖
  • 使 PipelineRun 中所有 Tasks 的 Pod 配置保持一致
  • 支持所有标准的 Kubernetes Pod template 字段

配置示例

apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  name: build-deploy-with-pod-template
spec:
  pipelineRef:
    name: build-deploy-app
  taskRunTemplate:
    serviceAccountName: default
    # Global Pod template for all Tasks in the PipelineRun
    podTemplate:
      nodeSelector:
        disktype: ssd
        environment: production
      tolerations:
      - key: "dedicated"
        operator: "Equal"
        value: "pipeline"
        effect: "NoSchedule"
      securityContext:
        runAsNonRoot: true
        runAsUser: 1000
        fsGroup: 2000
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: kubernetes.io/os
                operator: In
                values:
                - linux
  params:
    - name: image-name
      value: my-registry/my-app:latest

TaskRunSpecs

TaskRunSpecs 允许通过指定 PipelineTaskRunSpec 列表来定制 PipelineRun 中单个 TaskRun 的配置,从而为每个 task 设置 ServiceAccountName、Pod template、computeResourcesMetadata

使用场景

  • 为不同 Tasks 应用不同的 ServiceAccounts,以实现细粒度访问控制
  • 设置 Task 级 Pod templates,以满足不同的资源或安全要求
  • 配置 Task 级元数据,以便更好地组织和跟踪
  • 覆盖针对特定 Tasks 的全局 PipelineRun 配置
  • 为 Pipeline 的不同阶段应用不同的计算资源或 node selectors

原则

TaskRunSpecs:

  • 覆盖为整个 Pipeline 设置的 Pod template
  • 允许对 Task 执行环境进行细粒度控制
  • 可用于满足特定的安全、资源或调度需求
  • 支持为 Pipeline 的不同阶段配置不同内容
  • 支持所有标准的 Kubernetes Pod template 规范
  • 可与全局 PipelineRun 配置组合使用

配置字段

每个 TaskRunSpec 支持以下字段:

  • pipelineTaskName:要应用配置的 Pipeline task 名称
  • serviceAccountName:该特定 Task 使用的 ServiceAccount
  • podTemplate:该 Task 专属的 Pod template 配置
  • computeResources:该 Task 的计算资源需求(requests 和 limits),会覆盖 Task spec 中定义的默认值
  • metadata:TaskRun 的元数据配置

配置示例

示例 1:包含 ServiceAccount 和 Pod Template 的基本 TaskRunSpecs

apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  name: build-deploy-with-taskrunspecs
spec:
  pipelineRef:
    name: build-deploy-app
  taskRunSpecs:
    - pipelineTaskName: build
      serviceAccountName: build-service-account
      podTemplate:
        nodeSelector:
          disktype: ssd
          environment: build
        tolerations:
        - key: "dedicated"
          operator: "Equal"
          value: "build"
    - pipelineTaskName: deploy
      serviceAccountName: deploy-service-account
      podTemplate:
        nodeSelector:
          disktype: ssd
          environment: production
        tolerations:
        - key: "dedicated"
          operator: "Equal"
          value: "deploy"
          effect: "NoSchedule"
  params:
    - name: image-name
      value: my-registry/my-app:latest

示例 2:带有高级 Pod 配置的 TaskRunSpecs

apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  name: advanced-taskrunspecs
spec:
  pipelineRef:
    name: multi-stage-pipeline
  taskRunSpecs:
    - pipelineTaskName: build
      serviceAccountName: build-sa
      podTemplate:
        nodeSelector:
          gpu: available
          disktype: nvme
        securityContext:
          runAsNonRoot: true
          runAsUser: 1000
    - pipelineTaskName: test
      serviceAccountName: test-sa
      podTemplate:
        nodeSelector:
          environment: testing
        tolerations:
        - key: "test-only"
          operator: "Equal"
          value: "true"
          effect: "NoSchedule"
    - pipelineTaskName: deploy
      serviceAccountName: deploy-sa
      podTemplate:
        nodeSelector:
          environment: production
        affinity:
          nodeAffinity:
            requiredDuringSchedulingIgnoredDuringExecution:
              nodeSelectorTerms:
              - matchExpressions:
                - key: kubernetes.io/os
                  operator: In
                  values:
                  - linux

示例 3:带有 Metadata 配置的 TaskRunSpecs

apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  name: taskrunspecs-with-metadata
spec:
  pipelineRef:
    name: build-test-deploy
  taskRunSpecs:
    - pipelineTaskName: build
      serviceAccountName: build-sa
      metadata:
        labels:
          stage: build
          environment: development
        annotations:
          tekton.dev/description: "Build stage with optimized resources"
      podTemplate:
        nodeSelector:
          disktype: ssd
    - pipelineTaskName: deploy
      serviceAccountName: deploy-sa
      metadata:
        labels:
          stage: deploy
          environment: production
        annotations:
          tekton.dev/description: "Production deployment stage"
      podTemplate:
        nodeSelector:
          environment: production

示例 4:TaskRunSpecs 覆盖全局 Pod Template

TaskRunSpecs 可以覆盖 PipelineRun 级别设置的全局 Pod template:

apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  name: override-global-template
spec:
  pipelineRef:
    name: build-deploy-app
  taskRunTemplate:
    serviceAccountName: default
    # Global Pod template for all Tasks
    podTemplate:
      nodeSelector:
        disktype: ssd
      tolerations:
      - key: "general"
        operator: "Equal"
        value: "pipeline"
        effect: "NoSchedule"
  # Task-specific overrides
  taskRunSpecs:
    - pipelineTaskName: build
      podTemplate:
        nodeSelector:
          disktype: nvme
          gpu: available
        tolerations:
        - key: "build-only"
          operator: "Equal"
          value: "true"
          effect: "NoSchedule"
    - pipelineTaskName: deploy
      podTemplate:
        nodeSelector:
          environment: production
        tolerations:
        - key: "deploy-only"
          operator: "Equal"
          value: "true"
          effect: "NoSchedule"
  params:
    - name: image-name
      value: my-registry/my-app:latest

示例 5:为特定 Tasks 覆盖 computeResources

使用 taskRunSpecs[].computeResources 为单个 Tasks 分配不同的 CPU/内存配额, 覆盖 Task spec 中定义的任何默认值:

apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  name: pipeline-run-with-compute-resources
spec:
  pipelineRef:
    name: build-test-deploy
  taskRunSpecs:
    - pipelineTaskName: build
      # Allocate more resources for the resource-intensive build step
      computeResources:
        requests:
          cpu: "1"
          memory: "2Gi"
        limits:
          cpu: "2"
          memory: "4Gi"
    - pipelineTaskName: test
      # Use lighter resources for the test step
      computeResources:
        requests:
          cpu: "500m"
          memory: "512Mi"
        limits:
          cpu: "1"
          memory: "1Gi"
NOTE

taskRunSpecs 中的 computeResources 是一个 Beta 特性,并且需要在 Tekton feature flags ConfigMap 中将 enable-api-fields 设置为 beta(或 alpha)。在平台的默认安装中,enable-api-fields 已经设置为 beta,因此该特性开箱即用——只有在它被手动设置为 stable 时,你才需要调整该标志。

Workspaces

Workspaces 允许在 Pipeline 中的 Tasks 之间共享数据。

使用场景

  • 在 build 和 test Tasks 之间共享源代码
  • 将构建产物传递给部署 Tasks
  • 在多个 Tasks 之间共享配置文件
  • 在 Pipeline 执行之间持久化数据

原则

Workspaces:

  • 在 Pipeline 中声明,并在 PipelineRun 中绑定
  • 可以由多种卷类型提供支持(PVC、ConfigMap、Secret 等)
  • 支持在不直接依赖的情况下共享数据
  • 支持不同访问模式(ReadOnly、ReadWrite)

配置示例

apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  name: build-test-with-workspace
spec:
  pipelineRef:
    name: build-test-pipeline
  workspaces:
    - name: source-code
      volumeClaimTemplate:
        spec:
          accessModes:
            - ReadWriteOnce
          resources:
            requests:
              storage: 1Gi
    - name: cache
      persistentVolumeClaim:
        claimName: build-cache-pvc

PipelineRun 状态管理

监控执行状态

PipelineRun 的 status 字段提供执行进度的详细信息:

status:
  completionTime: "2023-05-04T02:19:14Z"
  conditions:
    - lastTransitionTime: "2023-05-04T02:19:14Z"
      message: "Tasks Completed: 4, Skipped: 0"
      reason: Succeeded
      status: "True"
      type: Succeeded
  startTime: "2023-05-04T02:00:11Z"
  childReferences:
  - name: build-deploy-app-run-build
    pipelineTaskName: build
    kind: TaskRun

取消 PipelineRun

要取消正在运行的 PipelineRun,请更新其 spec.status 字段:

apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  name: build-deploy-app-run
spec:
  # [...other fields...]
  status: "Cancelled"

这会立即终止所有正在运行的 TaskRuns,并且不会执行待处理的 Tasks 或 finally Tasks。

优雅停止 PipelineRun

要优雅地停止 PipelineRun,并允许 finally Tasks 执行:

apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  name: build-deploy-app-run
spec:
  # [...other fields...]
  status: "StoppedRunFinally"

这会完成当前正在运行的 Tasks,但不会启动新的 Tasks,finally Tasks 除外。

参考