第 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.pipeline 和 timeouts.tasks 来兜底。生产环境建议 Pipeline 超时设为 30 分钟,单个 Task 超时设为 15 分钟。
Q2: Workspace 有哪些类型?
Workspace 支持以下类型:emptyDir(临时卷)、persistentVolumeClaim(持久卷)、configMap、secret、hostPath(不推荐生产使用)、volumeClaimTemplate(PipelineRun 动态创建 PVC)。生产环境建议使用 persistentVolumeClaim 或 volumeClaimTemplate。
Q3: TaskRun 和 PipelineRun 的 Pod 生命周期是怎样的?
每个 TaskRun 对应一个 Pod,Pod 生命周期与 TaskRun 相同。TaskRun 完成后,Pod 进入 Completed 或 Error 状态。可通过 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 默认并行执行。例如,lint 和 unit-test 如果都只依赖 clone,则会并行运行。可以通过 runAfter 精确控制依赖关系,同时利用 Kubernetes 的调度能力实现最大并行度。
总结
Tekton 的核心概念设计体现了 Kubernetes 原生的哲学——一切皆资源。理解这五个概念的关系是掌握 Tekton 的关键:
- Step → Task → Pipeline 是模板层,定义了”做什么”;TaskRun → PipelineRun 是运行层,记录了”做的情况”
- Workspaces 是 Task 间的数据通道,替代了传统 CI 的共享存储概念
- Results 机制让 Task 之间可以传递结构化数据,实现参数化编排
- WhenExpression 替代了旧版 Conditions,实现更灵活的条件分支
- 所有资源都是 Kubernetes CRD,可以用
kubectl、tknCLI 或 API 统一管理
下一篇文章我们将深入 Argo CD 的核心概念,了解 Application、Project 和 Sync 策略如何实现 GitOps 持续交付。















暂无评论内容