云原生CI/CDDevOps后端【免费下载链接】pipelineA 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 toalphafor 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示例改写为pipelineSpecapiVersion: 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: notificationpipelineRef与pipelineSpec在运行时殊途同归控制器最终都会为这个PipelineTask生成一个子PipelineRun区别仅在于子PipelineRun的 spec 来源——前者引用现成的 Pipeline 对象后者直接内嵌完整的PipelineSpec。从源码看二者的创建路径完全一致见 pipelinerun.gochildSpec : 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-scansPipelineapiVersion: 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 工作区支持的 VolumeSourcePVC、VolumeClaimTemplate、ConfigMap/Secret/EmptyDir 等在嵌套场景下同样适用。底层实现子 PipelineRun 的创建与循环检测从 pipelinerun.go 的源码可以看到整个创建流程父PipelineRun的 reconciler 在调度阶段通过createChildPipelineRuns遍历rpt.ChildPipelineRunNames逐个调用createChildPipelineRun。若该PipelineTask使用pipelineRef先执行detectPipelineRefCycle做循环引用检测见下文。组装子PipelineRun继承父PipelineRun的TaskRunTemplatespec.params取自PipelineTask.Paramsspec.workspaces由getChildPipelineRunWorkspaces解析pipelineRef/pipelineSpec按前文逻辑二选一写入。子PipelineRun通过OwnerReferences: []metav1.OwnerReference{*kmeta.NewControllerRef(pr)}被父PipelineRun拥有同时带上继承自父级的 Labels/Annotations并用子 Pipeline 的实际名称覆盖tekton.dev/pipeline标签见 pipelinerun.go。最后通过PipelineRuns(pr.Namespace).Create(...)创建子对象日志会输出Creating a new child (PIP) PipelineRun object ...。循环引用检测detectPipelineRefCyclepipelinerun.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.gogetChildPipelineRunWorkspaces在父侧找不到绑定时会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/Paramspkg/apis/pipeline/v1/pipeline_types.go校验逻辑alpha 门控、ref-or-spec 互斥、结果引用护栏pkg/apis/pipeline/v1/pipeline_validation.go控制器实现子 PipelineRun 创建、工作区解析、循环检测pkg/reconciler/pipelinerun/pipelinerun.goFeature flag 默认配置config/config-feature-flags.yaml赞分享云原生CI/CDDevOps后端【免费下载链接】pipelineA cloud-native Pipeline resource.项目地址https://gitcode.com/gh_mirrors/pipelin/pipeline点击查看免费下载相关推荐Tekton Pipelines实战构建多阶段Pipeline并触发PipelineRun的10个技巧Tekton Pipelines实战构建多阶段Pipeline并触发PipelineRun的10个技巧 Tekton Pipelines 是一个云原生 CI/云原生CI/CDDevOps后端Tekton Pipeline 深入指南Tekton Pipeline 深入指南 1. 项目介绍 Tekton Pipeline https://github.com/tektoncd/pipelin云原生CI/CDDevOps后端在 Tekton Pipeline 中运行 TestcontainersDocker-in-Docker Sidecar 完整配置指南在 Tekton Pipeline 中运行 TestcontainersDocker in Docker Sidecar 完整配置指南 Testcontain测试容器运行时上一篇RubyMoney - Money-Rails简化Rails应用中的货币处理下一篇easy-vibe 容器化部署实战从 Dockerfile 多阶段构建到 Nginx 静态站点服务创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考