PAC Resolver

适用于普通用户

本指南面向普通用户,介绍如何使用 PAC resolver 自动解析并嵌入来自本地仓库、Tekton Hub 和远程 URL 的 task 和 pipeline。

本指南说明如何使用 Pipelines as Code (PAC) resolver,从三个来源自动解析并嵌入 task 和 pipeline:仓库中定义的本地 task、来自 Tekton Hub 的远程 task,以及来自远程 Git 仓库或 HTTP URL 的 task。

前提条件

  • PAC component 已部署并正在运行
  • 已配置 Repository CR(参见 Guides
  • 了解 Tekton PipelineRun 结构

关于 PAC Resolver

PAC resolver 会自动获取远程 task 和 pipeline,并将其嵌入到你的 PipelineRun 定义中。这样就不需要在 pipeline 代码中手动定义 task,或者使用 resolver 语法。

Task 嵌入的工作原理

当 PAC 从 Tekton Hub 解析某个 task 时:

  1. PAC 从 Hub 获取 task 定义(YAML)
  2. PAC 将 taskRef 转换为 taskSpec,并将 task 定义以内联方式嵌入到你的 PipelineRun 中
  3. 嵌入的 task 成为 PipelineRun 定义的一部分
  4. 该 task 无需作为单独的 Task resource 存在于你的 cluster 中

这意味着你可以直接使用 Tekton Hub 中的 task,而无需手动复制其定义或在 cluster 中创建 Task resource。

支持的来源

  • 本地 Task:在你的 Git repository 中定义的 Task(使用 taskSpec 或 resolver 语法)
  • Tekton Hub:来自 Tekton Hub catalog 的 Task 和 pipeline
  • 远程 URL:来自远程 Git repository 或 HTTP URL 的 Task 和 pipeline

PAC Resolver 的工作方式

理解 resolver 工作流有助于你排查问题并优化 pipeline 配置。

Resolver 工作流

当 PAC 处理带有 resolver 注解的 PipelineRun 时,会按以下步骤执行:

  1. 事件触发:Git 事件(push、pull request 等)触发 PAC controller
  2. Pipeline 获取:PAC controller 从你的 Git repository 获取 PipelineRun 定义
  3. 注解检测:PAC controller 扫描注解中的 resolver 指令:
    • pipelinesascode.tekton.dev/task: "task-name"
    • pipelinesascode.tekton.dev/task-1: "task-name"
    • pipelinesascode.tekton.dev/pipeline: "pipeline-name"
  4. Task 解析:针对每个 task 注解:
    • PAC controller 查询 Tekton Hub API(或已配置的 hub URL)
    • 获取 task 定义(YAML)
    • 验证 task 结构
  5. Task 嵌入:PAC 将解析后的 task 定义嵌入到 PipelineRun 中:
    • PAC 将 taskRef 转换为 taskSpec,并将 task 定义以内联方式嵌入到每个 task 条目中
    • 嵌入的 task 成为 PipelineRun 定义的一部分,因此无需作为单独的 Task resource 存在于 cluster 中
  6. PipelineRun 创建:PAC 在 Kubernetes 中创建包含嵌入 task 的最终 PipelineRun
  7. 执行: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 会:

  1. 从 Git 读取 PipelineRun:PAC 从 repository 获取 .tekton/pipelinerun.yaml 文件

  2. 检测注解:PAC 扫描类似 pipelinesascode.tekton.dev/task: "git-clone" 的 task 注解

  3. 解析 task 名称和版本

    • 仅 task 名称(例如 "git-clone"):从 Hub 获取最新版本
    • 带版本(例如 "git-clone:0.1"):获取指定版本
    • 版本选择
      • 未指定版本 → PAC 查询 Hub 获取最新稳定版本
      • 已指定版本(格式:task-name:version)→ PAC 获取该精确版本
      • 版本格式遵循语义化版本(例如 0.10.91.2.3
  4. 查询 Hub API

    • Hub URL:默认指向集群内的 ArtifactHub Shim(http://artifacthub-shim-api.artifacthub-shim-system.svc.cluster.local);请参见 Custom Hub URL 以将其指向其他位置
    • 查询最新版本:PAC 查询 Hub 获取可用的最新版本
    • 查询指定版本:PAC 请求注解中指定的精确版本
    • 示例查询
      • Latest: "git-clone" → Hub 返回最新版本
      • Specific: "git-clone:0.1" → Hub 返回版本 0.1
  5. 从 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 更新带来的 breaking changes
  • 版本更新:定期以受控方式审查并更新已固定的版本

步骤 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 中创建之前。这意味着:

  • Task 在 pipeline 定义阶段解析,而不是在执行阶段解析
  • 如果某个 task 无法解析,PipelineRun 创建将失败
  • 你可以通过检查 Kubernetes 中的 PipelineRun YAML 来验证 task 解析结果
  • PAC 会缓存已解析的 task 以提升性能

验证 Task 解析

要验证 task 是否已正确解析:

  1. 检查 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 来嵌入已解析的 task。该 task 定义以内联方式嵌入为 PipelineRun 的一部分,并遵循标准 Tekton 语法。

  1. 检查 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"}
  1. 验证 task 引用是否正确

    # Check that taskRef.name matches the task name in annotations
    kubectl get pipelinerun <name> -n <namespace> -o jsonpath='{.spec.pipelineSpec.tasks[*].taskRef.name}'

示例输出:

git-clone golangci-lint
  1. 检查 PipelineRun 是否成功创建

    kubectl get pipelinerun <name> -n <namespace> -o jsonpath='{.status.conditions[*].type}'

示例输出:

Succeeded

如果 task 解析失败,PipelineRun 可能不会被创建,或者会带有 Failed condition 和错误消息。

使用本地 Task

本地 task 是直接定义在 Git repository 中的 task。PAC 支持两种使用本地 task 的方式:

内联 Task 定义(taskSpec)

你可以在 PipelineRun 中直接使用 taskSpec 定义 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]"
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 ./...

工作原理

  • Task 通过 taskSpec 以内联方式定义在 pipeline 的每个 task 中
  • 不需要外部解析——task 本身就是 PipelineRun 定义的一部分
  • 适用于简单、与 repository 紧密相关的 task

引用 Repository 中的 Task 文件

你可以使用 PAC 注解引用存储在 repository 中的 task 文件,并使用针对 repository 内 task 的特殊语法。

重要:对于 repository 中的 task,请使用 pipelinesascode.tekton.dev/taskpipelinesascode.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 中的 task
  • taskRef.name 中的 task 名称应与 YAML 文件中定义的 task 名称一致
  • 这种方式比使用 resolver: git 语法更简单,也是 PAC 推荐的方式

何时使用本地 Task

在以下情况下使用本地 task:

  • Task 是项目特有的,不适合共享
  • 你需要完全控制 task 定义和版本
  • Task 会随着代码库频繁变化
  • 你希望将 task 和 pipeline 一起纳入版本控制

使用远程 Task 注解

你可以使用 PAC 注解引用 Tekton Hub 或远程 HTTP URL 中的远程 task。PAC 会自动获取并将这些 task 嵌入到你的 PipelineRun 中。

来自 Tekton Hub 的远程 Task

引用 Tekton 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 从 Tekton Hub 获取 git-clone task
  • PAC 会自动将 task 定义嵌入到你的 PipelineRun 中
  • 然后你可以使用 taskRef.name: git-clone 来引用它

来自 HTTP URL 的远程 Task

你也可以引用远程 HTTP URL 中的 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]"
    # 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 注解

使用编号注解引用多个 task:

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 列表语法

你也可以使用方括号语法在单个注解中指定多个 task:

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 task,并且可以选择使用 task-name:version 固定 task 版本。

最新版本(推荐用于开发):

metadata:
  annotations:
    pipelinesascode.tekton.dev/task: "git-clone"

特定版本(推荐用于生产):

metadata:
  annotations:
    pipelinesascode.tekton.dev/task: "git-clone:0.9"

带版本的多个 task

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 (http://artifacthub-shim-api.artifacthub-shim-system.svc.cluster.local,并使用 hub-catalog-type: artifacthub)。除非你需要使用其他 Hub,否则请保持不设置。若要使用 其他 Hub,请在 OpenShiftPipelinesAsCode CR 中设置——并且必须同时设置 hub-catalog-type,因为如果你只设置 URL,已附带的 artifacthub 值仍会保留:

apiVersion: operator.tekton.dev/v1alpha1
kind: OpenShiftPipelinesAsCode
metadata:
  name: pipelines-as-code
spec:
  settings:
    # An ArtifactHub-compatible API: public artifacthub.io, or your own mirror
    hub-url: "https://artifacthub.io"
    hub-catalog-type: "artifacthub"

如果改为使用 Tekton Hub 实例,则 catalog type 也必须随之更改。此发行版不 会部署 Tekton Hub,因此没有可复制的集群内地址——请使用你自己的实例运行所在 的 namespace:

spec:
  settings:
    hub-url: "http://tekton-hub-api.<namespace-of-your-tekton-hub>:8000/v1"
    hub-catalog-type: "tekton"

注意:只有 PAC controller 需要访问 Hub URL。如果使用集群内部的 Hub,请确保 PAC controller 可以访问该 Hub service。

使用远程 Pipeline 注解

限制性使用场景

远程 pipeline 注解在实际中很少使用。大多数用户更倾向于使用 pipelineSpec 以内联方式定义 pipeline,而不是引用远程 pipeline。本节仅为完整性而包含。

你可以引用来自 Tekton Hub 的远程 pipeline,不过这比使用内联 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 Tekton 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 从 Tekton Hub 获取 pipeline
  • PAC 会自动嵌入 pipeline 定义
  • 你可以使用 pipelineRef.name 来引用它

注意:在大多数情况下,你应该在 repository 中使用 pipelineSpec 以内联方式定义 pipeline,而不是使用远程 pipeline。这样可以更好地管理版本并更清晰地查看 pipeline 定义。

组合远程 Task 和 Pipeline

与 Resolver 语法的对比

PAC 注解提供了一种比 Tekton resolver 语法更简单的替代方案:

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

  1. 验证 task 名称:检查 Tekton Hub 中的 task 名称是否正确

  2. 检查 Hub URL:确认 hub URL 配置正确

  3. 查看 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 解析失败

  1. 检查网络连通性:确保 PAC controller 能够访问 Tekton Hub

    # 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 https://api.hub.tekton.dev/v1/resource/task/git-clone

示例输出(如果可访问):

HTTP/1.1 200 OK
Content-Type: application/json
  1. 验证 Hub 配置:请读取渲染后的 pipelines-as-code ConfigMap,而不是 CR——在默认安装中,spec.settings.hub-url 为空,因为该值来自 operator 随附提供的 ConfigMap

    kubectl -n <pac-namespace> get configmap pipelines-as-code \
      -o jsonpath='{.data.hub-url}{"\n"}{.data.hub-catalog-type}{"\n"}'

示例输出:

http://artifacthub-shim-api.artifacthub-shim-system.svc.cluster.local
artifacthub
  1. 检查 task 版本:确保指定的版本存在

    # Query Tekton Hub for available versions
    curl https://api.hub.tekton.dev/v1/resource/task/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 未嵌入

  1. 验证注解语法:检查注解 key 和 value 的格式
  2. 检查 PipelineRun:确保 taskRef.name 与注解中的 task 名称一致
  3. 查看 PAC controller 日志,排查嵌入错误

后续步骤