PAC Resolver
适用于普通用户
本指南面向普通用户,用于使用 PAC resolver 从本地仓库、DevOps Hub catalog 以及远程 URL 自动解析并嵌入 tasks 和 pipelines。
本指南介绍如何使用 Pipelines as Code (PAC) resolver,从三个来源自动解析并嵌入 tasks 和 pipelines:在你的 repository 中定义的本地 tasks、由 artifacthub-shim 提供的远程 DevOps Hub catalog 中的 tasks,以及来自远程 Git repositories 或 HTTP URLs 的 tasks。
先决条件
- 已部署并运行 PAC component
- 已配置 Repository CR(参见 指南)
- 理解 Tekton PipelineRun 结构
关于 PAC Resolver
PAC resolver 会自动获取远程 tasks 和 pipelines,并将其嵌入到你的 PipelineRun 定义中。这样就无需在 pipeline 代码中手动定义 tasks 或使用 resolver 语法。
Task 嵌入的工作原理
当 PAC 从 DevOps Hub catalog 解析一个 task 时:
- PAC 从 Hub 获取 task 定义(YAML)
- PAC 将
taskRef 转换为 taskSpec,并将 task 定义以内联方式嵌入到你的 PipelineRun 中
- 嵌入的 task 会成为 PipelineRun 定义的一部分
- 该 task 不需要作为独立的 Task resource 存在于你的 cluster 中
这意味着你可以直接使用 catalog tasks,而无需手动复制它们的定义或在 cluster 中创建 Task resources。
支持的来源
- 本地 Tasks:在你的 Git repository 中定义的 Tasks(使用 taskSpec 或 resolver 语法)
- DevOps Hub catalog:来自集群内
artifacthub-shim catalog 的 tasks 和 pipelines
- 远程 URLs:来自远程 Git repositories 或 HTTP URLs 的 tasks 和 pipelines
PAC Resolver 的工作方式
理解 resolver 工作流有助于你排查问题并优化 pipeline 配置。
Resolver 工作流
当 PAC 处理带有 resolver 注解的 PipelineRun 时,会执行以下步骤:
- 事件触发:Git 事件(push、pull request 等)触发 PAC controller
- Pipeline 获取:PAC controller 从你的 Git repository 获取 PipelineRun 定义
- 注解检测:PAC controller 扫描注解中的 resolver 指令:
pipelinesascode.tekton.dev/task: "task-name"
pipelinesascode.tekton.dev/task-1: "task-name"
pipelinesascode.tekton.dev/pipeline: "pipeline-name"
- Task 解析:针对每个 task 注解:
- PAC controller 查询已配置的 Hub API。ACP DevOps 默认将其设为集群内的
artifacthub-shim Service。
- 获取 task 定义(YAML)
- 验证 task 结构
- Task 嵌入:PAC 将解析得到的 task 定义嵌入到 PipelineRun 中:
- PAC 将
taskRef 转换为 taskSpec,并将 task 定义以内联方式嵌入到每个 task 条目中
- 嵌入的 task 会成为 PipelineRun 定义的一部分,因此它不需要作为独立的 Task resource 存在于 cluster 中
- PipelineRun 创建:PAC 在 Kubernetes 中创建最终的、已嵌入 tasks 的 PipelineRun
- 执行:Tekton Pipeline controller 获取该 PipelineRun 并执行它
详细示例:逐步解析
让我们通过一个完整示例来追踪 resolver 的工作过程:
步骤 1:原始 PipelineRun 定义
你在 repository(.tekton/pipelinerun.yaml)中定义一个 PipelineRun:
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: my-pipeline
annotations:
pipelinesascode.tekton.dev/on-target-branch: "[refs/heads/main]"
pipelinesascode.tekton.dev/on-event: "[push]"
pipelinesascode.tekton.dev/task: "git-clone"
spec:
pipelineSpec:
tasks:
- name: fetch-code
taskRef:
name: git-clone
params:
- name: url
value: "https://github.com/tektoncd/catalog.git"
- name: revision
value: "main"
步骤 2:PAC Controller 处理注解
当发生 push 事件时,PAC controller 会:
-
从 Git 读取 PipelineRun:PAC 从 repository 中获取 .tekton/pipelinerun.yaml 文件
-
检测注解:PAC 扫描类似 pipelinesascode.tekton.dev/task: "git-clone" 的 task 注解
-
解析 task 名称和版本:
- 仅 task 名称(例如
"git-clone"):从 Hub 获取最新版本
- 带版本(例如
"git-clone:0.1"):获取指定版本
- 版本选择:
- 未指定版本 → PAC 向 Hub 查询最新稳定版本
- 已指定版本(格式:
task-name:version)→ PAC 获取该确切版本
- 版本格式遵循语义化版本号(例如
0.1、0.9、1.2.3)
-
查询 Hub API:
- Hub URL:默认为
http://artifacthub-shim-api.artifacthub-shim-system.svc.cluster.local
- Catalog 类型:默认为
artifacthub
- Catalog 名称:默认为
catalog
- 查询最新版本:PAC 向 Hub 查询可用的最新版本
- 查询特定版本:PAC 请求注解中指定的确切版本
- 示例查询:
- 最新:
"git-clone" → Hub 返回最新版本
- 特定版本:
"git-clone:0.1" → Hub 返回 0.1 版本
-
从 Hub 接收 task 定义:Hub 返回完整的 Task YAML:
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: git-clone
spec:
params:
- name: url
description: git url to clone
- name: revision
description: revision to checkout
steps:
- name: clone
image: gcr.io/tekton-releases/git-init
script: |
#!/bin/sh
git clone $(params.url) $(workspaces.output.path)
cd $(workspaces.output.path)
git checkout $(params.revision)
版本选择最佳实践:
- 生产环境:指定确切版本(例如
"git-clone:0.1"),以保证可复现性和稳定性
- 开发/测试:使用最新版本(不带版本后缀),以便自动获取新特性和 bug 修复
- 版本固定:在生产环境中始终固定到特定版本,以避免 Hub 更新带来的破坏性变更
- 版本更新:定期以受控方式审查并更新已固定的版本
步骤 3:PAC 将 Task 嵌入 PipelineRun
PAC 通过将 taskRef 转换为 taskSpec 并嵌入解析后的 task 定义来修改 PipelineRun:
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: my-pipeline
annotations:
pipelinesascode.tekton.dev/on-target-branch: "[refs/heads/main]"
pipelinesascode.tekton.dev/on-event: "[push]"
spec:
pipelineSpec:
tasks:
- name: fetch-code
# PAC converts taskRef to taskSpec and embeds the task definition
taskSpec:
params:
- name: url
description: git url to clone
- name: revision
description: revision to checkout
steps:
- name: clone
image: gcr.io/tekton-releases/git-init
script: |
#!/bin/sh
git clone $(params.url) $(workspaces.output.path)
cd $(workspaces.output.path)
git checkout $(params.revision)
params:
- name: url
value: "https://github.com/tektoncd/catalog.git"
- name: revision
value: "main"
步骤 4:在 Kubernetes 中创建 PipelineRun
PAC 在你的 cluster 中创建最终的 PipelineRun。你可以通过以下方式验证:
kubectl get pipelinerun my-pipeline -n <namespace> -o yaml
示例输出(节选,显示嵌入的 task):
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: my-pipeline
spec:
pipelineSpec:
tasks:
- name: fetch-code
# Task definition is embedded as taskSpec
taskSpec:
params:
- name: url
- name: revision
steps:
- name: clone
image: gcr.io/tekton-releases/git-init
script: |
#!/bin/sh
git clone $(params.url) $(workspaces.output.path)
params:
- name: url
value: "https://gitlab.com/user/repo"
- name: revision
value: "abc1234"
Resolver 时机
重要:Task 解析发生在 PipelineRun 创建到 Kubernetes 之前。这意味着:
- Tasks 在 pipeline 定义时解析,而不是在执行时解析
- 如果某个 task 无法被解析,PipelineRun 创建会失败
- 你可以通过检查 Kubernetes 中的 PipelineRun YAML 来验证 task 解析结果
- PAC 会缓存已解析的 tasks 以提升性能
验证 Task 解析
要验证 tasks 是否已正确解析:
-
检查 Kubernetes 中的 PipelineRun:
kubectl get pipelinerun <name> -n <namespace> -o yaml
查看各个 task 中是否存在带有 taskSpec 的嵌入式 task:
spec:
pipelineSpec:
tasks:
- name: fetch-code
taskSpec:
params:
- name: url
- name: revision
steps:
- name: clone
image: gcr.io/tekton-releases/git-init
script: |
#!/bin/sh
git clone $(params.url) $(workspaces.output.path)
params:
- name: url
value: "https://gitlab.com/user/repo"
- name: revision
value: "abc1234"
理解 Task 嵌入
PAC 通过在单个 task 内将 taskRef 转换为 taskSpec 来嵌入已解析的 tasks。该 task 定义会以内联方式嵌入为 PipelineRun 的一部分,遵循标准 Tekton 语法。
-
检查 PAC Controller 日志:
kubectl logs -n <pac-namespace> -l app=pipelines-as-code-controller --tail=100 | grep -i "task.*resolve" # Replace <pac-namespace> with your actual namespace (default: tekton-pipelines)
示例输出(显示 task 解析过程):
{"level":"info","ts":"2024-01-01T12:00:00Z","logger":"controller","msg":"Resolving task","task":"git-clone","source":"hub"}
{"level":"info","ts":"2024-01-01T12:00:01Z","logger":"controller","msg":"Task resolved successfully","task":"git-clone","version":"0.9"}
{"level":"info","ts":"2024-01-01T12:00:02Z","logger":"controller","msg":"Task embedded in PipelineRun","task":"git-clone","pipelineRun":"my-pipeline"}
-
验证每个 task 是否已嵌入:已解析的 task 不再具有 taskRef —— PAC 会将其替换为内联的 taskSpec,因此在成功时,读取 taskRef.name 的命令不会输出任何内容。请列出每个 pipeline task 以及其最终形式:
kubectl get pipelinerun <name> -n <namespace> -o json \
| jq -r '.spec.pipelineSpec.tasks[] | "\(.name)\t\(if .taskSpec then "embedded" else "unresolved taskRef: " + .taskRef.name end)"'
示例输出:
fetch-code embedded
lint embedded
如果某条记录仍显示 unresolved taskRef:,说明它没有被解析。请检查该 task 是否列在 pipelinesascode.tekton.dev/task 注解中,然后查看上面的 controller 日志。
-
检查 PipelineRun 是否创建成功:
kubectl get pipelinerun <name> -n <namespace> -o jsonpath='{.status.conditions[*].type}'
示例输出:
如果 task 解析失败,PipelineRun 可能不会被创建,或者会带有 Failed 条件和错误消息。
使用本地 Tasks
本地 tasks 是直接定义在你的 Git repository 中的 tasks。PAC 支持两种方式使用本地 tasks:
内联 Task 定义(taskSpec)
你可以在 PipelineRun 中使用 taskSpec 直接定义 tasks:
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: my-pipeline
annotations:
pipelinesascode.tekton.dev/on-target-branch: "[refs/heads/main]"
pipelinesascode.tekton.dev/on-event: "[push]"
spec:
pipelineSpec:
tasks:
- name: build
taskSpec:
steps:
- name: build
image: golang:1.21
script: |
#!/bin/sh
go build -o app ./cmd
- name: test
taskSpec:
steps:
- name: test
image: golang:1.21
script: |
#!/bin/sh
go test ./...
工作方式:
- 在 pipeline 的每个 task 内使用
taskSpec 以内联方式定义 tasks
- 无需外部解析 - tasks 本身就是 PipelineRun 定义的一部分
- 适用于简单的、仅面向 repository 的 tasks
引用 Repository 中的 Task 文件
你可以使用 PAC 注解,通过用于 repository 内 task 的特殊语法,引用存储在 repository 中的 task 文件。
重要:对于 repository 中的 tasks,请使用 pipelinesascode.tekton.dev/task 或 pipelinesascode.tekton.dev/task-<N> 注解格式。
Repository 结构:
.tekton/
├── pipelinerun.yaml
└── tasks/
├── build-task.yaml
└── test-task.yaml
使用 PAC 注解的 PipelineRun 定义:
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: my-pipeline
annotations:
pipelinesascode.tekton.dev/on-target-branch: "[refs/heads/main]"
pipelinesascode.tekton.dev/on-event: "[push]"
# Reference local tasks using relative paths
pipelinesascode.tekton.dev/task: ".tekton/tasks/build-task.yaml"
pipelinesascode.tekton.dev/task-1: ".tekton/tasks/test-task.yaml"
spec:
pipelineSpec:
tasks:
- name: build
taskRef:
name: build-task
- name: test
taskRef:
name: test-task
runAfter: [build]
工作方式:
- 当你在 task 注解中使用相对路径时,PAC 会自动解析并嵌入你 repository 中的 tasks
taskRef.name 中的 task 名称应与 YAML 文件中定义的 task 名称一致
- 这种方式比使用
resolver: git 语法更简单,也是 PAC 推荐的方法
何时使用本地 Tasks
在以下场景中使用本地 tasks:
- tasks 仅适用于你的项目,不适合共享
- 你需要完全控制 task 定义和版本
- tasks 会随代码库频繁变化
- 你希望通过版本控制将 tasks 和 pipelines 放在一起管理
使用远程 Task 注解
你可以使用 PAC 注解引用来自 DevOps Hub catalog 或远程 HTTP URLs 的远程 tasks。PAC 会自动获取这些 tasks 并将其嵌入到你的 PipelineRun 中。
来自 DevOps Hub 的远程 Tasks
引用 DevOps Hub 中的单个 task:
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: my-pipeline
annotations:
pipelinesascode.tekton.dev/on-target-branch: "[refs/heads/main]"
pipelinesascode.tekton.dev/on-event: "[push]"
pipelinesascode.tekton.dev/task: "git-clone"
spec:
pipelineSpec:
tasks:
- name: fetch-code
taskRef:
name: git-clone
params:
- name: url
value: "https://github.com/tektoncd/catalog.git"
- name: revision
value: "main"
工作方式:
- 注解
pipelinesascode.tekton.dev/task: "git-clone" 告诉 PAC 从已配置的 Hub catalog 中获取 git-clone task
- PAC 会自动将 task 定义嵌入到你的 PipelineRun 中
- 然后你可以使用
taskRef.name: git-clone 来引用它
来自 HTTP URLs 的远程 Tasks
你也可以引用来自远程 HTTP URLs 的 tasks:
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: my-pipeline
annotations:
pipelinesascode.tekton.dev/on-target-branch: "[refs/heads/main]"
pipelinesascode.tekton.dev/on-event: "[push]"
# Reference task from remote URL
pipelinesascode.tekton.dev/task: "https://raw.githubusercontent.com/tektoncd/catalog/main/task/git-clone/0.9/git-clone.yaml"
spec:
pipelineSpec:
tasks:
- name: fetch-code
taskRef:
name: git-clone
params:
- name: url
value: "https://github.com/tektoncd/catalog.git"
- name: revision
value: "main"
工作方式:
- PAC 从指定的 HTTP URL 获取 task 定义
- PAC 会自动将 task 嵌入到你的 PipelineRun 中
taskRef.name 中的 task 名称应与远程 YAML 文件中定义的 task 名称一致
多个 Task 注解
使用编号注解引用多个 tasks:
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: build-pipeline
annotations:
pipelinesascode.tekton.dev/on-target-branch: "[refs/heads/main]"
pipelinesascode.tekton.dev/on-event: "[push]"
pipelinesascode.tekton.dev/task: "git-clone"
pipelinesascode.tekton.dev/task-1: "golangci-lint"
pipelinesascode.tekton.dev/task-2: "buildah"
spec:
pipelineSpec:
tasks:
- name: fetch
taskRef:
name: git-clone
params:
- name: url
value: "https://github.com/tektoncd/catalog.git"
- name: revision
value: "main"
- name: lint
taskRef:
name: golangci-lint
runAfter: [fetch]
- name: build
taskRef:
name: buildah
runAfter: [lint]
Task 列表语法
你还可以使用方括号语法在单个注解中指定多个 tasks:
metadata:
annotations:
pipelinesascode.tekton.dev/task-1: "[golangci-lint, buildah]"
这等同于:
metadata:
annotations:
pipelinesascode.tekton.dev/task-1: "golangci-lint"
pipelinesascode.tekton.dev/task-2: "buildah"
Task 版本指定
默认情况下,PAC 会从 Hub 获取 task 的最新版本。若要指定特定版本,请使用 task-name:version 格式。
PAC 按名称解析 Hub tasks,并且可以选择使用 task-name:version 固定 task 版本。
最新版本(推荐用于开发):
metadata:
annotations:
pipelinesascode.tekton.dev/task: "git-clone"
特定版本(推荐用于生产):
metadata:
annotations:
pipelinesascode.tekton.dev/task: "git-clone:0.9"
带版本的多个 tasks:
metadata:
annotations:
pipelinesascode.tekton.dev/task: "git-clone:0.9"
pipelinesascode.tekton.dev/task-1: "golangci-lint:0.4"
pipelinesascode.tekton.dev/task-2: "buildah" # Uses latest
自定义 Hub URL
默认的 hub-url 指向集群内部的 artifacthub-shim Service(http://artifacthub-shim-api.artifacthub-shim-system.svc.cluster.local),通常无需配置。只有在 artifacthub-shim 部署在其他 namespace,或者你希望使用不同的 Hub instance 时,才需要显式设置它。在 TektonConfig CR 中进行配置:
apiVersion: operator.tekton.dev/v1alpha1
kind: TektonConfig
metadata:
name: config
spec:
platforms:
kubernetes:
pipelinesAsCode:
enable: true
settings:
# The address artifacthub-shim is installed at by default. Change only the
# namespace if it was deployed somewhere other than artifacthub-shim-system.
hub-url: "http://artifacthub-shim-api.artifacthub-shim-system.svc.cluster.local"
hub-catalog-type: "artifacthub"
hub-catalog-name: "catalog"
# Or for an external Artifact Hub instance
# hub-url: "https://artifacthub.io"
# hub-catalog-type: "artifacthub"
# Or for a Tekton Hub instance - the catalog type has to change with it
# hub-url: "https://api.hub.tekton.dev/v1"
# hub-catalog-type: "tekton"
注意:只有 PAC controller 需要访问 Hub URL。对于 Artifact Hub providers,不要追加 /api/v1;PAC 会在内部自动添加该路径。始终要将 hub-catalog-type 与 hub-url 一起设置:如果你只修改 URL,而不修改 hub-catalog-type,保留的 artifacthub 值不会改变,因此指向 Tekton Hub 时若不同时调整该项,PAC 会使用 Artifact Hub API 去查询那个 Hub。
使用远程 Pipeline 注解
使用场景有限
远程 pipeline 注解在实践中很少使用。大多数用户会使用 pipelineSpec 以内联方式定义 pipelines,而不是引用远程 pipelines。此部分仅为完整性而保留。
你也可以引用来自 DevOps Hub 的远程 pipelines,不过这比使用内联 pipeline 定义更少见:
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: my-pipeline
annotations:
pipelinesascode.tekton.dev/on-target-branch: "[refs/heads/main]"
pipelinesascode.tekton.dev/on-event: "[push]"
# Reference remote pipeline from DevOps Hub
pipelinesascode.tekton.dev/pipeline: "pipeline-name"
spec:
pipelineRef:
name: pipeline-name
params:
- name: image-url
value: "registry.example.com/myapp"
工作方式:
- 注解
pipelinesascode.tekton.dev/pipeline: "pipeline-name" 告诉 PAC 从已配置的 Hub catalog 中获取 pipeline。PAC 仅使用一个 hub-catalog-name 设置,因此 artifacthub-shim 会将 Pipeline fallback 从 catalog 保留到 catalog-pipelines。
- PAC 会自动嵌入 pipeline 定义
- 你可以使用
pipelineRef.name 来引用它
关于 catalog source 配置和 resource 编写,请参见 ArtifactHub Shim 目录。
注意:在大多数情况下,你应该在 repository 中使用 pipelineSpec 以内联方式定义 pipeline,而不是使用远程 pipeline。这样可以更好地进行版本控制,并提高对 pipeline 定义的可见性。
组合远程 Tasks 和 Pipelines
与 Resolver 语法的比较
PAC 注解提供了比 Tekton resolver 语法更简单的替代方案:
使用 PAC 注解(推荐)
metadata:
annotations:
pipelinesascode.tekton.dev/task: "git-clone"
spec:
pipelineSpec:
tasks:
- name: clone
taskRef:
name: git-clone
使用 Resolver 语法
spec:
pipelineSpec:
tasks:
- name: clone
taskRef:
resolver: hub
params:
- name: name
value: git-clone
- name: kind
value: task
PAC 注解的优势:
- 语法更简单
- 自动嵌入 task
- 无需指定 resolver 参数
- 可与 PAC 的 task 解析无缝配合
故障排查
找不到 Task
-
验证 task 名称:检查 DevOps Hub 中的 task 名称是否正确
-
检查 Hub URL:验证 hub URL 是否配置正确
-
查看 PAC 日志:
kubectl logs -n <pac-namespace> -l app=pipelines-as-code-controller --tail=100 | grep -i task
示例输出:
{"level":"info","ts":"2024-01-01T12:00:00Z","logger":"controller","msg":"Resolving task","task":"git-clone","source":"hub"}
{"level":"info","ts":"2024-01-01T12:00:01Z","logger":"controller","msg":"Task resolved successfully","task":"git-clone","version":"0.9"}
{"level":"info","ts":"2024-01-01T12:00:02Z","logger":"controller","msg":"Task embedded in PipelineRun","task":"git-clone","pipelineRun":"my-pipeline"}
Task 解析失败
-
检查网络连通性:确保 PAC controller 可以访问 artifacthub-shim
# Test Hub connectivity from PAC controller pod
kubectl exec -n <pac-namespace> \
$(kubectl get pod -n <pac-namespace> -l app=pipelines-as-code-controller -o jsonpath='{.items[0].metadata.name}') \
-- curl -I http://artifacthub-shim-api.artifacthub-shim-system.svc.cluster.local/api/v1/packages/tekton-task/catalog/git-clone
示例输出(如果可访问):
HTTP/1.1 200 OK
Content-Type: application/json
-
验证 Hub 配置:检查 PAC controller 实际接收到的 hub-url 值。pipelines-as-code ConfigMap 是权威来源——controller 读取的就是它。它位于 PAC namespace 中,即 TektonConfig.spec.targetNamespace;下面的命令使用默认的 tekton-pipelines,因此如果你的 cluster 使用的是其他 namespace,请将其替换,否则查询会失败,看起来就像该设置从未生效:
kubectl get configmap pipelines-as-code -n tekton-pipelines -o jsonpath='{.data.hub-url}'
示例输出:
http://artifacthub-shim-api.artifacthub-shim-system.svc.cluster.local
-
检查 task 版本:确保指定的版本确实存在
# Query artifacthub-shim for the latest package detail
curl http://artifacthub-shim-api.artifacthub-shim-system.svc.cluster.local/api/v1/packages/tekton-task/catalog/git-clone
示例输出(节选):
{
"id": 1,
"name": "git-clone",
"kind": "Task",
"latestVersion": {
"id": 1,
"version": "0.9"
},
"versions": [
{"version": "0.9"},
{"version": "0.8"},
{"version": "0.7"}
]
}
Task 未嵌入
- 验证注解语法:检查注解 key 和 value 的格式
- 检查 PipelineRun:确保
taskRef.name 与注解中的 task 名称一致
- 查看 PAC controller 日志,排查嵌入错误
下一步