news 2026/9/25 2:12:03

Tekton Pipeline 嵌套 Pipeline:Pipelines in Pipelines(pipelineRef / pipelineSpec)实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Tekton Pipeline 嵌套 Pipeline:Pipelines in Pipelines(pipelineRef / pipelineSpec)实战指南
  • 云原生
  • CI/CD
  • DevOps
  • 后端

【免费下载链接】pipeline

A cloud-native Pipeline resource.

项目地址:https://gitcode.com/gh_mirrors/pipelin/pipeline
点击查看免费下载

导读

本文基于 Tekton Pipeline 仓库的 Pipelines in Pipelines 官方文档,系统讲解如何在PipelineTask中通过pipelineRef或pipelineSpec引用/内嵌一个子 Pipeline,从而在单个父 Pipeline 中编排"克隆 → 安全扫描 → 通知"这类跨 Pipeline 的复合流程。读完本文你将掌握:如何启用 alpha 特性、如何编写嵌套 Pipeline 的 YAML、如何传递params与workspaces、底层控制器如何创建子PipelineRun并检测循环引用,以及当前 alpha 实现的主要限制与规避方案。

功能状态:Pipelines in Pipelines 是一个 alpha 特性,必须在enable-api-fieldsfeature flag 中显式设置为"alpha"才能使用。启用后,引用子 Pipeline 的PipelineTask会产生一个由父PipelineRun拥有的子PipelineRun;递归的pipelineRef引用会通过沿父PipelineRun的 owner 链向上遍历来检测,并快速失败、给出明确错误。当前实现的详细限制参见本文 Known Limitations 一节。

启用 alpha 特性:enable-api-fields: "alpha"

在开始编写嵌套 Pipeline 之前,必须先将enable-api-fieldsfeature flag 调整为"alpha"。该 flag 定义在 config/config-feature-flags.yaml,仓库中的默认值是"beta":

# config/config-feature-flags.yaml enable-api-fields: "beta"

将其改为"alpha"并重新应用该 ConfigMap 后,控制器才会允许在PipelineTask中指定pipelineRef或pipelineSpec。从源码验证这一点:在 pipeline_validation.go 的validateRefOrSpec中,只要检测到PipelineTask.PipelineRef或PipelineTask.PipelineSpec非空,就会调用config.ValidateEnabledAPIFields(ctx, pipelineRef, config.AlphaAPIFields)进行校验——即这两个字段被硬性绑定到 alpha 门控;只有当len(nonNilFields) == 0时才会退回 beta/stable 下只要求taskRef/taskSpec的检查。

另外,pipeline_types.go 中PipelineTask.PipelineRef的字段注释也明确指出:"This is an alpha field. You must set theenable-api-fieldsfeature flag to"alpha"for this field to be supported. When enabled, the referenced Pipeline is executed as a child PipelineRun owned by the parent PipelineRun."——与文档描述完全一致。

在PipelineTask中指定pipelineRef

在编排阶段定义嵌套 Pipeline 的最直接方式,是在PipelineTask上同时指定pipelineRef(与既有的taskRef、taskSpec并列)。下面的例子定义了一个名为security-scans的 Pipeline,它被运行在名为clone-scan-notify的父 Pipeline 内部:

apiVersion: tekton.dev/v1 kind: Pipeline metadata: name: security-scans spec: tasks: - name: scorecards taskRef: name: scorecards - name: codeql taskRef: name: codeql --- apiVersion: tekton.dev/v1 kind: Pipeline metadata: name: clone-scan-notify spec: tasks: - name: git-clone taskRef: name: git-clone - name: security-scans pipelineRef: name: security-scans - name: notification taskRef: name: notification

要点说明:

  • 父 Pipeline 中名为security-scans的PipelineTask通过pipelineRef指向集群中已存在的另一个 Pipeline 对象;在父PipelineRun被调度时,控制器会为该任务创建独立的子PipelineRun(见下文"底层实现")。
  • 在同一个PipelineTask中,taskRef、taskSpec、pipelineRef、pipelineSpec四者只能且必须恰好出现一个。校验逻辑位于 pipeline_validation.go:如果同时指定多个,会报expected exactly one, got multiple;如果一个都没指定,在 alpha 模式下会报ErrMissingOneOf(taskRef, taskSpec, pipelineRef, pipelineSpec)。
  • 此外,内联的pipelineSpec与disable-inline-spec特性联动:validateEnabledInlineSpec会在disable-inline-spec包含pipeline时禁止内联pipelineSpec(见 pipeline_validation.go)。

在PipelineTask中指定pipelineSpec

如果不想预先创建独立的 Pipeline 对象,也可以把子 Pipeline 的spec直接内嵌到父 Pipeline 的PipelineTask中。将上面的pipelineRef示例改写为pipelineSpec:

apiVersion: tekton.dev/v1 kind: Pipeline metadata: name: clone-scan-notify spec: tasks: - name: git-clone taskRef: name: git-clone - name: security-scans pipelineSpec: tasks: - name: scorecards taskRef: name: scorecards - name: codeql taskRef: name: codeql - name: notification taskRef: name: notification

pipelineRef与pipelineSpec在运行时殊途同归:控制器最终都会为这个PipelineTask生成一个子PipelineRun,区别仅在于子PipelineRun的 spec 来源——前者引用现成的 Pipeline 对象,后者直接内嵌完整的PipelineSpec。从源码看,二者的创建路径完全一致,见 pipelinerun.go:

childSpec := v1.PipelineRunSpec{ TaskRunTemplate: pr.Spec.TaskRunTemplate, Params: rpt.PipelineTask.Params, Workspaces: childWorkspaces, } if rpt.PipelineTask.PipelineRef != nil { childSpec.PipelineRef = rpt.PipelineTask.PipelineRef } else { childSpec.PipelineSpec = rpt.ResolvedPipeline.PipelineSpec }

指定 Parameters:向子 Pipeline 传参

嵌套 Pipeline 消费 Parameters 的方式与普通 Pipeline 中的 Task 完全一致:在PipelineTask上声明params,把父 Pipeline 的参数(或字面值)转发给子 Pipeline。以下示例把父 Pipeline 的repo参数同时传给git-clone任务和嵌套的security-scansPipeline:

apiVersion: tekton.dev/v1 kind: Pipeline metadata: name: clone-scan-notify spec: params: - name: repo value: $(params.repo) tasks: - name: git-clone params: - name: repo value: $(params.repo) taskRef: name: git-clone - name: security-scans params: - name: repo value: $(params.repo) pipelineRef: name: security-scans - name: notification taskRef: name: notification

实现层面,子PipelineRun的spec.params直接取自PipelineTask.Params(见 pipelinerun.go 中Params: rpt.PipelineTask.Params),再由子 PipelineRun 按常规参数替换逻辑解析。需要注意的是:params 是目前跨 Pipeline 传递数据(包括把父 Pipeline 的 results 输入给子 Pipeline)的主要通道——因为子 Pipeline 的 Results 尚不能回传给父级(详见 Known Limitations 中的"子 Pipeline 的 Results 不会向上传播")。

指定 Workspaces:把父工作区映射给子 Pipeline

引用子 Pipeline 的PipelineTask可以像普通 Task 一样,把父 Pipeline 的工作区绑定映射到子 Pipeline 声明的工作区。PipelineTask上声明的绑定会被传播给子PipelineRun,再由子PipelineRun转发给子 Pipeline 的工作区。完整示例:

apiVersion: tekton.dev/v1 kind: Pipeline metadata: name: security-scans spec: workspaces: - name: source tasks: - name: scorecards workspaces: - name: source taskRef: name: scorecards --- apiVersion: tekton.dev/v1 kind: Pipeline metadata: name: clone-scan-notify spec: workspaces: - name: shared-ws tasks: - name: git-clone workspaces: - name: output workspace: shared-ws taskRef: name: git-clone - name: security-scans runAfter: - git-clone workspaces: - name: source workspace: shared-ws pipelineRef: name: security-scans

上例中,父 Pipeline 声明了名为shared-ws的工作区;security-scans这个PipelineTask通过workspace: shared-ws把父工作区映射给子 Pipeline 声明的source工作区,并用runAfter: [git-clone]保证顺序——子 Pipeline 内的scorecards任务再通过自己的 workspace 绑定消费source。

底层解析逻辑在 pipelinerun.go 的getChildPipelineRunWorkspaces中实现:它把父PipelineRun的所有 workspace 绑定建成parentWorkspaces映射,然后对PipelineTask.Workspaces逐项解析——若ws.Workspace为空则默认使用同名绑定;PVC 与 VolumeClaimTemplate 类型的绑定还会记录父级 PVC 名,最终复用与 TaskRun 完全一致的taskWorkspaceByWorkspaceVolumeSource逻辑生成子PipelineRun的绑定。因此 TaskRun 工作区支持的 VolumeSource(PVC、VolumeClaimTemplate、ConfigMap/Secret/EmptyDir 等)在嵌套场景下同样适用。

底层实现:子 PipelineRun 的创建与循环检测

从 pipelinerun.go 的源码可以看到整个创建流程:

  1. 父PipelineRun的 reconciler 在调度阶段通过createChildPipelineRuns遍历rpt.ChildPipelineRunNames,逐个调用createChildPipelineRun。
  2. 若该PipelineTask使用pipelineRef,先执行detectPipelineRefCycle做循环引用检测(见下文)。
  3. 组装子PipelineRun:继承父PipelineRun的TaskRunTemplate;spec.params取自PipelineTask.Params;spec.workspaces由getChildPipelineRunWorkspaces解析;pipelineRef/pipelineSpec按前文逻辑二选一写入。
  4. 子PipelineRun通过OwnerReferences: []metav1.OwnerReference{*kmeta.NewControllerRef(pr)}被父PipelineRun拥有,同时带上继承自父级的 Labels/Annotations(并用子 Pipeline 的实际名称覆盖tekton.dev/pipeline标签,见 pipelinerun.go)。
  5. 最后通过PipelineRuns(pr.Namespace).Create(...)创建子对象,日志会输出Creating a new child (PIP) PipelineRun object ...。

循环引用检测:detectPipelineRefCycle(pipelinerun.go)从当前PipelineRun出发,沿ownerReferences链向上遍历,每一层读取tekton.dev/pipeline标签并与目标 Pipeline 名称比对;一旦在祖先链中发现相同名称,立即返回controller.NewPermanentError,错误信息形如:

detected cycle in pipeline-in-pipeline: pipeline "security-scans" is already running in ancestor chain ...

需要说明的是:该检测是 best-effort 的,且发生在子 PipelineRun 的 reconcile 阶段,而非父 Pipeline 提交时(详见 Known Limitations)。若在向上查找父PipelineRun时发生 lister 瞬时失败,错误会原样返回让控制器重试,避免误判为永久失败。

Known Limitations:当前 alpha 实现的已知限制

以下限制均为初始 alpha 实现的现状,预期在后续工作中逐步解决。

其他当前限制

  • when表达式不能引用子 Pipeline 的结果:父 Pipeline 中的when表达式无法引用使用了pipelineRef/pipelineSpec的PipelineTask的 results(这是下方"Results 不传播"缺口的直接推论)。
  • timeout与retries不生效:PipelineTask上配置的timeout与retries不会应用到子PipelineRun。子 PipelineRun 使用自己的默认超时,且每个父 reconcile 周期至多创建一次。
  • 父级timeouts不向下传播:父PipelineRun.Spec.Timeouts不会传播给子PipelineRun,子 PipelineRun 使用自身的默认值。
  • 循环检测是 best-effort 且在子 reconcile 时进行:如上文所述,它沿ownerReferences链并匹配tekton.dev/pipeline标签,因此循环是在出问题的子 PipelineRun 被 reconcile 时才被发现,而不是在父 Pipeline 提交时。
  • 非可选子工作区校验在子 PipelineRun 处发生:若父 Pipeline 遗漏了某个非可选子工作区的绑定,失败的是子 PipelineRun 而非父 PipelineRun(跟踪问题见 pipeline 仓库 issue #9924 的注释引用,原始追踪编号为 tektoncd/pipeline#9924)。源码中对应行为见 pipelinerun.go:getChildPipelineRunWorkspaces在父侧找不到绑定时会continue跳过,把校验责任留给子 PipelineRun。
  • 执行Status不对外暴露:使用pipelineRef/pipelineSpec的PipelineTask的 ExecutionStatus不会上抛,因此finally任务无法通过$(tasks.<pipelineTaskName>.status)判断子 Pipeline 是成功、失败还是被跳过。
  • 不支持matrix扇出:使用pipelineRef/pipelineSpec的PipelineTask不能与matrix组合以产生多个子PipelineRun。

子 Pipeline 的 Results 不会向上传播

子 Pipeline 产生的Results不会出现在父PipelineRun上:

  • 不会被聚合进父PipelineRun的status.results;
  • 无法被其他PipelineTask通过$(tasks.<task-name>.results.<result-name>)消费,也无法在父 Pipeline 的when表达式中使用。

为保证这一点,Pipeline 的 validating webhook 会在编写阶段拒绝任何指向使用了pipelineRef/pipelineSpec的PipelineTask的结果引用,报错形如:

result reference to pipelineTask "child" is not supported: referenced task uses pipelineRef or pipelineSpec and result propagation from child Pipelines is not yet implemented

该校验的实现位于 pipeline_validation.go 的validatePipelineRefResultReferencesDisallowed:它收集所有使用pipelineRef/pipelineSpec的PipelineTask名称,再对tasks与finally中所有PipelineTaskResultRefs逐一比对,命中即报错。函数注释解释了原因:reconciler 的convertToResultRefs路径从ResolvedPipelineTask.TaskRuns读取结果,而对子 Pipeline 任务该字段为空,若不加此护栏,这类引用会在控制器运行时引发 panic。

规避方案:在结果传播实现落地之前,请通过PipelineTask上的params把值传入子 Pipeline;父 Pipeline 自身的results继续由普通TaskRun产生。

小结与建议

Pipelines in Pipelines 为 Tekton 提供了"编排 Pipeline 的 Pipeline"能力:通过pipelineRef或pipelineSpec,可以把一段成熟的流水线(如安全扫描、合规检查)作为一个整体步骤嵌入更大的编排流程,实现 Pipeline 的复用与分层组合。当前 alpha 阶段的核心约束是子 Pipeline 的 Results 与执行状态无法回传、超时/重试/matrix 不支持,因此它最适合"子 Pipeline 只做副作用型工作(写入 workspace、产出 artifacts),父级流程用 params 单向驱动"的场景;需要跨层级传递结果时,应先用 params 传递输入、用 TaskRun 产出父级 results。

想继续深入,可以阅读以下仓库资源:

  • 官方文档:docs/pipelines-in-pipelines.md
  • 类型定义(PipelineTask.PipelineRef/PipelineSpec/Workspaces/Params):pkg/apis/pipeline/v1/pipeline_types.go
  • 校验逻辑(alpha 门控、ref-or-spec 互斥、结果引用护栏):pkg/apis/pipeline/v1/pipeline_validation.go
  • 控制器实现(子 PipelineRun 创建、工作区解析、循环检测):pkg/reconciler/pipelinerun/pipelinerun.go
  • Feature flag 默认配置:config/config-feature-flags.yaml
  • 云原生
  • CI/CD
  • DevOps
  • 后端

【免费下载链接】pipeline

A cloud-native Pipeline resource.

项目地址:https://gitcode.com/gh_mirrors/pipelin/pipeline
点击查看免费下载
上一篇:RubyMoney - Money-Rails:简化Rails应用中的货币处理
下一篇:easy-vibe 容器化部署实战:从 Dockerfile 多阶段构建到 Nginx 静态站点服务

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/25 2:11:48

微信桌面版实时消息捕获技术原理与实现

简介&#xff1a;这是一套面向开发者与安全研究人员的微信聊天记录实时监控与查询工具源码&#xff0c;聚焦于微信私聊及群聊内容的本地化捕获与结构化访问。资源提供完整的Python后端服务实现&#xff0c;含HTTP服务入口、聊天历史管理、数据源适配及日志配置等核心模块&#…

作者头像 李华
网站建设 2026/9/25 2:10:55

win10下yolox tensorrt模型部署

TensorRT系列之 Win10下yolov8 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov8 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov7 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov6 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov5 tensorrt模型加速部署…

作者头像 李华
网站建设 2026/9/25 2:09:05

【Python深度学习】LSTM网络使用时间分布层

在神经网络模型中,当涉及时间序列或序列数据时,通常需要将网络结构与时间步保持一致。时间分布层(TimeDistributed) 是 Keras 中的一个关键组件,尤其在与 LSTM 层组合时。TimeDistributed 层的作用在于允许模型的每个时间步对输入序列独立应用某一层,实现逐步处理的特性。…

作者头像 李华
网站建设 2026/9/25 2:08:43

新代系统6ta模拟器实操:从程序验证到宏程序调试的数控编程指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/25 2:08:35

TMS运输管理系统部署实战:从解压ZIP到数据库初始化与避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华