生产环境 DevOps 实战 | 第 4 天:Tekton 核心概念入门——Task、Pipeline、PipelineRun、Step 详解

第 4/60 天

引言

在上一篇文章中,我们描绘了从代码提交到上线的全链路蓝图,其中 Tekton 作为 CI(持续集成)引擎,是整个流水线的核心驱动力。Tekton 是 Kubernetes 原生的云原生 CI/CD 框架,与 Jenkins 等传统工具不同,它把流水线的每个组件都定义为 Kubernetes CRD(自定义资源),这意味着你可以用 kubectl 管理流水线,用 Kubernetes RBAC 控制权限,让 CI 系统与基础设施无缝融合。

然而,Tekton 的 Kubernetes 原生特性也带来了一个陡峭的学习曲线——Task、Pipeline、PipelineRun、Step、Workspaces、Results、Triggers……这些概念之间的关系是什么?如何在 YAML 中正确地编排它们?本文将用最清晰的方式,逐层拆解 Tekton 的五大核心概念,并通过可执行的 YAML 示例带你快速上手。

核心概念

Tekton 的层次结构

在深入每个概念之前,先理解 Tekton 的层级关系:

Task (任务模板)
├── Step (步骤) —— 容器中执行的命令
└── Step (步骤)
Pipeline (流水线模板)
├── Task (引用 Task 定义,指定参数/Workspace)
└── Task
TaskRun (任务运行实例) —— 执行 Task 产生
PipelineRun (流水线运行实例) —— 执行 Pipeline 产生

关键原则: Task 和 Pipeline 是模板(定义”做什么”),TaskRun 和 PipelineRun 是运行实例(定义”何时做、结果如何”)。

五大核心概念对比

概念 类型 作用 类比 Jenkins
Step 最小执行单元 一个容器中执行的命令 一个 Shell 命令
Task 任务模板 一组有序的 Step 集合 一个 Job 中的构建步骤
TaskRun 任务运行实例 执行 Task 并记录结果 一次 Job 构建
Pipeline 流水线模板 编排多个 Task 的执行顺序与依赖 一个 Pipeline 定义
PipelineRun 流水线运行实例 执行 Pipeline 并记录结果 一次 Pipeline 构建

关键机制

  • Workspaces(工作区):Task 之间共享数据的卷挂载抽象,替代传统的 storage 配置
  • Results(结果):Task 的输出结果,可传递给下游 Task 作为参数
  • Params(参数):Task/Pipeline 的输入参数,支持字符串、数组等类型
  • Conditions(条件):控制 Task 执行的条件判断(Tekton v1 中已弃用,推荐使用 WhenExpression

实战步骤

1. 理解 Step:最小的执行单元

Step 是 Tekton 中最基本的构建块——它定义了一个容器中要执行的命令。每个 Step 运行在独立的容器中,共享同一个 Pod 的存储卷和网络。

apiVersion: tekton.dev/v1
kind: Task
metadata:
  name: hello-world
spec:
  steps:
    - name: say-hello
      image: ubuntu:22.04
      script: |
        #!/usr/bin/env bash
        echo "Hello, Tekton!"
        echo "当前时间: $(date)"
    - name: show-files
      image: alpine:3.18
      script: |
        #!/bin/sh
        ls -la /workspace/

关键点: 同一个 Task 内的 Step 运行在同一个 Pod 中,但每个 Step 有独立的容器。Step 之间通过共享的 workspace 卷传递数据。

2. Task 与 TaskRun:任务模板与执行

Task 定义一组有序的 Step。TaskRun 触发 Task 执行,并记录详细的运行日志和状态。

# task-build.yaml — 定义一个代码构建任务
apiVersion: tekton.dev/v1
kind: Task
metadata:
  name: build-app
spec:
  params:
    - name: source-path
      type: string
      description: 源码路径
      default: /workspace/source
  workspaces:
    - name: source
      description: 源码工作区
    - name: output
      description: 构建产物输出
  steps:
    - name: compile
      image: golang:1.21
      script: |
        #!/usr/bin/env bash
        cd $(workspaces.source.path)/$(params.source-path)
        go build -o $(workspaces.output.path)/app .
        echo "编译完成"
    - name: test
      image: golang:1.21
      script: |
        #!/usr/bin/env bash
        cd $(workspaces.source.path)/$(params.source-path)
        go test ./... -v
    - name: package
      image: alpine:3.18
      script: |
        #!/bin/sh
        cd $(workspaces.output.path)
        tar -czf /workspace/output/app.tar.gz app
        echo "打包完成: app.tar.gz"

使用 tkn CLI 或 kubectl 创建 TaskRun 来执行:

# 方式一:使用 tkn CLI
tkn task start build-app 
  --workspace name=source,emptyDir="" 
  --workspace name=output,emptyDir="" 
  --showlog

# 方式二:直接定义 TaskRun YAML
cat <<EOF | kubectl apply -f -
apiVersion: tekton.dev/v1
kind: TaskRun
metadata:
  name: build-app-run-001
spec:
  taskRef:
    name: build-app
  params:
    - name: source-path
      value: ./cmd/api
  workspaces:
    - name: source
      emptyDir: {}
    - name: output
      emptyDir: {}
EOF

查看 TaskRun 状态:

# 查看所有 TaskRun
kubectl get taskrun

# 查看特定 TaskRun 的详细信息
kubectl describe taskrun build-app-run-001

# 查看运行日志
kubectl logs --selector=tekton.dev/taskRun=build-app-run-001 --all-containers

3. Pipeline:多阶段流水线编排

Pipeline 将多个 Task 按依赖关系编排成完整的流水线。runAfter 控制执行顺序,Workspaces 和 Results 实现 Task 间的数据传递。

# pipeline-ci.yaml — 完整 CI 流水线
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
  name: ci-pipeline
spec:
  params:
    - name: repo-url
      type: string
      description: Git 仓库地址
    - name: branch
      type: string
      description: 分支名称
      default: main
  workspaces:
    - name: shared-workspace
      description: 所有 Task 共享的工作区
  tasks:
    - name: clone
      taskRef:
        name: git-clone
      params:
        - name: url
          value: $(params.repo-url)
        - name: revision
          value: $(params.branch)
      workspaces:
        - name: output
          workspace: shared-workspace

    - name: lint
      taskRef:
        name: golangci-lint
      runAfter:
        - clone
      workspaces:
        - name: source
          workspace: shared-workspace

    - name: build
      taskRef:
        name: build-app
      runAfter:
        - lint
      params:
        - name: source-path
          value: .
      workspaces:
        - name: source
          workspace: shared-workspace
        - name: output
          workspace: shared-workspace

    - name: test
      taskRef:
        name: run-tests
      runAfter:
        - build
      workspaces:
        - name: source
          workspace: shared-workspace

    - name: image-build-push
      taskRef:
        name: kaniko-build
      runAfter:
        - test
      params:
        - name: IMAGE
          value: harbor.stellardata.top/devops/app:$(tasks.build.results.commit-sha)
      workspaces:
        - name: source
          workspace: shared-workspace

4. PipelineRun:触发流水线执行

PipelineRun 是 Pipeline 的运行实例。创建 PipelineRun 时,可以覆盖参数、绑定 Workspace,Tekton 会自动为每个 Task 创建对应的 TaskRun。

# pipelinerun-ci.yaml — 触发流水线
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  name: ci-pipeline-run-$(context.pipelineRun.uid)
  annotations:
    tekton.dev/description: "生产环境 CI 流水线"
spec:
  pipelineRef:
    name: ci-pipeline
  params:
    - name: repo-url
      value: https://github.com/example/app.git
    - name: branch
      value: main
  workspaces:
    - name: shared-workspace
      volumeClaimTemplate:
        spec:
          accessModes:
            - ReadWriteOnce
          resources:
            requests:
              storage: 5Gi
  timeouts:
    pipeline: 30m
    tasks: 15m

使用 tkn CLI 启动流水线:

# 启动流水线并实时查看日志
tkn pipeline start ci-pipeline 
  --param repo-url=https://github.com/example/app.git 
  --param branch=main 
  --workspace name=shared-workspace,claimName=workspace-pvc 
  --showlog

# 查看所有 PipelineRun
tkn pipelinerun list

# 查看特定 PipelineRun 的日志
tkn pipelinerun logs ci-pipeline-run-xxx -f

5. Results 机制:Task 间传递数据

Results 是 Tekton 中最强大的数据传递机制之一。Task 可以将关键信息(如镜像标签、版本号、构建 ID)输出为 Results,然后通过 $(tasks.<task-name>.results.<result-name>) 语法在 Pipeline 中引用。

# task-with-results.yaml — 输出结果的 Task
apiVersion: tekton.dev/v1
kind: Task
metadata:
  name: generate-version
spec:
  results:
    - name: version
      description: 生成的版本号
    - name: commit-sha
      description: Git 提交 SHA
  steps:
    - name: generate
      image: alpine:3.18
      script: |
        #!/bin/sh
        # 生成语义化版本号
        VERSION="v1.0.$(date +%Y%m%d%H%M%S)"
        COMMIT=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")

        # 写入结果(写入指定路径的文件)
        printf "%s" "$VERSION" > $(results.version.path)
        printf "%s" "$COMMIT" > $(results.commit-sha.path)

        echo "版本: $VERSION, Commit: $COMMIT"

在 Pipeline 中引用 Results:

tasks:
  - name: generate-version
    taskRef:
      name: generate-version

  - name: build-and-push
    taskRef:
      name: kaniko-build
    runAfter:
      - generate-version
    params:
      - name: IMAGE_TAG
        value: $(tasks.generate-version.results.version)
      - name: COMMIT_SHA
        value: $(tasks.generate-version.results.commit-sha)

6. WhenExpression:条件执行

在 Tekton v1 中,使用 when 字段替代已弃用的 Conditions,实现条件分支:

apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
  name: conditional-pipeline
spec:
  tasks:
    - name: check-branch
      taskRef:
        name: check-branch-task

    - name: deploy-prod
      taskRef:
        name: deploy
      when:
        - input: $(params.branch)
          operator: in
          values: ["main", "release"]
      runAfter:
        - check-branch

    - name: deploy-staging
      taskRef:
        name: deploy
      when:
        - input: $(params.branch)
          operator: in
          values: ["develop", "staging"]
      runAfter:
        - check-branch

常见问题

Q1: Task 和 Pipeline 中 Step 超过多少会超时?

每个 Step 默认超时时间由 Task 的 stepTimeout 字段控制,默认无限制。建议在 Pipeline 层面设置 timeouts.pipelinetimeouts.tasks 来兜底。生产环境建议 Pipeline 超时设为 30 分钟,单个 Task 超时设为 15 分钟。

Q2: Workspace 有哪些类型?

Workspace 支持以下类型:emptyDir(临时卷)、persistentVolumeClaim(持久卷)、configMapsecrethostPath(不推荐生产使用)、volumeClaimTemplate(PipelineRun 动态创建 PVC)。生产环境建议使用 persistentVolumeClaimvolumeClaimTemplate

Q3: TaskRun 和 PipelineRun 的 Pod 生命周期是怎样的?

每个 TaskRun 对应一个 Pod,Pod 生命周期与 TaskRun 相同。TaskRun 完成后,Pod 进入 CompletedError 状态。可通过 kubectl delete taskrun <name> 清理 Pod。建议配置自动清理策略,避免大量已完成的 Pod 占用资源。

Q4: 如何调试失败的 Step?

使用 kubectl logs 查看失败的 Step 日志,或使用 tkn taskrun logs <name> -f 实时查看。如果 Step 定义了 onError: continue,即使失败也不会终止 Task。生产环境建议在调试阶段使用 --showlog 参数,运行阶段配置日志采集到 ELK/Loki。

Q5: Tekton 如何支持并行执行?

Pipeline 中不依赖 runAfter 的 Task 默认并行执行。例如,lintunit-test 如果都只依赖 clone,则会并行运行。可以通过 runAfter 精确控制依赖关系,同时利用 Kubernetes 的调度能力实现最大并行度。

总结

Tekton 的核心概念设计体现了 Kubernetes 原生的哲学——一切皆资源。理解这五个概念的关系是掌握 Tekton 的关键:

  1. Step → Task → Pipeline模板层,定义了”做什么”;TaskRun → PipelineRun运行层,记录了”做的情况”
  2. Workspaces 是 Task 间的数据通道,替代了传统 CI 的共享存储概念
  3. Results 机制让 Task 之间可以传递结构化数据,实现参数化编排
  4. WhenExpression 替代了旧版 Conditions,实现更灵活的条件分支
  5. 所有资源都是 Kubernetes CRD,可以用 kubectltkn CLI 或 API 统一管理

下一篇文章我们将深入 Argo CD 的核心概念,了解 Application、Project 和 Sync 策略如何实现 GitOps 持续交付。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容